From 29fd303425e989adaffdc7f7e1ffff248cff0372 Mon Sep 17 00:00:00 2001 From: agrgr Date: Sun, 20 Apr 2025 18:07:17 +0300 Subject: [PATCH 01/20] change API, return one Filter, leave only one ConditionVisitor and update it, other refactoring --- .../java/com/aerospike/dsl/DSLParser.java | 176 +++++- .../java/com/aerospike/dsl/DSLParserImpl.java | 73 ++- .../com/aerospike/dsl/ParsedExpression.java | 39 ++ .../NoApplicableFilterException.java | 8 + .../java/com/aerospike/dsl/index/Index.java | 23 + .../com/aerospike/dsl/model/AbstractPart.java | 9 +- .../java/com/aerospike/dsl/model/Expr.java | 29 +- .../com/aerospike/dsl/model/SIndexFilter.java | 22 - .../com/aerospike/dsl/model/WithOperand.java | 25 + .../aerospike/dsl/model/WithOperandsExpr.java | 16 + .../visitor/ExpressionConditionVisitor.java | 128 ++-- .../dsl/visitor/FilterConditionVisitor.java | 231 +++---- .../aerospike/dsl/visitor/VisitorUtils.java | 228 ++++++- .../ArithmeticExpressionsTests.java | 66 +- .../dsl/expression/BinExpressionsTests.java | 48 +- .../dsl/expression/CastingTests.java | 12 +- .../expression/ControlStructuresTests.java | 14 +- .../dsl/expression/ExplicitTypesTests.java | 138 ++--- .../dsl/expression/ImplicitTypesTests.java | 40 +- .../dsl/expression/ListExpressionsTests.java | 122 ++-- .../expression/LogicalExpressionsTests.java | 34 +- .../MapAndListExpressionsTests.java | 24 +- .../dsl/expression/MapExpressionsTests.java | 162 ++--- .../dsl/expression/RecordMetadataTests.java | 48 +- .../dsl/filter/ArithmeticFiltersTests.java | 569 ++++++++---------- .../aerospike/dsl/filter/BinFiltersTests.java | 124 ++-- .../dsl/filter/ExplicitTypesFiltersTests.java | 105 ++-- .../dsl/filter/ImplicitTypesFiltersTests.java | 17 +- .../com/aerospike/dsl/util/TestUtils.java | 22 +- 29 files changed, 1504 insertions(+), 1048 deletions(-) create mode 100644 src/main/java/com/aerospike/dsl/ParsedExpression.java create mode 100644 src/main/java/com/aerospike/dsl/exception/NoApplicableFilterException.java create mode 100644 src/main/java/com/aerospike/dsl/index/Index.java delete mode 100644 src/main/java/com/aerospike/dsl/model/SIndexFilter.java create mode 100644 src/main/java/com/aerospike/dsl/model/WithOperand.java create mode 100644 src/main/java/com/aerospike/dsl/model/WithOperandsExpr.java diff --git a/src/main/java/com/aerospike/dsl/DSLParser.java b/src/main/java/com/aerospike/dsl/DSLParser.java index a6d70ae..55aa61a 100644 --- a/src/main/java/com/aerospike/dsl/DSLParser.java +++ b/src/main/java/com/aerospike/dsl/DSLParser.java @@ -3,8 +3,9 @@ import com.aerospike.client.exp.Expression; import com.aerospike.client.query.Filter; import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.index.Index; -import java.util.List; +import java.util.Collection; /** * Contains API to convert dot separated String path into an Aerospike filter - @@ -25,6 +26,7 @@ public interface DSLParser { *

* Examples: * + * * * * @@ -47,9 +49,84 @@ public interface DSLParser { * * * - * + * + * * - * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Path element
$.binName Bin “binName”
{=bb} Map value “bb”
{='1'} Map value (String) “1” {='1'} Map value (String) “1”
{#1} Map rank 1
{#1} Map rank 1
[1] List index 1
[=1] List value 1
[#1] List rank 1
+ *
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
A nested element
$.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 ParsedExpression object + * @throws AerospikeDSLException in case of invalid syntax + */ + ParsedExpression parseDslExpression(String input); + + /** + * Parse String DSL path into Aerospike filter Expression. + *

+ * Examples: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * * * * @@ -59,12 +136,84 @@ public interface DSLParser { * * * + * *
Path element
$.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 rank 1
*
* + * + * + * + * + * + * + * * - * + * + * + * + * + * + * + * * + *
A nested element
$.mapBinName.k [mapBinName -> mapKey("a")]
$.mapBinName.a.aa.aaa [mapBinName -> mapKey("a") -> mapKey("aa") -> mapKey("aaa")]
$.binName [binName] $.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 + * @param namespace Namespace to use + * @return ParsedExpression object + * @throws AerospikeDSLException in case of or invalid syntax + */ + ParsedExpression parseDslExpression(String input, String namespace, Collection indexes); + + /** + * Parse String DSL path into Aerospike filter Expression. + *

+ * Examples: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Path element
$.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
+ *
+ * + * * * * @@ -82,17 +231,19 @@ public interface DSLParser { * mapKey("10")] * *
A nested element
$.mapBinName.k [mapBinName -> mapKey("a")]
- * @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 + * + * @param input String consisting of dot separated elements, typically bin name and optional context + * @return Expression for filtering records + * @throws AerospikeDSLException in case of or invalid syntax */ - Expression parseExpression(String input); + Expression parseFilterExpression(String input); /** * Parse String DSL path into Aerospike secondary index Filter. *

* Examples: * + * * * * @@ -103,9 +254,12 @@ public interface DSLParser { * * *
Filter for a bin
$.intBin1 == 10 Filter.equal("intBin1", 10)
$.stringBin1 == 'text' Filter.equal("stringBin1", "text")
- * @param input String consisting of dot separated elements, typically bin name and value + * + * @param input String consisting of dot separated elements, typically bin name and value + * @param namespace Namespace to use + * @param indexes List of indexes to choose from. Can be null * @return List of Filter objects - * @throws AerospikeDSLException in case of unsupported DSL String or invalid syntax + * @throws AerospikeDSLException in case of invalid syntax */ - List parseFilters(String input); + Filter parseFilter(String input, String namespace, Collection indexes); } diff --git a/src/main/java/com/aerospike/dsl/DSLParserImpl.java b/src/main/java/com/aerospike/dsl/DSLParserImpl.java index 8a9287b..762795b 100644 --- a/src/main/java/com/aerospike/dsl/DSLParserImpl.java +++ b/src/main/java/com/aerospike/dsl/DSLParserImpl.java @@ -5,46 +5,81 @@ import com.aerospike.client.query.Filter; import com.aerospike.dsl.annotation.Beta; import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.exception.NoApplicableFilterException; +import com.aerospike.dsl.index.Index; import com.aerospike.dsl.model.AbstractPart; 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; -import java.util.List; +import java.util.Collection; public class DSLParserImpl implements DSLParser { @Beta - public Expression parseExpression(String input) { + public ParsedExpression parseDslExpression(String input) { + ParseTree parseTree = getParseTree(input); + Filter sIndexFilter = parseFilter(parseTree, "test", null); + Expression expResult = Exp.build(parseFilterExp(parseTree)); + return new ParsedExpression(expResult, sIndexFilter); + } + + @Beta + public ParsedExpression parseDslExpression(String input, String namespace, Collection indexes) { + ParseTree parseTree = getParseTree(input); + Expression expResult = Exp.build(parseFilterExp(parseTree)); + Filter sIndexFilter = parseFilter(parseTree, namespace, indexes); + return new ParsedExpression(expResult, sIndexFilter); + } + + @Beta + public Expression parseFilterExpression(String input) { + Exp result = parseFilterExp(getParseTree(input)); + if (result == null) return null; + return Exp.build(result); + } + + @Beta + public Filter parseFilter(String input, String namespace, Collection indexes) { + return parseFilter(getParseTree(input), namespace, indexes); + } + + private ParseTree getParseTree(String input) { ConditionLexer lexer = new ConditionLexer(CharStreams.fromString(input)); ConditionParser parser = new ConditionParser(new CommonTokenStream(lexer)); - ParseTree tree = parser.parse(); + return parser.parse(); + } - ExpressionConditionVisitor visitor = new ExpressionConditionVisitor(); - AbstractPart abstractPart = visitor.visit(tree); + private Exp parseFilterExp(ParseTree parseTree) { + AbstractPart filterExprAbstractPart = new ExpressionConditionVisitor(true, false).visit(parseTree); // When we can't identify a specific case of syntax error, we throw a generic DSL syntax error instead of NPE - if (abstractPart == null) { + if (filterExprAbstractPart == null) { throw new AerospikeDSLException("Could not parse given input, wrong syntax"); } - 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(); + return filterExprAbstractPart.getExp(); + } - FilterConditionVisitor visitor = new FilterConditionVisitor(); - AbstractPart abstractPart = visitor.visit(tree); + private Filter parseFilter(ParseTree parseTree, String namespace, Collection indexes) { + boolean isEmptyList = false; + AbstractPart sIndexFiltersAbstractPart = null; + try { + sIndexFiltersAbstractPart = new ExpressionConditionVisitor(namespace, indexes, false, true).visit(parseTree); + } catch (NoApplicableFilterException e) { + isEmptyList = true; + } - if (abstractPart == null) { + // When we can't identify a specific case of syntax error, we throw a generic DSL syntax error instead of NPE + if (!isEmptyList && sIndexFiltersAbstractPart == null) { throw new AerospikeDSLException("Could not parse given input, wrong syntax"); } - return abstractPart.getSIndexFilter().getFilters(); + + Filter sIndexFilter = null; + if (sIndexFiltersAbstractPart != null && sIndexFiltersAbstractPart.getSIndexFilter() != null) { + sIndexFilter = sIndexFiltersAbstractPart.getSIndexFilter(); + } + return sIndexFilter; } } diff --git a/src/main/java/com/aerospike/dsl/ParsedExpression.java b/src/main/java/com/aerospike/dsl/ParsedExpression.java new file mode 100644 index 0000000..10e3e7a --- /dev/null +++ b/src/main/java/com/aerospike/dsl/ParsedExpression.java @@ -0,0 +1,39 @@ +package com.aerospike.dsl; + +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 lombok.AllArgsConstructor; + + +/** + * A class to store the results of DSL expression parsing: secondary index {@link Filter} or/and filter {@link Expression}. + *
+ * Expression exists as long as DSL input String is valid. + *
+ * List of Filters can be an empty if no suitable secondary index Filter was found. + */ +@AllArgsConstructor +@Beta +@SuppressWarnings("LombokGetterMayBeUsed") +public class ParsedExpression { + + Expression filterExpression; + Filter siFilter; + + /** + * @return filter {@link Expression}. Can be null + * @throws AerospikeDSLException If there was an error + */ + public Expression getFilterExpression() { + return filterExpression; + } + + /** + * @return secondary index {@link Filter}. Can be null + */ + public Filter getSIFilter() { + return siFilter; + } +} diff --git a/src/main/java/com/aerospike/dsl/exception/NoApplicableFilterException.java b/src/main/java/com/aerospike/dsl/exception/NoApplicableFilterException.java new file mode 100644 index 0000000..f3a64b7 --- /dev/null +++ b/src/main/java/com/aerospike/dsl/exception/NoApplicableFilterException.java @@ -0,0 +1,8 @@ +package com.aerospike.dsl.exception; + +public class NoApplicableFilterException extends RuntimeException { + + public NoApplicableFilterException(String description) { + super(description); + } +} diff --git a/src/main/java/com/aerospike/dsl/index/Index.java b/src/main/java/com/aerospike/dsl/index/Index.java new file mode 100644 index 0000000..2baee03 --- /dev/null +++ b/src/main/java/com/aerospike/dsl/index/Index.java @@ -0,0 +1,23 @@ +package com.aerospike.dsl.index; + +import com.aerospike.client.query.IndexType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * This class represents a secondary index created in the cluster. + */ +@Builder +@RequiredArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode +@Getter +public class Index { + + private final String bin; + private final IndexType indexType; + private int binValuesRatio; +} diff --git a/src/main/java/com/aerospike/dsl/model/AbstractPart.java b/src/main/java/com/aerospike/dsl/model/AbstractPart.java index 2499c79..fe01578 100644 --- a/src/main/java/com/aerospike/dsl/model/AbstractPart.java +++ b/src/main/java/com/aerospike/dsl/model/AbstractPart.java @@ -1,6 +1,7 @@ package com.aerospike.dsl.model; import com.aerospike.client.exp.Exp; +import com.aerospike.client.query.Filter; import lombok.Getter; import lombok.Setter; @@ -11,7 +12,7 @@ public abstract class AbstractPart { protected Exp.Type expType; protected PartType partType; protected Exp exp; - protected SIndexFilter sIndexFilter; + protected Filter sIndexFilter; protected AbstractPart(PartType partType) { this.partType = partType; @@ -23,9 +24,9 @@ protected AbstractPart(PartType partType, Exp exp) { this.exp = exp; } - protected AbstractPart(PartType partType, SIndexFilter filters) { + protected AbstractPart(PartType partType, Filter filter) { this.partType = partType; - this.sIndexFilter = filters; + this.sIndexFilter = filter; } public enum PartType { @@ -35,6 +36,8 @@ public enum PartType { STRING_OPERAND, LIST_OPERAND, MAP_OPERAND, + WITH_OPERAND, + WITH_OPERAND_EXPR, BASE_PATH, BIN_PART, LIST_PART, diff --git a/src/main/java/com/aerospike/dsl/model/Expr.java b/src/main/java/com/aerospike/dsl/model/Expr.java index ce68eeb..2308e40 100644 --- a/src/main/java/com/aerospike/dsl/model/Expr.java +++ b/src/main/java/com/aerospike/dsl/model/Expr.java @@ -14,10 +14,6 @@ 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; @@ -25,10 +21,33 @@ public Expr(AbstractPart left, AbstractPart right, ExprPartsOperation operationT this.operationType = operationType; } + public Expr(AbstractPart singleOperand, ExprPartsOperation operationType) { + super(PartType.EXPR); + this.left = singleOperand; // TODO: unary operator + this.operationType = operationType; + } + public enum ExprPartsOperation { ADD, SUB, DIV, - MUL + MUL, + MOD, + INT_XOR, + INT_NOT, + INT_AND, + INT_OR, + L_SHIFT, + R_SHIFT, + AND, + OR, + EQ, + NOTEQ, + GT, + GTEQ, + LT, + LTEQ, + WITH, + WHEN // TODO } } diff --git a/src/main/java/com/aerospike/dsl/model/SIndexFilter.java b/src/main/java/com/aerospike/dsl/model/SIndexFilter.java deleted file mode 100644 index 54a9c15..0000000 --- a/src/main/java/com/aerospike/dsl/model/SIndexFilter.java +++ /dev/null @@ -1,22 +0,0 @@ -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/WithOperand.java b/src/main/java/com/aerospike/dsl/model/WithOperand.java new file mode 100644 index 0000000..a91af51 --- /dev/null +++ b/src/main/java/com/aerospike/dsl/model/WithOperand.java @@ -0,0 +1,25 @@ +package com.aerospike.dsl.model; + +import lombok.Getter; + +@Getter +public class WithOperand extends AbstractPart { + + private final String string; + private final AbstractPart part; + private final boolean isLastPart; + + public WithOperand(AbstractPart part, String string) { + super(PartType.WITH_OPERAND); + this.string = string; + this.part = part; + this.isLastPart = false; + } + + public WithOperand(AbstractPart part, boolean isLastPart) { + super(PartType.WITH_OPERAND); + this.string = null; + this.part = part; + this.isLastPart = isLastPart; + } +} diff --git a/src/main/java/com/aerospike/dsl/model/WithOperandsExpr.java b/src/main/java/com/aerospike/dsl/model/WithOperandsExpr.java new file mode 100644 index 0000000..f3758e6 --- /dev/null +++ b/src/main/java/com/aerospike/dsl/model/WithOperandsExpr.java @@ -0,0 +1,16 @@ +package com.aerospike.dsl.model; + +import lombok.Getter; + +import java.util.List; + +@Getter +public class WithOperandsExpr extends AbstractPart { + + private final List operands; + + public WithOperandsExpr(List operands) { + super(PartType.WITH_OPERAND_EXPR); + this.operands = operands; + } +} diff --git a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java index 175e948..5ebe864 100644 --- a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java +++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java @@ -4,6 +4,7 @@ import com.aerospike.dsl.ConditionBaseVisitor; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.index.Index; import com.aerospike.dsl.model.*; import com.aerospike.dsl.model.cdt.list.ListIndex; import com.aerospike.dsl.model.cdt.list.ListIndexRange; @@ -20,25 +21,63 @@ import org.antlr.v4.runtime.tree.RuleNode; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.TreeMap; +import static com.aerospike.dsl.model.Expr.ExprPartsOperation.*; import static com.aerospike.dsl.util.ParsingUtils.unquote; import static com.aerospike.dsl.visitor.VisitorUtils.*; public class ExpressionConditionVisitor extends ConditionBaseVisitor { + private final boolean isFilterExp; + private final boolean isSIndexFilter; + private final String namespace; + private final Collection indexes; + + public ExpressionConditionVisitor() { + this.isFilterExp = false; + this.isSIndexFilter = false; + this.namespace = null; + this.indexes = null; + } + + public ExpressionConditionVisitor(boolean isFilterExp, boolean isSIndexFilter) { + this.isFilterExp = isFilterExp; + this.isSIndexFilter = isSIndexFilter; + this.namespace = null; + this.indexes = null; + } + + public ExpressionConditionVisitor(String namespace, Collection indexes) { + this.isFilterExp = false; + this.isSIndexFilter = false; + this.namespace = namespace; + this.indexes = indexes; + } + + public ExpressionConditionVisitor(String namespace, Collection indexes, boolean isFilterExp, + boolean isSIndexFilter) { + this.isFilterExp = isFilterExp; + this.isSIndexFilter = isSIndexFilter; + this.namespace = namespace; + this.indexes = indexes; + } + @Override public AbstractPart visitWithExpression(ConditionParser.WithExpressionContext ctx) { - List expressions = new ArrayList<>(); + List expressions = new ArrayList<>(); // iterate each definition for (ConditionParser.VariableDefinitionContext vdc : ctx.variableDefinition()) { - expressions.add(Exp.def(vdc.stringOperand().getText(), visit(vdc.expression()).getExp())); + AbstractPart part = visit(vdc.expression()); + WithOperand withOperand = new WithOperand(part, vdc.stringOperand().getText()); + expressions.add(withOperand); } // last expression is the action (described after "do") - expressions.add(visit(ctx.expression()).getExp()); - return new Expr(Exp.let(expressions.toArray(new Exp[0]))); + expressions.add(new WithOperand(visit(ctx.expression()), true)); + return new Expr(new WithOperandsExpr(expressions), Expr.ExprPartsOperation.WITH); } @Override @@ -64,7 +103,7 @@ public AbstractPart visitAndExpression(ConditionParser.AndExpressionContext ctx) Expr right = (Expr) visit(ctx.expression(1)); logicalSetBinsAsBooleanExpr(left, right); - return new Expr(Exp.and(left.getExp(), right.getExp())); + return new Expr(left, right, Expr.ExprPartsOperation.AND); } @Override @@ -73,7 +112,7 @@ public AbstractPart visitOrExpression(ConditionParser.OrExpressionContext ctx) { Expr right = (Expr) visit(ctx.expression(1)); logicalSetBinsAsBooleanExpr(left, right); - return new Expr(Exp.or(left.getExp(), right.getExp())); + return new Expr(left, right, Expr.ExprPartsOperation.OR); } @Override @@ -81,7 +120,7 @@ public AbstractPart visitNotExpression(ConditionParser.NotExpressionContext ctx) Expr expr = (Expr) visit(ctx.expression()); logicalSetBinAsBooleanExpr(expr); - return new Expr(Exp.not(expr.getExp())); + return new Expr(expr, Expr.ExprPartsOperation.LT); // TODO: unary operator } @Override @@ -105,8 +144,7 @@ public AbstractPart visitGreaterThanExpression(ConditionParser.GreaterThanExpres AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::gt); - return new Expr(exp); + return new Expr(left, right, Expr.ExprPartsOperation.GT); } @Override @@ -114,8 +152,7 @@ public AbstractPart visitGreaterThanOrEqualExpression(ConditionParser.GreaterTha AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::ge); - return new Expr(exp); + return new Expr(left, right, Expr.ExprPartsOperation.GTEQ); } @Override @@ -123,8 +160,7 @@ public AbstractPart visitLessThanExpression(ConditionParser.LessThanExpressionCo AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::lt); - return new Expr(exp); + return new Expr(left, right, Expr.ExprPartsOperation.LT); } @Override @@ -132,8 +168,7 @@ public AbstractPart visitLessThanOrEqualExpression(ConditionParser.LessThanOrEqu AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::le); - return new Expr(exp); + return new Expr(left, right, Expr.ExprPartsOperation.LTEQ); } @Override @@ -141,8 +176,7 @@ public AbstractPart visitEqualityExpression(ConditionParser.EqualityExpressionCo AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::eq); - return new Expr(exp); + return new Expr(left, right, Expr.ExprPartsOperation.EQ); } @Override @@ -150,8 +184,7 @@ public AbstractPart visitInequalityExpression(ConditionParser.InequalityExpressi AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::ne); - return new Expr(exp); + return new Expr(left, right, Expr.ExprPartsOperation.NOTEQ); } @Override @@ -159,8 +192,8 @@ public AbstractPart visitAddExpression(ConditionParser.AddExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::add); - return new Expr(exp); + if (!isFilterExp) validateNumericBinForFilter(left, right); + return new Expr(left, right, ADD); } @Override @@ -168,8 +201,8 @@ public AbstractPart visitSubExpression(ConditionParser.SubExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::sub); - return new Expr(exp); + if (!isFilterExp) validateNumericBinForFilter(left, right); + return new Expr(left, right, SUB); } @Override @@ -177,8 +210,8 @@ public AbstractPart visitMulExpression(ConditionParser.MulExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::mul); - return new Expr(exp); + if (!isFilterExp) validateNumericBinForFilter(left, right); + return new Expr(left, right, MUL); } @Override @@ -186,8 +219,8 @@ public AbstractPart visitDivExpression(ConditionParser.DivExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::div); - return new Expr(exp); + if (!isFilterExp) validateNumericBinForFilter(left, right); + return new Expr(left, right, DIV); } @Override @@ -195,8 +228,7 @@ public AbstractPart visitModExpression(ConditionParser.ModExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::mod); - return new Expr(exp); + return new Expr(left, right, MOD); } @Override @@ -204,8 +236,7 @@ public AbstractPart visitIntAndExpression(ConditionParser.IntAndExpressionContex AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::intAnd); - return new Expr(exp); + return new Expr(left, right, INT_AND); } @Override @@ -213,8 +244,7 @@ public AbstractPart visitIntOrExpression(ConditionParser.IntOrExpressionContext AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::intOr); - return new Expr(exp); + return new Expr(left, right, INT_OR); } @Override @@ -222,16 +252,14 @@ public AbstractPart visitIntXorExpression(ConditionParser.IntXorExpressionContex AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::intXor); - return new Expr(exp); + return new Expr(left, right, INT_XOR); } @Override public AbstractPart visitIntNotExpression(ConditionParser.IntNotExpressionContext ctx) { AbstractPart operand = visit(ctx.operand()); - Exp exp = getExpOrFail(operand, Exp::intNot); - return new Expr(exp); + return new Expr(operand, INT_NOT); } @Override @@ -239,8 +267,7 @@ public AbstractPart visitIntLShiftExpression(ConditionParser.IntLShiftExpression AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::lshift); - return new Expr(exp); + return new Expr(left, right, L_SHIFT); } @Override @@ -248,8 +275,7 @@ public AbstractPart visitIntRShiftExpression(ConditionParser.IntRShiftExpression AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - Exp exp = getExpOrFail(left, right, Exp::rshift); - return new Expr(exp); + return new Expr(left, right, R_SHIFT); } @Override @@ -520,4 +546,24 @@ public AbstractPart visitMapPart(ConditionParser.MapPartContext ctx) { protected AbstractPart aggregateResult(AbstractPart aggregate, AbstractPart nextResult) { return nextResult == null ? aggregate : nextResult; } + + @Override + public AbstractPart visitChildren(RuleNode node) { + AbstractPart result = defaultResult(); + int n = node.getChildCount(); + for (int i=0; i filters = Stream.concat( +// left.getSIndexFilter().getFilter().stream(), +// right.getSIndexFilter().getFilter().stream() +// ).toList(); +// return new Expr(new SIndexFilter(filters)); +// } +// +// @Override +// public AbstractPart visitOrExpression(ConditionParser.OrExpressionContext ctx) { +// Expr left = (Expr) visit(ctx.expression(0)); +// Expr right = (Expr) visit(ctx.expression(1)); +// +// logicalSetBinsAsBooleanExpr(left, right); +// Collection filters = Stream.concat( +// left.getSIndexFilter().getFilter().stream(), +// right.getSIndexFilter().getFilter().stream() +// ).toList(); +// return new Expr(new SIndexFilter(filters)); +// } +//} diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index 744416e..1484339 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -2,8 +2,11 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.query.Filter; +import com.aerospike.client.query.IndexType; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.exception.NoApplicableFilterException; +import com.aerospike.dsl.index.Index; import com.aerospike.dsl.model.AbstractPart; import com.aerospike.dsl.model.BinPart; import com.aerospike.dsl.model.Expr; @@ -14,19 +17,27 @@ import org.antlr.v4.runtime.misc.Pair; import org.antlr.v4.runtime.tree.ParseTree; +import java.util.ArrayList; import java.util.Base64; +import java.util.Collection; +import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.function.BinaryOperator; import java.util.function.UnaryOperator; +import java.util.stream.Stream; +import static com.aerospike.dsl.model.AbstractPart.PartType.*; 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 { + Map expTypeToIndexType = Map.of(Exp.Type.INT, IndexType.NUMERIC, + Exp.Type.STRING, IndexType.STRING); + protected enum FilterOperationType { GT, GTEQ, @@ -120,10 +131,10 @@ static Exp getExpOrFail(AbstractPart left, AbstractPart right, BinaryOperator getLimitsForDivision(long left, long right, FilterOperationType type, - ArithmeticTermType termType) { + private static Pair getLimitsForDivisionForFilter(long left, long right, FilterOperationType type, + ArithmeticTermType termType) { // Prevent division by zero if (right == 0) { - throw new AerospikeDSLException("Cannot divide by zero"); + throw new NoApplicableFilterException("Cannot divide by zero"); } return switch (termType) { @@ -521,7 +532,7 @@ private static Filter getFilter(BinPart bin, AbstractPart operand, FilterOperati } case STRING_OPERAND -> { - if (type != EQ) throw new AerospikeDSLException("Operand type not supported"); + if (type != FilterOperationType.EQ) throw new NoApplicableFilterException("Operand type not supported"); if (bin.getExpType() != null && bin.getExpType().equals(Exp.Type.BLOB)) { @@ -537,7 +548,7 @@ private static Filter getFilter(BinPart bin, AbstractPart operand, FilterOperati } } default -> - throw new AerospikeDSLException("Operand type not supported: %s".formatted(operand.getPartType())); + throw new NoApplicableFilterException("Operand type not supported: %s".formatted(operand.getPartType())); }; } @@ -559,17 +570,17 @@ private static Filter applyFilterOperator(String binName, IntOperand leftOperand default -> throw new IllegalStateException("Unexpected term type: " + termType); }; } else if (operationType == DIV) { - Pair valueForDiv = getLimitsForDivision(leftValue, rightValue, type, termType); + Pair valueForDiv = getLimitsForDivisionForFilter(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"); + throw new NoApplicableFilterException("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"); + if (leftValue == 0) throw new NoApplicableFilterException("Cannot divide by zero"); type = invertType(type); } float val = (float) rightValue / leftValue; @@ -577,7 +588,6 @@ private static Filter applyFilterOperator(String binName, IntOperand leftOperand } else { throw new UnsupportedOperationException("Not supported"); } - return getFilterForArithmeticOrFail(binName, value, type); } @@ -589,7 +599,8 @@ private static Filter getFilterForArithmeticOrFail(String binName, float 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"); + default -> + throw new NoApplicableFilterException("The operation is not supported by secondary index filter"); }; } @@ -619,11 +630,178 @@ private static long getClosestLongToTheRight(float value) { private FilterOperationType invertType(FilterOperationType type) { return switch (type) { - case GT -> LT; - case GTEQ -> LTEQ; - case LT -> GT; - case LTEQ -> GTEQ; + case GT -> FilterOperationType.LT; + case GTEQ -> FilterOperationType.LTEQ; + case LT -> FilterOperationType.GT; + case LTEQ -> FilterOperationType.GTEQ; default -> type; }; } + + AbstractPart buildExpr(Expr expr, String namespace, Collection indexes, boolean isFilterExp) { + AbstractPart left = expr.getLeft(); + AbstractPart right = expr.getRight(); + Expr.ExprPartsOperation opType = expr.getOperationType(); + Exp exp = null; + try { + if (!isFilterExp) { + expr.setSIndexFilter(getFilter(expr, namespace, indexes)); + } + } catch (NoApplicableFilterException e) { + // TODO: add cases with both Filter and Exp needed + } + if (isFilterExp) { + processFilterExpressions(left, right); + exp = getExpOrFail(left, right, getExpOperator(opType)); + } + expr.setExp(exp); + return expr; + } + + private static Filter getFilter(Expr expr, String namespace, Collection indexes) { + List exprs = getExprs(expr); + Expr chosenExpr = chooseFilter(exprs, namespace, indexes); + return chosenExpr == null ? null + : getFilterOrFail(chosenExpr.getLeft(), + chosenExpr.getRight(), + getFilterOperation(chosenExpr.getOperationType()) + ); + } + + private static Expr chooseFilter(List exprs, String namespace, Collection indexes) { + if (exprs.size() == 1) return exprs.get(0); + if (exprs.size() > 1 && (indexes == null || indexes.isEmpty())) return null; + + Expr resultExpr = null; + int maxRatio = Integer.MIN_VALUE; + + for (Expr expr : exprs) { + BinPart binPart = getBinPart(expr); + for (Index index : indexes) { + if (binPart.getBinName().equals(index.getBin()) + && expTypeToIndexType.get(binPart.getExpType()) == index.getIndexType()) { + if (index.getBinValuesRatio() > maxRatio) { + maxRatio = index.getBinValuesRatio(); + resultExpr = expr; + } + break; // Assuming one Index corresponds to one Expr based on the criteria + } + } + } + + return resultExpr; + } + + private static BinPart getBinPart(Expr expr) { + BinPart result = null; + if (expr.getOperationType() == AND || expr.getOperationType() == OR) { + Expr leftExpr = (Expr) expr.getLeft(); + if (leftExpr.getLeft() != null && leftExpr.getLeft().getPartType() == EXPR) { + result = getBinPart(leftExpr); + if (result != null) return result; + } + + if (expr.getRight() != null && expr.getRight().getPartType() == EXPR) { + Expr rightExpr = (Expr) expr.getRight(); + if (rightExpr.getRight() != null && rightExpr.getRight().getPartType() == EXPR) { + result = getBinPart(rightExpr); + if (result != null) return result; + } + } + } else { + if (expr.getLeft() != null && expr.getLeft().getPartType() == BIN_PART) { + return (BinPart) expr.getLeft(); + } + + if (expr.getRight() != null && expr.getRight().getPartType() == BIN_PART) { + return (BinPart) expr.getRight(); + } + } + return result; + } + + private static List getExprs(Expr expr) { + List results = new ArrayList<>(); + if (expr.getOperationType() == AND) { + if (expr.getLeft() != null && expr.getLeft().getPartType() == EXPR) { + Expr leftExpr = (Expr) expr.getLeft(); + if (leftExpr.getOperationType() == AND || leftExpr.getOperationType() == OR) { + Stream stream = getExprs(leftExpr).stream(); + results = Stream.concat(results.stream(), stream).toList(); + } else { + Stream stream = Stream.of(leftExpr); + results = Stream.concat(results.stream(), stream).toList(); + } + } + + if (expr.getRight() != null && expr.getRight().getPartType() == EXPR) { + Expr rightExpr = (Expr) expr.getRight(); + if (rightExpr.getOperationType() == AND || rightExpr.getOperationType() == OR) { + Stream stream = getExprs(rightExpr).stream(); + results = Stream.concat(results.stream(), stream).toList(); + } else { + Stream stream = Stream.of(rightExpr); + results = Stream.concat(results.stream(), stream).toList(); + } + } + } else { + return List.of(expr); + } + return results; + } + + private void processFilterExpressions(AbstractPart left, AbstractPart right) { + // Process left Expr + if (left != null && left.getPartType() == EXPR) { + Expr leftExpr = (Expr) left; + Exp exp = getExpOrFail(leftExpr.getLeft(), leftExpr.getRight(), + getExpOperator(leftExpr.getOperationType())); + left.setExp(exp); + } + + // Process right Expr + if (right != null && right.getPartType() == EXPR) { + Expr rightExpr = (Expr) right; + Exp exp = getExpOrFail(rightExpr.getLeft(), rightExpr.getRight(), + getExpOperator(rightExpr.getOperationType())); + right.setExp(exp); + } + } + + private static FilterOperationType getFilterOperation(Expr.ExprPartsOperation exprPartsOperation) { + return switch (exprPartsOperation) { + case GT -> FilterOperationType.GT; + case GTEQ -> FilterOperationType.GTEQ; + case LT -> FilterOperationType.LT; + case LTEQ -> FilterOperationType.LTEQ; + case EQ -> FilterOperationType.EQ; + case NOTEQ -> FilterOperationType.NOTEQ; + default -> throw new NoApplicableFilterException("ExprPartsOperation has no matching FilterOperationType"); + }; + } + + private static BinaryOperator getExpOperator(Expr.ExprPartsOperation exprPartsOperation) { + return switch (exprPartsOperation) { + case ADD -> Exp::add; + case SUB -> Exp::sub; + case MUL -> Exp::mul; + case DIV -> Exp::div; + case MOD -> Exp::mod; + case INT_XOR -> Exp::intXor; +// case INT_NOT -> Exp::intNot; // TODO: unary operator + case L_SHIFT -> Exp::lshift; + case R_SHIFT -> Exp::rshift; + case INT_AND -> Exp::intAnd; + case INT_OR -> Exp::intOr; + case AND -> Exp::and; + case OR -> Exp::or; + case EQ -> Exp::eq; + case NOTEQ -> Exp::ne; + case LT -> Exp::lt; + case LTEQ -> Exp::le; + case GT -> Exp::gt; + case GTEQ -> Exp::ge; + default -> throw new NoApplicableFilterException("ExprPartsOperation has no matching BinaryOperator"); + }; + } } diff --git a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java index 7876e58..1cd4a5e 100644 --- a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java @@ -2,122 +2,124 @@ import com.aerospike.client.exp.Exp; import com.aerospike.dsl.exception.AerospikeDSLException; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import static com.aerospike.dsl.util.TestUtils.parseExpression; -import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseFilterExp; +import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class ArithmeticExpressionsTests { @Test void add() { - parseExpressionAndCompare("($.apples + $.bananas) > 10", + parseFilterExpAndCompare("($.apples + $.bananas) > 10", Exp.gt(Exp.add(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseExpressionAndCompare("($.apples + 5) > 10", + parseFilterExpAndCompare("($.apples + 5) > 10", Exp.gt(Exp.add(Exp.intBin("apples"), Exp.val(5)), Exp.val(10))); - parseExpressionAndCompare("(5 + $.bananas) > 10", + parseFilterExpAndCompare("(5 + $.bananas) > 10", Exp.gt(Exp.add(Exp.val(5), Exp.intBin("bananas")), Exp.val(10))); - parseExpressionAndCompare("(5.2 + $.bananas) > 10.2", + parseFilterExpAndCompare("(5.2 + $.bananas) > 10.2", Exp.gt(Exp.add(Exp.val(5.2), Exp.floatBin("bananas")), Exp.val(10.2))); } @Test void sub() { - parseExpressionAndCompare("($.apples - $.bananas) == 10", + parseFilterExpAndCompare("($.apples - $.bananas) == 10", Exp.eq(Exp.sub(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseExpressionAndCompare("($.apples - 5) == 10", + parseFilterExpAndCompare("($.apples - 5) == 10", Exp.eq(Exp.sub(Exp.intBin("apples"), Exp.val(5)), Exp.val(10))); - parseExpressionAndCompare("(15 - $.bananas) == 10", + parseFilterExpAndCompare("(15 - $.bananas) == 10", Exp.eq(Exp.sub(Exp.val(15), Exp.intBin("bananas")), Exp.val(10))); } @Test void mul() { - parseExpressionAndCompare("($.apples * $.bananas) != 10", + parseFilterExpAndCompare("($.apples * $.bananas) != 10", Exp.ne(Exp.mul(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseExpressionAndCompare("($.apples * 7) != 10", + parseFilterExpAndCompare("($.apples * 7) != 10", Exp.ne(Exp.mul(Exp.intBin("apples"), Exp.val(7)), Exp.val(10))); - parseExpressionAndCompare("(3 * $.bananas) != 10", + parseFilterExpAndCompare("(3 * $.bananas) != 10", Exp.ne(Exp.mul(Exp.val(3), Exp.intBin("bananas")), Exp.val(10))); } @Test void div() { - parseExpressionAndCompare("($.apples / $.bananas) <= 10", + parseFilterExpAndCompare("($.apples / $.bananas) <= 10", Exp.le(Exp.div(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseExpressionAndCompare("($.apples / 5) <= 10", + parseFilterExpAndCompare("($.apples / 5) <= 10", Exp.le(Exp.div(Exp.intBin("apples"), Exp.val(5)), Exp.val(10))); - parseExpressionAndCompare("(33 / $.bananas) <= 10", + parseFilterExpAndCompare("(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 - parseExpressionAndCompare("($.apples / 0) <= 10", + parseFilterExpAndCompare("($.apples / 0) <= 10", Exp.le(Exp.div(Exp.intBin("apples"), Exp.val(0)), Exp.val(10))); } @Test void mod() { - parseExpressionAndCompare("($.apples % $.bananas) != 10", + parseFilterExpAndCompare("($.apples % $.bananas) != 10", Exp.ne(Exp.mod(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseExpressionAndCompare("($.apples % 7) != 10", + parseFilterExpAndCompare("($.apples % 7) != 10", Exp.ne(Exp.mod(Exp.intBin("apples"), Exp.val(7)), Exp.val(10))); - parseExpressionAndCompare("(3 % $.bananas) != 10", + parseFilterExpAndCompare("(3 % $.bananas) != 10", Exp.ne(Exp.mod(Exp.val(3), Exp.intBin("bananas")), Exp.val(10))); } @Test void intAnd() { - parseExpressionAndCompare("($.apples & $.bananas) != 10", + parseFilterExpAndCompare("($.apples & $.bananas) != 10", Exp.ne(Exp.intAnd(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseExpressionAndCompare("($.apples & 7) != 10", + parseFilterExpAndCompare("($.apples & 7) != 10", Exp.ne(Exp.intAnd(Exp.intBin("apples"), Exp.val(7)), Exp.val(10))); - parseExpressionAndCompare("(3 & $.bananas) != 10", + parseFilterExpAndCompare("(3 & $.bananas) != 10", Exp.ne(Exp.intAnd(Exp.val(3), Exp.intBin("bananas")), Exp.val(10))); } @Test void intOr() { - parseExpressionAndCompare("($.apples | $.bananas) != 10", + parseFilterExpAndCompare("($.apples | $.bananas) != 10", Exp.ne(Exp.intOr(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseExpressionAndCompare("($.apples | 7) != 10", + parseFilterExpAndCompare("($.apples | 7) != 10", Exp.ne(Exp.intOr(Exp.intBin("apples"), Exp.val(7)), Exp.val(10))); - parseExpressionAndCompare("(3 | $.bananas) != 10", + parseFilterExpAndCompare("(3 | $.bananas) != 10", Exp.ne(Exp.intOr(Exp.val(3), Exp.intBin("bananas")), Exp.val(10))); } @Test void intXor() { - parseExpressionAndCompare("($.apples ^ $.bananas) != 10", + parseFilterExpAndCompare("($.apples ^ $.bananas) != 10", Exp.ne(Exp.intXor(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseExpressionAndCompare("($.apples ^ 7) != 10", + parseFilterExpAndCompare("($.apples ^ 7) != 10", Exp.ne(Exp.intXor(Exp.intBin("apples"), Exp.val(7)), Exp.val(10))); - parseExpressionAndCompare("(3 ^ $.bananas) != 10", + parseFilterExpAndCompare("(3 ^ $.bananas) != 10", Exp.ne(Exp.intXor(Exp.val(3), Exp.intBin("bananas")), Exp.val(10))); } + @Disabled // TODO: unary operator @Test void intNot() { - parseExpressionAndCompare("(~$.apples) != 10", + parseFilterExpAndCompare("(~$.apples) != 10", Exp.ne(Exp.intNot(Exp.intBin("apples")), Exp.val(10))); } @Test void intLShift() { - parseExpressionAndCompare("$.visits << 1", + parseFilterExpAndCompare("$.visits << 1", Exp.lshift(Exp.intBin("visits"), Exp.val(1))); } @Test void intRShift() { - parseExpressionAndCompare("(($.flags >> 6) & 1) == 1", + parseFilterExpAndCompare("(($.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(() -> parseExpression("($.apples.get(type: STRING) + 5) > 10")) + assertThatThrownBy(() -> parseFilterExp("($.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 index eb0d85a..f497ddb 100644 --- a/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java @@ -4,61 +4,61 @@ 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 com.aerospike.dsl.util.TestUtils.parseFilterExp; +import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; 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"))); + parseFilterExpAndCompare("$.intBin1 > 100", Exp.gt(Exp.intBin("intBin1"), Exp.val(100))); + parseFilterExpAndCompare("$.stringBin1 > 'text'", Exp.gt(Exp.stringBin("stringBin1"), Exp.val("text"))); + parseFilterExpAndCompare("$.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"))); + parseFilterExpAndCompare("100 < $.intBin1", Exp.lt(Exp.val(100), Exp.intBin("intBin1"))); + parseFilterExpAndCompare("'text' < $.stringBin1", Exp.lt(Exp.val("text"), Exp.stringBin("stringBin1"))); + parseFilterExpAndCompare("\"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"))); + parseFilterExpAndCompare("$.intBin1 >= 100", Exp.ge(Exp.intBin("intBin1"), Exp.val(100))); + parseFilterExpAndCompare("$.stringBin1 >= 'text'", Exp.ge(Exp.stringBin("stringBin1"), Exp.val("text"))); + parseFilterExpAndCompare("$.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"))); + parseFilterExpAndCompare("$.intBin1 < 100", Exp.lt(Exp.intBin("intBin1"), Exp.val(100))); + parseFilterExpAndCompare("$.stringBin1 < 'text'", Exp.lt(Exp.stringBin("stringBin1"), Exp.val("text"))); + parseFilterExpAndCompare("$.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"))); + parseFilterExpAndCompare("$.intBin1 <= 100", Exp.le(Exp.intBin("intBin1"), Exp.val(100))); + parseFilterExpAndCompare("$.stringBin1 <= 'text'", Exp.le(Exp.stringBin("stringBin1"), Exp.val("text"))); + parseFilterExpAndCompare("$.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"))); + parseFilterExpAndCompare("$.intBin1 == 100", Exp.eq(Exp.intBin("intBin1"), Exp.val(100))); + parseFilterExpAndCompare("$.strBin == \"yes\"", Exp.eq(Exp.stringBin("strBin"), Exp.val("yes"))); + parseFilterExpAndCompare("$.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"))); + parseFilterExpAndCompare("$.intBin1 != 100", Exp.ne(Exp.intBin("intBin1"), Exp.val(100))); + parseFilterExpAndCompare("$.strBin != \"yes\"", Exp.ne(Exp.stringBin("strBin"), Exp.val("yes"))); + parseFilterExpAndCompare("$.strBin != 'yes'", Exp.ne(Exp.stringBin("strBin"), Exp.val("yes"))); } @Test void negativeStringBinEquals() { - assertThatThrownBy(() -> parseExpression("$.strBin == yes")) + assertThatThrownBy(() -> parseFilterExp("$.strBin == yes")) .isInstanceOf(AerospikeDSLException.class) .hasMessage("Unable to parse right operand"); } diff --git a/src/test/java/com/aerospike/dsl/expression/CastingTests.java b/src/test/java/com/aerospike/dsl/expression/CastingTests.java index c398386..97cb5d3 100644 --- a/src/test/java/com/aerospike/dsl/expression/CastingTests.java +++ b/src/test/java/com/aerospike/dsl/expression/CastingTests.java @@ -4,8 +4,8 @@ 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 com.aerospike.dsl.util.TestUtils.parseFilterExp; +import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; 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 - parseExpressionAndCompare("$.intBin1 > $.floatBin1.asInt()", expectedExp); - parseExpressionAndCompare("$.intBin1.get(type: INT) > $.floatBin1.asInt()", expectedExp); + parseFilterExpAndCompare("$.intBin1 > $.floatBin1.asInt()", expectedExp); + parseFilterExpAndCompare("$.intBin1.get(type: INT) > $.floatBin1.asInt()", expectedExp); } @Test void intToFloatComparison() { - parseExpressionAndCompare("$.intBin1.get(type: INT) > $.intBin2.asFloat()", + parseFilterExpAndCompare("$.intBin1.get(type: INT) > $.intBin2.asFloat()", Exp.gt(Exp.intBin("intBin1"), Exp.floatBin("intBin2"))); } @Test void negativeInvalidTypesComparison() { - assertThatThrownBy(() -> parseExpression("$.stringBin1.get(type: STRING) > $.intBin2.asFloat()")) + assertThatThrownBy(() -> parseFilterExp("$.stringBin1.get(type: STRING) > $.intBin2.asFloat()")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Cannot compare STRING to FLOAT"); } diff --git a/src/test/java/com/aerospike/dsl/expression/ControlStructuresTests.java b/src/test/java/com/aerospike/dsl/expression/ControlStructuresTests.java index 14b7c94..a178140 100644 --- a/src/test/java/com/aerospike/dsl/expression/ControlStructuresTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ControlStructuresTests.java @@ -3,7 +3,7 @@ import com.aerospike.client.exp.Exp; import org.junit.jupiter.api.Test; -import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; public class ControlStructuresTests { @@ -17,10 +17,10 @@ void whenWithASingleDeclaration() { Exp.val("other") ); - parseExpressionAndCompare("when ($.who == 1 => \"bob\", default => \"other\")", + parseFilterExpAndCompare("when ($.who == 1 => \"bob\", default => \"other\")", expected); // different spacing style - parseExpressionAndCompare("when($.who == 1 => \"bob\", default => \"other\")", + parseFilterExpAndCompare("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); - parseExpressionAndCompare("$.stringBin1.get(type: STRING) == (when ($.who == 1 => \"bob\", default => \"other\"))", + parseFilterExpAndCompare("$.stringBin1.get(type: STRING) == (when ($.who == 1 => \"bob\", default => \"other\"))", expected); } @@ -58,7 +58,7 @@ void whenWithMultipleDeclarations() { Exp.val("other") ); - parseExpressionAndCompare("when ($.who == 1 => \"bob\", $.who == 2 => \"fred\", default => \"other\")", + parseFilterExpAndCompare("when ($.who == 1 => \"bob\", $.who == 2 => \"fred\", default => \"other\")", expected); } @@ -74,10 +74,10 @@ void withMultipleVariablesDefinitionAndUsage() { Exp.add(Exp.var("x"), Exp.var("y")) ); - parseExpressionAndCompare("with (x = 1, y = ${x} + 1) do (${x} + ${y})", + parseFilterExpAndCompare("with (x = 1, y = ${x} + 1) do (${x} + ${y})", expected); // different spacing style - parseExpressionAndCompare("with(x = 1, y = ${x}+1) do(${x}+${y})", + parseFilterExpAndCompare("with(x = 1, y = ${x}+1) do(${x}+${y})", expected); } } diff --git a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java index 7774aa5..ee7d2a8 100644 --- a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java @@ -8,8 +8,8 @@ import java.util.List; import java.util.TreeMap; -import static com.aerospike.dsl.util.TestUtils.parseExpression; -import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseFilterExp; +import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; 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() { - parseExpressionAndCompare("$.intBin1.get(type: INT) > 5", + parseFilterExpAndCompare("$.intBin1.get(type: INT) > 5", Exp.gt(Exp.intBin("intBin1"), Exp.val(5))); - parseExpressionAndCompare("5 < $.intBin1.get(type: INT)", + parseFilterExpAndCompare("5 < $.intBin1.get(type: INT)", Exp.lt(Exp.val(5), Exp.intBin("intBin1"))); } @Test void stringComparison() { // A String constant must contain quoted Strings - parseExpressionAndCompare("$.stringBin1.get(type: STRING) == \"yes\"", + parseFilterExpAndCompare("$.stringBin1.get(type: STRING) == \"yes\"", Exp.eq(Exp.stringBin("stringBin1"), Exp.val("yes"))); - parseExpressionAndCompare("$.stringBin1.get(type: STRING) == 'yes'", + parseFilterExpAndCompare("$.stringBin1.get(type: STRING) == 'yes'", Exp.eq(Exp.stringBin("stringBin1"), Exp.val("yes"))); - parseExpressionAndCompare("\"yes\" == $.stringBin1.get(type: STRING)", + parseFilterExpAndCompare("\"yes\" == $.stringBin1.get(type: STRING)", Exp.eq(Exp.val("yes"), Exp.stringBin("stringBin1"))); - parseExpressionAndCompare("'yes' == $.stringBin1.get(type: STRING)", + parseFilterExpAndCompare("'yes' == $.stringBin1.get(type: STRING)", Exp.eq(Exp.val("yes"), Exp.stringBin("stringBin1"))); } @Test void stringComparisonNegativeTest() { // A String constant must be quoted - assertThatThrownBy(() -> parseExpressionAndCompare("$.stringBin1.get(type: STRING) == yes", + assertThatThrownBy(() -> parseFilterExpAndCompare("$.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); - parseExpressionAndCompare("$.blobBin1.get(type: BLOB) == \"" + encodedString + "\"", + parseFilterExpAndCompare("$.blobBin1.get(type: BLOB) == \"" + encodedString + "\"", Exp.eq(Exp.blobBin("blobBin1"), Exp.val(data))); // Reverse - parseExpressionAndCompare("\"" + encodedString + "\"" + " == $.blobBin1.get(type: BLOB)", + parseFilterExpAndCompare("\"" + encodedString + "\"" + " == $.blobBin1.get(type: BLOB)", Exp.eq(Exp.val(data), Exp.blobBin("blobBin1"))); } @Test void floatComparison() { - parseExpressionAndCompare("$.floatBin1.get(type: FLOAT) == 1.5", + parseFilterExpAndCompare("$.floatBin1.get(type: FLOAT) == 1.5", Exp.eq(Exp.floatBin("floatBin1"), Exp.val(1.5))); - parseExpressionAndCompare("1.5 == $.floatBin1.get(type: FLOAT)", + parseFilterExpAndCompare("1.5 == $.floatBin1.get(type: FLOAT)", Exp.eq(Exp.val(1.5), Exp.floatBin("floatBin1"))); } @Test void booleanComparison() { - parseExpressionAndCompare("$.boolBin1.get(type: BOOL) == true", + parseFilterExpAndCompare("$.boolBin1.get(type: BOOL) == true", Exp.eq(Exp.boolBin("boolBin1"), Exp.val(true))); - parseExpressionAndCompare("true == $.boolBin1.get(type: BOOL)", + parseFilterExpAndCompare("true == $.boolBin1.get(type: BOOL)", Exp.eq(Exp.val(true), Exp.boolBin("boolBin1"))); } @Test void negativeBooleanComparison() { - assertThatThrownBy(() -> parseExpression("$.boolBin1.get(type: BOOL) == 5")) + assertThatThrownBy(() -> parseFilterExp("$.boolBin1.get(type: BOOL) == 5")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Cannot compare BOOL to INT"); } @Test void listComparison_constantOnRightSide() { - parseExpressionAndCompare("$.listBin1.get(type: LIST) == [100]", + parseFilterExpAndCompare("$.listBin1.get(type: LIST) == [100]", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of(100)))); - parseExpressionAndCompare("$.listBin1.[] == [100]", + parseFilterExpAndCompare("$.listBin1.[] == [100]", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of(100)))); // integer values are read as long - parseExpressionAndCompare("$.listBin1.get(type: LIST) == [100, 200, 300, 400]", + parseFilterExpAndCompare("$.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 - parseExpressionAndCompare("$.listBin1.get(type: LIST) == [100, 200, 300, 400]", + parseFilterExpAndCompare("$.listBin1.get(type: LIST) == [100, 200, 300, 400]", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of(100L, 200L, 300L, 400L)))); - parseExpressionAndCompare("$.listBin1.get(type: LIST) == ['yes']", + parseFilterExpAndCompare("$.listBin1.get(type: LIST) == ['yes']", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of("yes")))); - parseExpressionAndCompare("$.listBin1.get(type: LIST) == ['yes', 'of course']", + parseFilterExpAndCompare("$.listBin1.get(type: LIST) == ['yes', 'of course']", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of("yes", "of course")))); - parseExpressionAndCompare("$.listBin1.get(type: LIST) == [\"yes\"]", + parseFilterExpAndCompare("$.listBin1.get(type: LIST) == [\"yes\"]", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of("yes")))); - parseExpressionAndCompare("$.listBin1.get(type: LIST) == [\"yes\", \"of course\"]", + parseFilterExpAndCompare("$.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(() -> - parseExpressionAndCompare("$.listBin1.get(type: LIST) == [yes, of course]", + parseFilterExpAndCompare("$.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() { - parseExpressionAndCompare("[100] == $.listBin1.get(type: LIST)", + parseFilterExpAndCompare("[100] == $.listBin1.get(type: LIST)", Exp.eq(Exp.val(List.of(100)), Exp.listBin("listBin1"))); - parseExpressionAndCompare("[100] == $.listBin1.[]", + parseFilterExpAndCompare("[100] == $.listBin1.[]", Exp.eq(Exp.val(List.of(100)), Exp.listBin("listBin1"))); // integer values are read as long - parseExpressionAndCompare("[100, 200, 300, 400] == $.listBin1.get(type: LIST)", + parseFilterExpAndCompare("[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 - parseExpressionAndCompare("[100, 200, 300, 400] == $.listBin1.get(type: LIST)", + parseFilterExpAndCompare("[100, 200, 300, 400] == $.listBin1.get(type: LIST)", Exp.eq(Exp.val(List.of(100L, 200L, 300L, 400L)), Exp.listBin("listBin1"))); - parseExpressionAndCompare("['yes'] == $.listBin1.get(type: LIST)", + parseFilterExpAndCompare("['yes'] == $.listBin1.get(type: LIST)", Exp.eq(Exp.val(List.of("yes")), Exp.listBin("listBin1"))); - parseExpressionAndCompare("['yes', 'of course'] == $.listBin1.get(type: LIST)", + parseFilterExpAndCompare("['yes', 'of course'] == $.listBin1.get(type: LIST)", Exp.eq(Exp.val(List.of("yes", "of course")), Exp.listBin("listBin1"))); - parseExpressionAndCompare("[\"yes\"] == $.listBin1.get(type: LIST)", + parseFilterExpAndCompare("[\"yes\"] == $.listBin1.get(type: LIST)", Exp.eq(Exp.val(List.of("yes")), Exp.listBin("listBin1"))); - parseExpressionAndCompare("[\"yes\", \"of course\"] == $.listBin1.get(type: LIST)", + parseFilterExpAndCompare("[\"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(() -> - parseExpressionAndCompare("[yes, of course] == $.listBin1.get(type: LIST)", + parseFilterExpAndCompare("[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 - parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {100:100}", + parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {100:100}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(100, 100)))); - parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {100 : 100}", + parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {100 : 100}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(100, 100)))); - parseExpressionAndCompare("$.mapBin1.{} == {100:100}", + parseFilterExpAndCompare("$.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 - parseExpressionAndCompare("$.mapBin1.{} == {'" + encodedBlobKey + "':100}", + parseFilterExpAndCompare("$.mapBin1.{} == {'" + encodedBlobKey + "':100}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(encodedBlobKey, 100)))); // integer values are read as long - parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {100:200, 300:400}", + parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {100:200, 300:400}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(100L, 200L, 300L, 400L)))); - parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {100:200, 300:400}", + parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {100:200, 300:400}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(100, 200, 300, 400)))); - parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {'yes?':'yes!'}", + parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {'yes?':'yes!'}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("yes?", "yes!")))); - parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {\"yes\" : \"yes\"}", + parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {\"yes\" : \"yes\"}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("yes", "yes")))); - parseExpressionAndCompare( + parseFilterExpAndCompare( "$.mapBin1.get(type: MAP) == {\"yes of course\" : \"yes of course\"}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("yes of course", "yes of course")))); - parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {\"yes\" : [\"yes\", \"of course\"]}", + parseFilterExpAndCompare("$.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(() -> - parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {yes, of course}", + parseFilterExpAndCompare("$.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(() -> - parseExpressionAndCompare("$.mapBin1.get(type: MAP) == ['yes', 'of course']", + parseFilterExpAndCompare("$.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(() -> - parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {[100]:[100]}", + parseFilterExpAndCompare("$.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 - parseExpressionAndCompare("{100:100} == $.mapBin1.get(type: MAP)", + parseFilterExpAndCompare("{100:100} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf(100, 100)), Exp.mapBin("mapBin1"))); - parseExpressionAndCompare("{100 : 100} == $.mapBin1.get(type: MAP)", + parseFilterExpAndCompare("{100 : 100} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf(100, 100)), Exp.mapBin("mapBin1"))); - parseExpressionAndCompare("{100:100} == $.mapBin1.{}", + parseFilterExpAndCompare("{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 - parseExpressionAndCompare("{'" + encodedBlobKey + "':100} == $.mapBin1.{}", + parseFilterExpAndCompare("{'" + encodedBlobKey + "':100} == $.mapBin1.{}", Exp.eq(Exp.val(treeMapOf(encodedBlobKey, 100)), Exp.mapBin("mapBin1"))); // integer values are read as long - parseExpressionAndCompare("{100:200, 300:400} == $.mapBin1.get(type: MAP)", + parseFilterExpAndCompare("{100:200, 300:400} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf(100L, 200L, 300L, 400L)), Exp.mapBin("mapBin1"))); - parseExpressionAndCompare("{100:200, 300:400} == $.mapBin1.get(type: MAP)", + parseFilterExpAndCompare("{100:200, 300:400} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf(100, 200, 300, 400)), Exp.mapBin("mapBin1"))); - parseExpressionAndCompare("{'yes?':'yes!'} == $.mapBin1.get(type: MAP)", + parseFilterExpAndCompare("{'yes?':'yes!'} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf("yes?", "yes!")), Exp.mapBin("mapBin1"))); - parseExpressionAndCompare("{\"yes\" : \"yes\"} == $.mapBin1.get(type: MAP)", + parseFilterExpAndCompare("{\"yes\" : \"yes\"} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf("yes", "yes")), Exp.mapBin("mapBin1"))); - parseExpressionAndCompare( + parseFilterExpAndCompare( "{\"yes of course\" : \"yes of course\"} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf("yes of course", "yes of course")), Exp.mapBin("mapBin1"))); - parseExpressionAndCompare("{\"yes\" : [\"yes\", \"of course\"]} == $.mapBin1.get(type: MAP)", + parseFilterExpAndCompare("{\"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(() -> - parseExpressionAndCompare("{yes, of course} == $.mapBin1.get(type: MAP)", + parseFilterExpAndCompare("{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(() -> - parseExpressionAndCompare("['yes', 'of course'] == $.mapBin1.get(type: MAP)", // incorrect: must be {} + parseFilterExpAndCompare("['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(() -> - parseExpressionAndCompare("{[100]:[100]} == $.mapBin1.get(type: MAP)", + parseFilterExpAndCompare("{[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() { - parseExpressionAndCompare("$.stringBin1.get(type: STRING) == $.stringBin2.get(type: STRING)", + parseFilterExpAndCompare("$.stringBin1.get(type: STRING) == $.stringBin2.get(type: STRING)", Exp.eq(Exp.stringBin("stringBin1"), Exp.stringBin("stringBin2"))); } @Test void twoIntegerBinsComparison() { - parseExpressionAndCompare("$.intBin1.get(type: INT) == $.intBin2.get(type: INT)", + parseFilterExpAndCompare("$.intBin1.get(type: INT) == $.intBin2.get(type: INT)", Exp.eq(Exp.intBin("intBin1"), Exp.intBin("intBin2"))); } @Test void twoFloatBinsComparison() { - parseExpressionAndCompare("$.floatBin1.get(type: FLOAT) == $.floatBin2.get(type: FLOAT)", + parseFilterExpAndCompare("$.floatBin1.get(type: FLOAT) == $.floatBin2.get(type: FLOAT)", Exp.eq(Exp.floatBin("floatBin1"), Exp.floatBin("floatBin2"))); } @Test void twoBlobBinsComparison() { - parseExpressionAndCompare("$.blobBin1.get(type: BLOB) == $.blobBin2.get(type: BLOB)", + parseFilterExpAndCompare("$.blobBin1.get(type: BLOB) == $.blobBin2.get(type: BLOB)", Exp.eq(Exp.blobBin("blobBin1"), Exp.blobBin("blobBin2"))); } @Test void negativeTwoDifferentBinTypesComparison() { - assertThatThrownBy(() -> parseExpression("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")) + assertThatThrownBy(() -> parseFilterExp("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Cannot compare STRING to FLOAT"); } @Test void secondDegreeExplicitFloat() { - parseExpressionAndCompare("($.apples.get(type: FLOAT) + $.bananas.get(type: FLOAT)) > 10.5", + parseFilterExpAndCompare("($.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() { - parseExpressionAndCompare("(($.apples.get(type: FLOAT) + $.bananas.get(type: FLOAT))" + + parseFilterExpAndCompare("(($.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() { ) ); - parseExpressionAndCompare("$.a.get(type: INT) == " + + parseFilterExpAndCompare("$.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() { ) ); - parseExpressionAndCompare("$.a.get(type: STRING) == " + + parseFilterExpAndCompare("$.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/expression/ImplicitTypesTests.java b/src/test/java/com/aerospike/dsl/expression/ImplicitTypesTests.java index 641f6aa..8d9e43a 100644 --- a/src/test/java/com/aerospike/dsl/expression/ImplicitTypesTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ImplicitTypesTests.java @@ -1,57 +1,59 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; public class ImplicitTypesTests { @Test void floatComparison() { - parseExpressionAndCompare("$.floatBin1 >= 100.25", + parseFilterExpAndCompare("$.floatBin1 >= 100.25", Exp.ge(Exp.floatBin("floatBin1"), Exp.val(100.25))); } @Test void booleanComparison() { - parseExpressionAndCompare("$.boolBin1 == true", + parseFilterExpAndCompare("$.boolBin1 == true", Exp.eq(Exp.boolBin("boolBin1"), Exp.val(true))); - parseExpressionAndCompare("false == $.boolBin1", + parseFilterExpAndCompare("false == $.boolBin1", Exp.eq(Exp.val(false), Exp.boolBin("boolBin1"))); - parseExpressionAndCompare("$.boolBin1 != false", + parseFilterExpAndCompare("$.boolBin1 != false", Exp.ne(Exp.boolBin("boolBin1"), Exp.val(false))); } // Logical expressions are always treated on boolean operands // this can also be an expression that evaluates to a boolean result + @Disabled // TODO: unary operator @Test void binBooleanImplicitLogicalComparison() { - parseExpressionAndCompare("$.boolBin1 and $.boolBin2", + parseFilterExpAndCompare("$.boolBin1 and $.boolBin2", Exp.and(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2"))); - parseExpressionAndCompare("$.boolBin1 or $.boolBin2", + parseFilterExpAndCompare("$.boolBin1 or $.boolBin2", Exp.or(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2"))); - parseExpressionAndCompare("not($.boolBin1)", + parseFilterExpAndCompare("not($.boolBin1)", Exp.not(Exp.boolBin("boolBin1"))); - parseExpressionAndCompare("exclusive($.boolBin1, $.boolBin2)", + parseFilterExpAndCompare("exclusive($.boolBin1, $.boolBin2)", Exp.exclusive(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2"))); } @Test void implicitDefaultIntComparison() { - parseExpressionAndCompare("$.intBin1 < $.intBin2", + parseFilterExpAndCompare("$.intBin1 < $.intBin2", Exp.lt(Exp.intBin("intBin1"), Exp.intBin("intBin2"))); } @Test void secondDegreeImplicitCastingFloat() { - parseExpressionAndCompare("($.apples + $.bananas) > 10.5", + parseFilterExpAndCompare("($.apples + $.bananas) > 10.5", Exp.gt(Exp.add(Exp.floatBin("apples"), Exp.floatBin("bananas")), Exp.val(10.5))); } @Test void secondDegreeComplicatedFloatFirstImplicitCastingFloat() { - parseExpressionAndCompare("($.apples + $.bananas) > 10.5 and ($.oranges + $.grapes) <= 5", + parseFilterExpAndCompare("($.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 +62,7 @@ void secondDegreeComplicatedFloatFirstImplicitCastingFloat() { @Test void secondDegreeComplicatedIntFirstImplicitCastingFloat() { - parseExpressionAndCompare("($.apples + $.bananas) > 5 and ($.oranges + $.grapes) <= 10.5", + parseFilterExpAndCompare("($.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 +71,7 @@ void secondDegreeComplicatedIntFirstImplicitCastingFloat() { @Test void thirdDegreeComplicatedDefaultInt() { - parseExpressionAndCompare("(($.apples + $.bananas) + $.oranges) > 10", + parseFilterExpAndCompare("(($.apples + $.bananas) + $.oranges) > 10", Exp.gt( Exp.add(Exp.add(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.intBin("oranges")), Exp.val(10)) @@ -78,7 +80,7 @@ void thirdDegreeComplicatedDefaultInt() { @Test void thirdDegreeComplicatedImplicitCastingFloat() { - parseExpressionAndCompare("(($.apples + $.bananas) + $.oranges) > 10.5", + parseFilterExpAndCompare("(($.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 +89,7 @@ void thirdDegreeComplicatedImplicitCastingFloat() { @Test void forthDegreeComplicatedDefaultInt() { - parseExpressionAndCompare("(($.apples + $.bananas) + ($.oranges + $.acai)) > 10", + parseFilterExpAndCompare("(($.apples + $.bananas) + ($.oranges + $.acai)) > 10", Exp.gt( Exp.add( Exp.add(Exp.intBin("apples"), Exp.intBin("bananas")), @@ -98,7 +100,7 @@ void forthDegreeComplicatedDefaultInt() { @Test void forthDegreeComplicatedImplicitCastingFloat() { - parseExpressionAndCompare("(($.apples + $.bananas) + ($.oranges + $.acai)) > 10.5", + parseFilterExpAndCompare("(($.apples + $.bananas) + ($.oranges + $.acai)) > 10.5", Exp.gt( Exp.add( Exp.add(Exp.floatBin("apples"), Exp.floatBin("bananas")), @@ -128,7 +130,7 @@ void complicatedWhenImplicitTypeInt() { ) ); - parseExpressionAndCompare("$.a == (when($.b == 1 => $.a1, $.b == 2 => $.a2, $.b == 3 => $.a3, default => $.a4+1))", + parseFilterExpAndCompare("$.a == (when($.b == 1 => $.a1, $.b == 2 => $.a2, $.b == 3 => $.a3, default => $.a4+1))", expected); } @@ -154,7 +156,7 @@ void complicatedWhenImplicitTypeString() { ) ); - parseExpressionAndCompare("$.a == (when($.b == 1 => $.a1, $.b == 2 => $.a2, $.b == 3 => $.a3, default => \"hello\"))", + parseFilterExpAndCompare("$.a == (when($.b == 1 => $.a1, $.b == 2 => $.a2, $.b == 3 => $.a3, default => \"hello\"))", expected); } } diff --git a/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java index fa6f36c..bc1bb71 100644 --- a/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java @@ -9,8 +9,8 @@ import java.util.List; -import static com.aerospike.dsl.util.TestUtils.parseExpression; -import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseFilterExp; +import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; import static org.assertj.core.api.Assertions.assertThatThrownBy; class ListExpressionsTests { @@ -26,10 +26,10 @@ void listByIndexInteger() { ), Exp.val(100)); // Implicit detect as Int - 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); + parseFilterExpAndCompare("$.listBin1.[0] == 100", expected); + parseFilterExpAndCompare("$.listBin1.[0].get(type: INT) == 100", expected); + parseFilterExpAndCompare("$.listBin1.[0].get(type: INT, return: VALUE) == 100", expected); + parseFilterExpAndCompare("$.listBin1.[0].asInt() == 100", expected); } @Test @@ -43,9 +43,9 @@ void listByIndexOtherTypes() { ), Exp.val("stringVal")); // Implicit detect as string - parseExpressionAndCompare("$.listBin1.[0] == \"stringVal\"", expected); - parseExpressionAndCompare("$.listBin1.[0].get(type: STRING) == \"stringVal\"", expected); - parseExpressionAndCompare("$.listBin1.[0].get(type: STRING, return: VALUE) == \"stringVal\"", expected); + parseFilterExpAndCompare("$.listBin1.[0] == \"stringVal\"", expected); + parseFilterExpAndCompare("$.listBin1.[0].get(type: STRING) == \"stringVal\"", expected); + parseFilterExpAndCompare("$.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 - parseExpressionAndCompare("$.listBin1.[0] == true", expected); - parseExpressionAndCompare("$.listBin1.[0].get(type: BOOL) == true", expected); - parseExpressionAndCompare("$.listBin1.[0].get(type: BOOL, return: VALUE) == true", expected); + parseFilterExpAndCompare("$.listBin1.[0] == true", expected); + parseFilterExpAndCompare("$.listBin1.[0].get(type: BOOL) == true", expected); + parseFilterExpAndCompare("$.listBin1.[0].get(type: BOOL, return: VALUE) == true", expected); } @Test @@ -70,10 +70,10 @@ void listByValue() { Exp.listBin("listBin1") ), Exp.val(100)); - 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); + parseFilterExpAndCompare("$.listBin1.[=100] == 100", expected); + parseFilterExpAndCompare("$.listBin1.[=100].get(type: INT) == 100", expected); + parseFilterExpAndCompare("$.listBin1.[=100].get(type: INT, return: VALUE) == 100", expected); + parseFilterExpAndCompare("$.listBin1.[=100].asInt() == 100", expected); } @Test @@ -84,8 +84,8 @@ void listByValueCount() { Exp.listBin("listBin1")), Exp.val(0) ); - parseExpressionAndCompare("$.listBin1.[=100].count() > 0", expected); - parseExpressionAndCompare("$.listBin1.[=100].[].count() > 0", expected); + parseFilterExpAndCompare("$.listBin1.[=100].count() > 0", expected); + parseFilterExpAndCompare("$.listBin1.[=100].[].count() > 0", expected); } @Test @@ -98,10 +98,10 @@ void listByRank() { Exp.listBin("listBin1") ), Exp.val(100)); - 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); + parseFilterExpAndCompare("$.listBin1.[#-1] == 100", expected); + parseFilterExpAndCompare("$.listBin1.[#-1].get(type: INT) == 100", expected); + parseFilterExpAndCompare("$.listBin1.[#-1].get(type: INT, return: VALUE) == 100", expected); + parseFilterExpAndCompare("$.listBin1.[#-1].asInt() == 100", expected); } @Test @@ -116,9 +116,9 @@ void listBinElementEquals_Nested() { CTX.listIndex(0) ), Exp.val(100)); - 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); + parseFilterExpAndCompare("$.listBin1.[0].[0].[0] == 100", expected); + parseFilterExpAndCompare("$.listBin1.[0].[0].[0].get(type: INT) == 100", expected); + parseFilterExpAndCompare("$.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)); - parseExpressionAndCompare("$.listBin1.[].count() == 1", expected); + parseFilterExpAndCompare("$.listBin1.[].count() == 1", expected); // the default behaviour for count() without List '[]' or Map '{}' designators is List - parseExpressionAndCompare("$.listBin1.count() == 1", expected); + parseFilterExpAndCompare("$.listBin1.count() == 1", expected); } @Test @@ -143,10 +143,10 @@ void nestedListSize() { Exp.listBin("listBin1")) ), Exp.val(100)); - parseExpressionAndCompare("$.listBin1.[1].[].count() == 100", expected); + parseFilterExpAndCompare("$.listBin1.[1].[].count() == 100", expected); // the default behaviour for count() without List '[]' or Map '{}' designators is List - parseExpressionAndCompare("$.listBin1.[1].count() == 100", expected); + parseFilterExpAndCompare("$.listBin1.[1].count() == 100", expected); } @@ -162,10 +162,10 @@ void nestedListSizeWithContext() { CTX.listIndex(1)) ), Exp.val(100)); - parseExpressionAndCompare("$.listBin1.[1].[2].[].count() == 100", expected); + parseFilterExpAndCompare("$.listBin1.[1].[2].[].count() == 100", expected); // the default behaviour for count() without List '[]' or Map '{}' designators is List - parseExpressionAndCompare("$.listBin1.[1].[2].count() == 100", expected); + parseFilterExpAndCompare("$.listBin1.[1].[2].count() == 100", expected); } @Test @@ -179,7 +179,7 @@ void nestedLists() { CTX.listIndex(5) ), Exp.val("stringVal")); - parseExpressionAndCompare("$.listBin1.[5].[1].get(type: STRING) == \"stringVal\"", expected); + parseFilterExpAndCompare("$.listBin1.[5].[1].get(type: STRING) == \"stringVal\"", expected); } @Test @@ -195,8 +195,8 @@ void nestedListsWithDifferentContextTypes() { ), Exp.val("stringVal")); // Implicit detect as String - parseExpressionAndCompare("$.listBin1.[5].[#-1] == \"stringVal\"", expected); - parseExpressionAndCompare("$.listBin1.[5].[#-1].get(type: STRING) == \"stringVal\"", expected); + parseFilterExpAndCompare("$.listBin1.[5].[#-1] == \"stringVal\"", expected); + parseFilterExpAndCompare("$.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 - parseExpressionAndCompare("$.listBin1.[5].[#-1].[=100] == 200", expected); + parseFilterExpAndCompare("$.listBin1.[5].[#-1].[=100] == 200", expected); } @Test @@ -223,21 +223,21 @@ void listBinElementCount() { ), Exp.val(100) ); - parseExpressionAndCompare("$.listBin1.[0].count() == 100", expected); - parseExpressionAndCompare("$.listBin1.[0].[].count() == 100", expected); + parseFilterExpAndCompare("$.listBin1.[0].count() == 100", expected); + parseFilterExpAndCompare("$.listBin1.[0].[].count() == 100", expected); } @Test void negativeSyntaxList() { // TODO: throw meaningful exception (by ANTLR?) - assertThatThrownBy(() -> parseExpression("$.listBin1.[stringValue] == 100")) + assertThatThrownBy(() -> parseFilterExp("$.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(() -> parseExpression("$.listBin1.[#-1].get(type: INT) == \"stringValue\"")) + assertThatThrownBy(() -> parseFilterExp("$.listBin1.[#-1].get(type: INT) == \"stringValue\"")) .isInstanceOf(NullPointerException.class); } @@ -248,7 +248,7 @@ void listIndexRange() { Exp.val(1), Exp.val(2), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[1:3]", expected); + parseFilterExpAndCompare("$.listBin1.[1:3]", expected); // Negative expected = ListExp.getByIndexRange( @@ -256,7 +256,7 @@ void listIndexRange() { Exp.val(-3), Exp.val(4), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[-3:1]", expected); + parseFilterExpAndCompare("$.listBin1.[-3:1]", expected); // Inverted expected = ListExp.getByIndexRange( @@ -264,14 +264,14 @@ void listIndexRange() { Exp.val(2), Exp.val(2), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[!2:4]", expected); + parseFilterExpAndCompare("$.listBin1.[!2:4]", expected); // From start till the end expected = ListExp.getByIndexRange( ListReturnType.VALUE, Exp.val(1), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[1:]", expected); + parseFilterExpAndCompare("$.listBin1.[1:]", expected); } @Test @@ -280,23 +280,23 @@ void listValueList() { ListReturnType.VALUE, Exp.val(List.of("a", "b", "c")), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[=a,b,c]", expected); - parseExpressionAndCompare("$.listBin1.[=\"a\",\"b\",\"c\"]", expected); + parseFilterExpAndCompare("$.listBin1.[=a,b,c]", expected); + parseFilterExpAndCompare("$.listBin1.[=\"a\",\"b\",\"c\"]", expected); // Integer expected = ListExp.getByValueList( ListReturnType.VALUE, Exp.val(List.of(1, 2, 3)), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[=1,2,3]", expected); + parseFilterExpAndCompare("$.listBin1.[=1,2,3]", expected); // Inverted expected = ListExp.getByValueList( ListReturnType.VALUE | ListReturnType.INVERTED, Exp.val(List.of("a", "b", "c")), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[!=a,b,c]", expected); - parseExpressionAndCompare("$.listBin1.[!=\"a\",\"b\",\"c\"]", expected); + parseFilterExpAndCompare("$.listBin1.[!=a,b,c]", expected); + parseFilterExpAndCompare("$.listBin1.[!=\"a\",\"b\",\"c\"]", expected); } @Test @@ -307,7 +307,7 @@ void listValueRange() { Exp.val(111), Exp.val(334), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[=111:334]", expected); + parseFilterExpAndCompare("$.listBin1.[=111:334]", expected); // Inverted expected = ListExp.getByValueRange( @@ -315,7 +315,7 @@ void listValueRange() { Exp.val(10), Exp.val(20), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[!=10:20]", expected); + parseFilterExpAndCompare("$.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")); - parseExpressionAndCompare("$.listBin1.[=111:]", expected); + parseFilterExpAndCompare("$.listBin1.[=111:]", expected); } @Test @@ -333,7 +333,7 @@ void listRankRange() { Exp.val(0), Exp.val(3), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[#0:3]", expected); + parseFilterExpAndCompare("$.listBin1.[#0:3]", expected); // Inverted expected = ListExp.getByRankRange( @@ -341,14 +341,14 @@ void listRankRange() { Exp.val(0), Exp.val(3), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[!#0:3]", expected); + parseFilterExpAndCompare("$.listBin1.[!#0:3]", expected); // From start till the end expected = ListExp.getByRankRange( ListReturnType.VALUE, Exp.val(-3), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[#-3:]", expected); + parseFilterExpAndCompare("$.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)); - parseExpressionAndCompare("$.listBin1.[5].[#-3:]", expected); + parseFilterExpAndCompare("$.listBin1.[5].[#-3:]", expected); } @Test @@ -367,7 +367,7 @@ void listRankRangeRelative() { Exp.val("b"), Exp.val(2), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[#-3:-1~b]", expected); + parseFilterExpAndCompare("$.listBin1.[#-3:-1~b]", expected); // Inverted expected = ListExp.getByValueRelativeRankRange( @@ -376,7 +376,7 @@ void listRankRangeRelative() { Exp.val("b"), Exp.val(2), Exp.listBin("listBin1")); - parseExpressionAndCompare("$.listBin1.[!#-3:-1~b]", expected); + parseFilterExpAndCompare("$.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")); - parseExpressionAndCompare("$.listBin1.[#-3:~b]", expected); + parseFilterExpAndCompare("$.listBin1.[#-3:~b]", expected); } @Test @@ -398,7 +398,7 @@ void listReturnTypes() { ), Exp.val(5)); // Implicit detect as Int - parseExpressionAndCompare("$.listBin1.[0].get(return: COUNT) == 5", expected); + parseFilterExpAndCompare("$.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 - parseExpressionAndCompare("$.listBin1.[0].get(return: EXISTS) == true", expected); + parseFilterExpAndCompare("$.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 - parseExpressionAndCompare("$.listBin1.[0].get(return: INDEX) == 1", expected); + parseFilterExpAndCompare("$.listBin1.[0].get(return: INDEX) == 1", expected); } } diff --git a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java index 28a7b86..7f5565f 100644 --- a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java @@ -2,11 +2,12 @@ import com.aerospike.client.exp.Exp; import com.aerospike.dsl.exception.AerospikeDSLException; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; -import static com.aerospike.dsl.util.TestUtils.parseExpression; -import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseFilterExp; +import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class LogicalExpressionsTests { @@ -15,7 +16,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))); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", expected1); + parseFilterExpAndCompare("$.intBin1 > 100 and $.intBin2 > 100", expected1); Exp expected2 = Exp.or( Exp.and( @@ -25,8 +26,8 @@ void binLogicalAndOrCombinations() { Exp.lt(Exp.intBin("intBin3"), Exp.val(100)) ); // TODO: what should be the default behaviour with no parentheses? - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 or $.intBin3 < 100", expected2); - parseExpressionAndCompare("($.intBin1 > 100 and $.intBin2 > 100) or $.intBin3 < 100", expected2); + parseFilterExpAndCompare("$.intBin1 > 100 and $.intBin2 > 100 or $.intBin3 < 100", expected2); + parseFilterExpAndCompare("($.intBin1 > 100 and $.intBin2 > 100) or $.intBin3 < 100", expected2); Exp expected3 = Exp.and( Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), @@ -35,27 +36,28 @@ void binLogicalAndOrCombinations() { Exp.lt(Exp.intBin("intBin3"), Exp.val(100)) ) ); - parseExpressionAndCompare("($.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 < 100))", expected3); + parseFilterExpAndCompare("($.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 < 100))", expected3); // check that parentheses make difference - assertThatThrownBy(() -> parseExpressionAndCompare("($.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 < 100))", expected2)) + assertThatThrownBy(() -> parseFilterExpAndCompare("($.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 < 100))", expected2)) .isInstanceOf(AssertionFailedError.class); } + @Disabled // TODO: unary operator @Test void logicalNot() { - parseExpressionAndCompare("not($.keyExists())", Exp.not(Exp.keyExists())); + parseFilterExpAndCompare("not($.keyExists())", Exp.not(Exp.keyExists())); } @Test void binLogicalExclusive() { - parseExpressionAndCompare("exclusive($.hand == \"hook\", $.leg == \"peg\")", + parseFilterExpAndCompare("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 - parseExpressionAndCompare("exclusive($.a == \"aVal\", $.b == \"bVal\", $.c == \"cVal\", $.d == 4)", + parseFilterExpAndCompare("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 +68,7 @@ void binLogicalExclusive() { //TODO: FMWK-488 //@Test void flatHierarchyAnd() { - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 < 100", + parseFilterExpAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 < 100", Exp.and( Exp.gt( Exp.intBin("intBin1"), @@ -81,26 +83,26 @@ void flatHierarchyAnd() { @Test void negativeSyntaxLogicalOperators() { - assertThatThrownBy(() -> parseExpression("($.intBin1 > 100 and ($.intBin2 > 100) or")) + assertThatThrownBy(() -> parseFilterExp("($.intBin1 > 100 and ($.intBin2 > 100) or")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Could not parse given input"); - assertThatThrownBy(() -> parseExpression("and ($.intBin1 > 100 and ($.intBin2 > 100)")) + assertThatThrownBy(() -> parseFilterExp("and ($.intBin1 > 100 and ($.intBin2 > 100)")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Could not parse given input"); - assertThatThrownBy(() -> parseExpression("($.intBin1 > 100 and ($.intBin2 > 100) not")) + assertThatThrownBy(() -> parseFilterExp("($.intBin1 > 100 and ($.intBin2 > 100) not")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Could not parse given input"); - assertThatThrownBy(() -> parseExpression("($.intBin1 > 100 and ($.intBin2 > 100) exclusive")) + assertThatThrownBy(() -> parseFilterExp("($.intBin1 > 100 and ($.intBin2 > 100) exclusive")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Could not parse given input"); } @Test void negativeBinLogicalExclusiveWithOneParam() { - assertThatThrownBy(() -> parseExpressionAndCompare("exclusive($.hand == \"hook\")", + assertThatThrownBy(() -> parseFilterExpAndCompare("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/expression/MapAndListExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/MapAndListExpressionsTests.java index 5bff0a5..bdea01b 100644 --- a/src/test/java/com/aerospike/dsl/expression/MapAndListExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/MapAndListExpressionsTests.java @@ -9,7 +9,7 @@ import com.aerospike.client.exp.MapExp; import org.junit.jupiter.api.Test; -import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; public class MapAndListExpressionsTests { @@ -24,7 +24,7 @@ void listInsideAMap() { CTX.mapKey(Value.get("a")) ), Exp.val(100)); - parseExpressionAndCompare("$.mapBin1.a.[0] == 100", expected); + parseFilterExpAndCompare("$.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)); - parseExpressionAndCompare("$.mapBin1.a.cc.[2].get(type: INT) > 100", expected); + parseFilterExpAndCompare("$.mapBin1.a.cc.[2].get(type: INT) > 100", expected); } @Test @@ -50,7 +50,7 @@ void mapListList() { CTX.listIndex(0) ), Exp.val(100)); - parseExpressionAndCompare("$.mapBin1.a.[0].[0] == 100", expected); + parseFilterExpAndCompare("$.mapBin1.a.[0].[0] == 100", expected); } @Test @@ -63,7 +63,7 @@ void mapInsideAList() { Exp.listBin("listBin1"), CTX.listIndex(2) ), Exp.val(100)); - parseExpressionAndCompare("$.listBin1.[2].cc.get(type: INT) > 100", expected); + parseFilterExpAndCompare("$.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)); - parseExpressionAndCompare("$.listBin1.[2].aa.cc > 100", expected); - parseExpressionAndCompare("$.listBin1.[2].aa.cc.get(type: INT) > 100", expected); + parseFilterExpAndCompare("$.listBin1.[2].aa.cc > 100", expected); + parseFilterExpAndCompare("$.listBin1.[2].aa.cc.get(type: INT) > 100", expected); } @Test @@ -93,7 +93,7 @@ void listMapList() { CTX.mapKey(Value.get("a")) ), Exp.val(100)); - parseExpressionAndCompare("$.listBin1.[1].a.[0] == 100", expected); + parseFilterExpAndCompare("$.listBin1.[1].a.[0] == 100", expected); } @Test @@ -110,8 +110,8 @@ void listMapListSize() { ) ), Exp.val(100)); - parseExpressionAndCompare("$.listBin1.[1].a.[0].count() == 100", expected); - parseExpressionAndCompare("$.listBin1.[1].a.[0].[].count() == 100", expected); + parseFilterExpAndCompare("$.listBin1.[1].a.[0].count() == 100", expected); + parseFilterExpAndCompare("$.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)); - parseExpressionAndCompare("$.mapBin1.a.[0].cc > 100", expected); - parseExpressionAndCompare("$.mapBin1.a.[0].cc.get(type: INT) > 100", expected); + parseFilterExpAndCompare("$.mapBin1.a.[0].cc > 100", expected); + parseFilterExpAndCompare("$.mapBin1.a.[0].cc.get(type: INT) > 100", expected); } //@Test diff --git a/src/test/java/com/aerospike/dsl/expression/MapExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/MapExpressionsTests.java index 68f36fb..dff3a7f 100644 --- a/src/test/java/com/aerospike/dsl/expression/MapExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/MapExpressionsTests.java @@ -11,7 +11,7 @@ import java.util.List; -import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; public class MapExpressionsTests { @@ -27,10 +27,10 @@ void mapOneLevelExpressions() { ), Exp.val(200)); // Implicit detect as Int - 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); + parseFilterExpAndCompare("$.mapBin1.a == 200", expected); + parseFilterExpAndCompare("$.mapBin1.a.get(type: INT) == 200", expected); + parseFilterExpAndCompare("$.mapBin1.a.get(type: INT, return: VALUE) == 200", expected); + parseFilterExpAndCompare("$.mapBin1.a.asInt() == 200", expected); // String expected = Exp.eq( @@ -42,9 +42,9 @@ void mapOneLevelExpressions() { ), Exp.val("stringVal")); // Implicit detect as String - parseExpressionAndCompare("$.mapBin1.a == \"stringVal\"", expected); - parseExpressionAndCompare("$.mapBin1.a.get(type: STRING) == \"stringVal\"", expected); - parseExpressionAndCompare("$.mapBin1.a.get(type: STRING, return: VALUE) == \"stringVal\"", expected); + parseFilterExpAndCompare("$.mapBin1.a == \"stringVal\"", expected); + parseFilterExpAndCompare("$.mapBin1.a.get(type: STRING) == \"stringVal\"", expected); + parseFilterExpAndCompare("$.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)); - 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); + parseFilterExpAndCompare("$.mapBin1.a.bb.bcc > 200", expected); + parseFilterExpAndCompare("$.mapBin1.a.bb.bcc.get(type: INT) > 200", expected); + parseFilterExpAndCompare("$.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 - 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); + parseFilterExpAndCompare("$.mapBin1.a.bb.bcc == \"stringVal\"", expected); + parseFilterExpAndCompare("$.mapBin1.a.bb.bcc.get(type: STRING) == \"stringVal\"", expected); + parseFilterExpAndCompare("$.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)); - 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); + parseFilterExpAndCompare("$.mapBin1.a.bb.bcc.get(type: INT) > 200", expected); + parseFilterExpAndCompare("$.mapBin1.a.\"bb\".bcc.get(type: INT) > 200", expected); + parseFilterExpAndCompare("$.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)); - parseExpressionAndCompare("$.mapBin1.\"127.0.0.1\".bcc.get(type: INT) > 200", expected); - parseExpressionAndCompare("$.mapBin1.'127.0.0.1'.bcc.get(type: INT) > 200", expected); + parseFilterExpAndCompare("$.mapBin1.\"127.0.0.1\".bcc.get(type: INT) > 200", expected); + parseFilterExpAndCompare("$.mapBin1.'127.0.0.1'.bcc.get(type: INT) > 200", expected); } @Test @@ -113,7 +113,7 @@ void mapSize() { Exp.mapBin("mapBin1") ), Exp.val(200)); - parseExpressionAndCompare("$.mapBin1.{}.count() > 200", expected); + parseFilterExpAndCompare("$.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)); - parseExpressionAndCompare("$.mapBin1.count() > 200", expected2); + parseFilterExpAndCompare("$.mapBin1.count() > 200", expected2); } @Test @@ -135,7 +135,7 @@ void nestedMapSize() { Exp.mapBin("mapBin1")) ), Exp.val(200)); - parseExpressionAndCompare("$.mapBin1.a.{}.count() == 200", expected); + parseFilterExpAndCompare("$.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)); - parseExpressionAndCompare("$.mapBin1.a.count() == 200", expected2); + parseFilterExpAndCompare("$.mapBin1.a.count() == 200", expected2); } @Test @@ -161,7 +161,7 @@ void nestedMapSizeWithContext() { CTX.mapKey(Value.get("a"))) ), Exp.val(200)); - parseExpressionAndCompare("$.mapBin1.a.b.{}.count() == 200", expected); + parseFilterExpAndCompare("$.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)); - parseExpressionAndCompare("$.mapBin1.a.b.count() == 200", expected2); + parseFilterExpAndCompare("$.mapBin1.a.b.count() == 200", expected2); } @Test @@ -186,10 +186,10 @@ void mapByIndex() { Exp.mapBin("mapBin1") ), Exp.val(100)); - 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); + parseFilterExpAndCompare("$.mapBin1.{0} == 100", expected); + parseFilterExpAndCompare("$.mapBin1.{0}.get(type: INT) == 100", expected); + parseFilterExpAndCompare("$.mapBin1.{0}.get(type: INT, return: VALUE) == 100", expected); + parseFilterExpAndCompare("$.mapBin1.{0}.asInt() == 100", expected); } @Test @@ -201,10 +201,10 @@ void mapByValue() { Exp.mapBin("mapBin1") ), Exp.val(100)); - 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); + parseFilterExpAndCompare("$.mapBin1.{=100} == 100", expected); + parseFilterExpAndCompare("$.mapBin1.{=100}.get(type: INT) == 100", expected); + parseFilterExpAndCompare("$.mapBin1.{=100}.get(type: INT, return: VALUE) == 100", expected); + parseFilterExpAndCompare("$.mapBin1.{=100}.asInt() == 100", expected); } @Test @@ -215,8 +215,8 @@ void mapByValueCount() { Exp.mapBin("mapBin1")), Exp.val(0) ); - parseExpressionAndCompare("$.mapBin1.{=100}.count() > 0", expected); - parseExpressionAndCompare("$.mapBin1.{=100}.{}.count() > 0", expected); + parseFilterExpAndCompare("$.mapBin1.{=100}.count() > 0", expected); + parseFilterExpAndCompare("$.mapBin1.{=100}.{}.count() > 0", expected); } @Test @@ -229,10 +229,10 @@ void mapByRank() { Exp.mapBin("mapBin1") ), Exp.val(100)); - 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); + parseFilterExpAndCompare("$.mapBin1.{#-1} == 100", expected); + parseFilterExpAndCompare("$.mapBin1.{#-1}.get(type: INT) == 100", expected); + parseFilterExpAndCompare("$.mapBin1.{#-1}.get(type: INT, return: VALUE) == 100", expected); + parseFilterExpAndCompare("$.mapBin1.{#-1}.asInt() == 100", expected); } @Test @@ -246,10 +246,10 @@ void mapByRankWithNesting() { CTX.mapKey(Value.get("a")) ), Exp.val(100)); - 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); + parseFilterExpAndCompare("$.mapBin1.a.{#-1} == 100", expected); + parseFilterExpAndCompare("$.mapBin1.a.{#-1}.get(type: INT) == 100", expected); + parseFilterExpAndCompare("$.mapBin1.a.{#-1}.get(type: INT, return: VALUE) == 100", expected); + parseFilterExpAndCompare("$.mapBin1.a.{#-1}.asInt() == 100", expected); } @Test @@ -265,8 +265,8 @@ void nestedListsWithDifferentContextTypes() { ), Exp.val("stringVal")); // Implicit detect as String - parseExpressionAndCompare("$.mapBin1.{5}.{#-1} == \"stringVal\"", expected); - parseExpressionAndCompare("$.mapBin1.{5}.{#-1}.get(type: STRING) == \"stringVal\"", expected); + parseFilterExpAndCompare("$.mapBin1.{5}.{#-1} == \"stringVal\"", expected); + parseFilterExpAndCompare("$.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)); - parseExpressionAndCompare("$.mapBin1.{5}.{#-1}.{=100} == 200", expected); + parseFilterExpAndCompare("$.mapBin1.{5}.{#-1}.{=100} == 200", expected); } @Test @@ -288,8 +288,8 @@ void mapKeyRange() { Exp.val("a"), Exp.val("c"), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{a-c}", expected); - parseExpressionAndCompare("$.mapBin1.{\"a\"-\"c\"}", expected); + parseFilterExpAndCompare("$.mapBin1.{a-c}", expected); + parseFilterExpAndCompare("$.mapBin1.{\"a\"-\"c\"}", expected); // Inverted expected = MapExp.getByKeyRange( @@ -297,8 +297,8 @@ void mapKeyRange() { Exp.val("a"), Exp.val("c"), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{!a-c}", expected); - parseExpressionAndCompare("$.mapBin1.{!\"a\"-\"c\"}", expected); + parseFilterExpAndCompare("$.mapBin1.{!a-c}", expected); + parseFilterExpAndCompare("$.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")); - parseExpressionAndCompare("$.mapBin1.{a-}", expected); - parseExpressionAndCompare("$.mapBin1.{\"a\"-}", expected); + parseFilterExpAndCompare("$.mapBin1.{a-}", expected); + parseFilterExpAndCompare("$.mapBin1.{\"a\"-}", expected); } @Test @@ -316,16 +316,16 @@ void mapKeyList() { MapReturnType.VALUE, Exp.val(List.of("a", "b", "c")), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{a,b,c}", expected); - parseExpressionAndCompare("$.mapBin1.{\"a\",\"b\",\"c\"}", expected); + parseFilterExpAndCompare("$.mapBin1.{a,b,c}", expected); + parseFilterExpAndCompare("$.mapBin1.{\"a\",\"b\",\"c\"}", expected); // Inverted expected = MapExp.getByKeyList( MapReturnType.VALUE | MapReturnType.INVERTED, Exp.val(List.of("a", "b", "c")), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{!a,b,c}", expected); - parseExpressionAndCompare("$.mapBin1.{!\"a\",\"b\",\"c\"}", expected); + parseFilterExpAndCompare("$.mapBin1.{!a,b,c}", expected); + parseFilterExpAndCompare("$.mapBin1.{!\"a\",\"b\",\"c\"}", expected); } @Test @@ -335,7 +335,7 @@ void mapIndexRange() { Exp.val(1), Exp.val(2), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{1:3}", expected); + parseFilterExpAndCompare("$.mapBin1.{1:3}", expected); // Negative expected = MapExp.getByIndexRange( @@ -343,7 +343,7 @@ void mapIndexRange() { Exp.val(-3), Exp.val(4), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{-3:1}", expected); + parseFilterExpAndCompare("$.mapBin1.{-3:1}", expected); // Inverted expected = MapExp.getByIndexRange( @@ -351,14 +351,14 @@ void mapIndexRange() { Exp.val(2), Exp.val(2), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{!2:4}", expected); + parseFilterExpAndCompare("$.mapBin1.{!2:4}", expected); // From start till the end expected = MapExp.getByIndexRange( MapReturnType.VALUE, Exp.val(1), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{1:}", expected); + parseFilterExpAndCompare("$.mapBin1.{1:}", expected); } @Test @@ -367,23 +367,23 @@ void mapValueList() { MapReturnType.VALUE, Exp.val(List.of("a", "b", "c")), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{=a,b,c}", expected); - parseExpressionAndCompare("$.mapBin1.{=\"a\",\"b\",\"c\"}", expected); + parseFilterExpAndCompare("$.mapBin1.{=a,b,c}", expected); + parseFilterExpAndCompare("$.mapBin1.{=\"a\",\"b\",\"c\"}", expected); // Integer expected = MapExp.getByValueList( MapReturnType.VALUE, Exp.val(List.of(1, 2, 3)), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{=1,2,3}", expected); + parseFilterExpAndCompare("$.mapBin1.{=1,2,3}", expected); // Inverted expected = MapExp.getByValueList( MapReturnType.VALUE | MapReturnType.INVERTED, Exp.val(List.of("a", "b", "c")), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{!=a,b,c}", expected); - parseExpressionAndCompare("$.mapBin1.{!=\"a\",\"b\",\"c\"}", expected); + parseFilterExpAndCompare("$.mapBin1.{!=a,b,c}", expected); + parseFilterExpAndCompare("$.mapBin1.{!=\"a\",\"b\",\"c\"}", expected); } @Test @@ -393,7 +393,7 @@ void mapValueRange() { Exp.val(111), Exp.val(334), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{=111:334}", expected); + parseFilterExpAndCompare("$.mapBin1.{=111:334}", expected); // Inverted expected = MapExp.getByValueRange( @@ -401,7 +401,7 @@ void mapValueRange() { Exp.val(10), Exp.val(20), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{!=10:20}", expected); + parseFilterExpAndCompare("$.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")); - parseExpressionAndCompare("$.mapBin1.{=111:}", expected); + parseFilterExpAndCompare("$.mapBin1.{=111:}", expected); } @Test @@ -419,7 +419,7 @@ void mapRankRange() { Exp.val(0), Exp.val(3), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{#0:3}", expected); + parseFilterExpAndCompare("$.mapBin1.{#0:3}", expected); // Inverted expected = MapExp.getByRankRange( @@ -427,14 +427,14 @@ void mapRankRange() { Exp.val(0), Exp.val(3), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{!#0:3}", expected); + parseFilterExpAndCompare("$.mapBin1.{!#0:3}", expected); // From start till the end expected = MapExp.getByRankRange( MapReturnType.VALUE, Exp.val(-3), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{#-3:}", expected); + parseFilterExpAndCompare("$.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)); - parseExpressionAndCompare("$.mapBin1.{5}.{#-3:}", expected); + parseFilterExpAndCompare("$.mapBin1.{5}.{#-3:}", expected); } @Test @@ -453,7 +453,7 @@ void mapRankRangeRelative() { Exp.val(10), Exp.val(2), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{#-1:1~10}", expected); + parseFilterExpAndCompare("$.mapBin1.{#-1:1~10}", expected); // Inverted expected = MapExp.getByValueRelativeRankRange( @@ -462,7 +462,7 @@ void mapRankRangeRelative() { Exp.val(10), Exp.val(2), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{!#-1:1~10}", expected); + parseFilterExpAndCompare("$.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")); - parseExpressionAndCompare("$.mapBin1.{#-2:~10}", expected); + parseFilterExpAndCompare("$.mapBin1.{#-2:~10}", expected); } @Test @@ -481,7 +481,7 @@ void mapIndexRangeRelative() { Exp.val(0), Exp.val(1), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{0:1~a}", expected); + parseFilterExpAndCompare("$.mapBin1.{0:1~a}", expected); // Inverted expected = MapExp.getByKeyRelativeIndexRange( @@ -490,7 +490,7 @@ void mapIndexRangeRelative() { Exp.val(0), Exp.val(1), Exp.mapBin("mapBin1")); - parseExpressionAndCompare("$.mapBin1.{!0:1~a}", expected); + parseFilterExpAndCompare("$.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")); - parseExpressionAndCompare("$.mapBin1.{0:~a}", expected); + parseFilterExpAndCompare("$.mapBin1.{0:~a}", expected); } @Test @@ -512,7 +512,7 @@ void mapReturnTypes() { ), Exp.val(5)); // Implicit detect as Int - parseExpressionAndCompare("$.mapBin1.a.get(type: INT, return: COUNT) == 5", expected); + parseFilterExpAndCompare("$.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 - parseExpressionAndCompare("$.mapBin1.a.get(return: ORDERED_MAP)", expected); + parseFilterExpAndCompare("$.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 - parseExpressionAndCompare("$.mapBin1.a.get(type: INT, return: RANK) == 5", expected); + parseFilterExpAndCompare("$.mapBin1.a.get(type: INT, return: RANK) == 5", expected); } } diff --git a/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java index ca59c28..107f2bc 100644 --- a/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java +++ b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java @@ -4,8 +4,8 @@ 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 com.aerospike.dsl.util.TestUtils.parseFilterExp; +import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; 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)); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(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)); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(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)); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(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)); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(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")); - parseExpressionAndCompare(input2, expected2); + parseFilterExpAndCompare(input2, expected2); } @Test @@ -52,7 +52,7 @@ void isTombstone() { // Expression to find records that are tombstones String input = "$.isTombstone()"; Exp expected = Exp.isTombstone(); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(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(); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(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")); - parseExpressionAndCompare(inputMetadataLeft, expectedLeft); + parseFilterExpAndCompare(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()); - parseExpressionAndCompare(inputMetadataRight, expectedRight); + parseFilterExpAndCompare(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)); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(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")); - parseExpressionAndCompare(input2, expected2); + parseFilterExpAndCompare(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")); - parseExpressionAndCompare(input3, expected3); + parseFilterExpAndCompare(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()); - parseExpressionAndCompare(input4, expected4); + parseFilterExpAndCompare(input4, expected4); } @Test @@ -108,12 +108,12 @@ void setName() { Exp.eq(Exp.setName(), Exp.val("groupA")), Exp.eq(Exp.setName(), Exp.val("groupB")) ); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(input, expected); // set name compared with String Bin input = "$.mySetBin == $.setName()"; expected = Exp.eq(Exp.stringBin("mySetBin"), Exp.setName()); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(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)); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(input, expected); } //@Test void negativeTtlAsDifferentType() { // TODO: should be supported when adding operator + metadata validations (requires a refactor) - assertThatThrownBy(() -> parseExpression("$.ttl() == true")) + assertThatThrownBy(() -> parseFilterExp("$.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)); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(input, expected); } @Test @@ -148,7 +148,7 @@ void metadataWithLogicalOperatorsExpressions() { Exp.gt(Exp.deviceSize(), Exp.val(1024)), Exp.lt(Exp.ttl(), Exp.val(300)) ); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(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)) ); - parseExpressionAndCompare(input2, expected2); + parseFilterExpAndCompare(input2, expected2); } @Test @@ -166,13 +166,13 @@ void metadataAsExpressionWithLogicalOperator() { Exp.isTombstone(), Exp.lt(Exp.ttl(), Exp.val(300)) ); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(input, expected); input = "$.ttl() < 300 or $.keyExists()"; expected = Exp.or( Exp.lt(Exp.ttl(), Exp.val(300)), Exp.keyExists() ); - parseExpressionAndCompare(input, expected); + parseFilterExpAndCompare(input, expected); } } diff --git a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java index c5e3cef..9082ae9 100644 --- a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java @@ -4,373 +4,302 @@ 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 com.aerospike.dsl.util.TestUtils.parseFilter; +import static com.aerospike.dsl.util.TestUtils.parseFilterAndCompare; +import static org.assertj.core.api.Assertions.assertThat; 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")) + assertThat(parseFilter("($.apples + $.bananas) > 10")).isNull(); // not supported by secondary index filter + + parseFilterAndCompare("($.apples + 5) > 10", + Filter.range("apples", 10 - 5 + 1, Long.MAX_VALUE)); + parseFilterAndCompare("($.apples + 5) >= 10", + Filter.range("apples", 10 - 5, Long.MAX_VALUE)); + parseFilterAndCompare("($.apples + 5) < 10", + Filter.range("apples", Long.MIN_VALUE, 10 - 5 - 1)); + parseFilterAndCompare("($.apples + 5) <= 10", + Filter.range("apples", Long.MIN_VALUE, 10 - 5)); + + parseFilterAndCompare("(9 + $.bananas) > 10", + Filter.range("bananas", 10 - 9 + 1, Long.MAX_VALUE)); + parseFilterAndCompare("(9 + $.bananas) >= 10", + Filter.range("bananas", 10 - 9, Long.MAX_VALUE)); + parseFilterAndCompare("(9 + $.bananas) < 10", + Filter.range("bananas", Long.MIN_VALUE, 10 - 9 - 1)); + parseFilterAndCompare("(9 + $.bananas) <= 10", + Filter.range("bananas", Long.MIN_VALUE, 10 - 9)); + + assertThat(parseFilter("(5.2 + $.bananas) > 10.2")).isNull(); // not supported by secondary index filter + assertThatThrownBy(() -> parseFilter("($.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")) + assertThat(parseFilter("($.apples - $.bananas) > 10")).isNull(); // not supported by secondary index filter + + parseFilterAndCompare("($.apples - 5) > 10", + Filter.range("apples", 10 + 5 + 1, Long.MAX_VALUE)); + parseFilterAndCompare("($.apples - 5) >= 10", + Filter.range("apples", 10 + 5, Long.MAX_VALUE)); + parseFilterAndCompare("($.apples - 5) < 10", + Filter.range("apples", Long.MIN_VALUE, 10 + 5 - 1)); + parseFilterAndCompare("($.apples - 5) <= 10", + Filter.range("apples", Long.MIN_VALUE, 10 + 5)); + + parseFilterAndCompare("($.apples - 5) > -10", + Filter.range("apples", -10 + 5 + 1, Long.MAX_VALUE)); + parseFilterAndCompare("($.apples - 5) >= -10", + Filter.range("apples", -10 + 5, Long.MAX_VALUE)); + parseFilterAndCompare("($.apples - 5) < -10", + Filter.range("apples", Long.MIN_VALUE, -10 + 5 - 1)); + parseFilterAndCompare("($.apples - 5) <= -10", + Filter.range("apples", Long.MIN_VALUE, -10 + 5)); + + parseFilterAndCompare("(9 - $.bananas) > 10", + Filter.range("bananas", Long.MIN_VALUE, 9 - 10 - 1)); + parseFilterAndCompare("(9 - $.bananas) >= 10", + Filter.range("bananas", Long.MIN_VALUE, 9 - 10)); + parseFilterAndCompare("(9 - $.bananas) < 10", + Filter.range("bananas", 9 - 10 + 1, Long.MAX_VALUE)); + parseFilterAndCompare("(9 - $.bananas) <= 10", + Filter.range("bananas", 9 - 10, Long.MAX_VALUE)); + + assertThat(parseFilter("($.apples - $.bananas) > 10")).isNull(); // not supported by secondary index filter + assertThatThrownBy(() -> parseFilter("($.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")) + assertThat(parseFilter("($.apples * $.bananas) > 10")).isNull(); // not supported by secondary index filter + + parseFilterAndCompare("($.apples * 5) > 10", + Filter.range("apples", 10 / 5 + 1, Long.MAX_VALUE)); + parseFilterAndCompare("($.apples * 5) >= 10", + Filter.range("apples", 10 / 5, Long.MAX_VALUE)); + parseFilterAndCompare("($.apples * 5) < 10", + Filter.range("apples", Long.MIN_VALUE, 10 / 5 - 1)); + parseFilterAndCompare("($.apples * 5) <= 10", + Filter.range("apples", Long.MIN_VALUE, 10 / 5)); + + parseFilterAndCompare("(9 * $.bananas) > 10", + Filter.range("bananas", 10 / 9 + 1, Long.MAX_VALUE)); + parseFilterAndCompare("(9 * $.bananas) >= 10", + Filter.range("bananas", 10 / 9, Long.MAX_VALUE)); + parseFilterAndCompare("(9 * $.bananas) < 10", + Filter.range("bananas", Long.MIN_VALUE, 10 / 9)); + parseFilterAndCompare("(9 * $.bananas) <= 10", + Filter.range("bananas", Long.MIN_VALUE, 10 / 9)); + + parseFilterAndCompare("($.apples * -5) > 10", + Filter.range("apples", Long.MIN_VALUE, 10 / -5 - 1)); + parseFilterAndCompare("($.apples * -5) >= 10", + Filter.range("apples", Long.MIN_VALUE, 10 / -5)); + parseFilterAndCompare("($.apples * -5) < 10", + Filter.range("apples", 10 / -5 + 1, Long.MAX_VALUE)); + parseFilterAndCompare("($.apples * -5) <= 10", + Filter.range("apples", 10 / -5, Long.MAX_VALUE)); + + assertThat(parseFilter("(0 * $.bananas) > 10")).isNull(); // Cannot divide by zero + + parseFilterAndCompare("(9 * $.bananas) > 0", + Filter.range("bananas", 0 / 9 + 1, Long.MAX_VALUE)); + + assertThatThrownBy(() -> parseFilter("($.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"); + assertThat(parseFilter("($.apples / $.bananas) <= 10")).isNull(); // 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] + parseFilterAndCompare("($.apples / 50) > 10", + Filter.range("apples", 50 * 10 + 1, Long.MAX_VALUE)); // [501, 2^63 - 1] + parseFilterAndCompare("($.apples / 50) >= 10", + Filter.range("apples", 50 * 10, Long.MAX_VALUE)); // [500, 2^63 - 1] + parseFilterAndCompare("($.apples / 50) < 10", + Filter.range("apples", Long.MIN_VALUE, 50 * 10 - 1)); // [-2^63, 499] + parseFilterAndCompare("($.apples / 50) <= 10", + Filter.range("apples", Long.MIN_VALUE, 50 * 10)); // [-2^63, 500] + + parseFilterAndCompare("($.apples / -50) > 10", + Filter.range("apples", Long.MIN_VALUE, -50 * 10 - 1)); // [-2^63, -501] + parseFilterAndCompare("($.apples / -50) >= 10", + Filter.range("apples", Long.MIN_VALUE, -50 * 10)); // [-2^63, -500] + parseFilterAndCompare("($.apples / -50) < 10", + Filter.range("apples", -50 * 10 + 1, Long.MAX_VALUE)); // [-499, 2^63 - 1] + parseFilterAndCompare("($.apples / -50) <= 10", + Filter.range("apples", -50 * 10, Long.MAX_VALUE)); // [-500, 2^63 - 1] + + parseFilterAndCompare("($.apples / 50) > -10", + Filter.range("apples", 50 * -10 + 1, Long.MAX_VALUE)); // [-499, 2^63 - 1] + parseFilterAndCompare("($.apples / 50) >= -10", + Filter.range("apples", 50 * -10, Long.MAX_VALUE)); // [-500, 2^63 - 1] + parseFilterAndCompare("($.apples / 50) < -10", + Filter.range("apples", Long.MIN_VALUE, 50 * -10 - 1)); // [-2^63, -501] + parseFilterAndCompare("($.apples / 50) <= -10", + Filter.range("apples", Long.MIN_VALUE, 50 * -10)); // [-2^63, -500] + + parseFilterAndCompare("($.apples / -50) > -10", + Filter.range("apples", Long.MIN_VALUE, -50 * -10 - 1)); // [-2^63, 499] + parseFilterAndCompare("($.apples / -50) >= -10", + Filter.range("apples", Long.MIN_VALUE, -10 * -50)); // [-2^63, 500] + parseFilterAndCompare("($.apples / -50) < -10", + Filter.range("apples", -10 * -50 + 1, Long.MAX_VALUE)); // [501, 2^63 - 1] + parseFilterAndCompare("($.apples / -50) <= -10", + 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] + parseFilterAndCompare("($.apples / 5) > 10", + Filter.range("apples", 5 * 10 + 1, Long.MAX_VALUE)); // [51, 2^63 - 1] + parseFilterAndCompare("($.apples / 5) >= 10", + Filter.range("apples", 5 * 10, Long.MAX_VALUE)); // [50, 2^63 - 1] + parseFilterAndCompare("($.apples / 5) < 10", + Filter.range("apples", Long.MIN_VALUE, 5 * 10 - 1)); // [-2^63, 49] + parseFilterAndCompare("($.apples / 5) <= 10", + Filter.range("apples", Long.MIN_VALUE, 5 * 10)); // [-2^63, 50] + + parseFilterAndCompare("($.apples / -5) > 10", + Filter.range("apples", Long.MIN_VALUE, -5 * 10 - 1)); // [-2^63, -51] + parseFilterAndCompare("($.apples / -5) >= 10", + Filter.range("apples", Long.MIN_VALUE, -5 * 10)); // [-2^63, -50] + parseFilterAndCompare("($.apples / -5) < 10", + Filter.range("apples", -5 * 10 + 1, Long.MAX_VALUE)); // [-49, 2^63 - 1] + parseFilterAndCompare("($.apples / -5) <= 10", + Filter.range("apples", -5 * 10, Long.MAX_VALUE)); // [-50, 2^63 - 1] + + parseFilterAndCompare("($.apples / 5) > -10", + Filter.range("apples", 5 * -10 + 1, Long.MAX_VALUE)); // [-49, 2^63 - 1] + parseFilterAndCompare("($.apples / 5) >= -10", + Filter.range("apples", 5 * -10, Long.MAX_VALUE)); // [-50, 2^63 - 1] + parseFilterAndCompare("($.apples / 5) < -10", + Filter.range("apples", Long.MIN_VALUE, 5 * -10 - 1)); // [-2^63, -51] + parseFilterAndCompare("($.apples / 5) <= -10", + Filter.range("apples", Long.MIN_VALUE, 5 * -10)); // [-2^63, -50] + + parseFilterAndCompare("($.apples / -5) > -10", + Filter.range("apples", Long.MIN_VALUE, -5 * -10 - 1)); // [-2^63, 49] + parseFilterAndCompare("($.apples / -5) >= -10", + Filter.range("apples", Long.MIN_VALUE, -10 * -5)); // [-2^63, 50] + parseFilterAndCompare("($.apples / -5) < -10", + Filter.range("apples", -10 * -5 + 1, Long.MAX_VALUE)); // [51, 2^63 - 1] + parseFilterAndCompare("($.apples / -5) <= -10", + 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] + parseFilterAndCompare("($.apples / 5) > 5", + Filter.range("apples", 5 * 5 + 1, Long.MAX_VALUE)); // [26, 2^63 - 1] + parseFilterAndCompare("($.apples / 5) >= 5", + Filter.range("apples", 5 * 5, Long.MAX_VALUE)); // [25, 2^63 - 1] + parseFilterAndCompare("($.apples / 5) < 5", + Filter.range("apples", Long.MIN_VALUE, 5 * 5 - 1)); // [-2^63, 24] + parseFilterAndCompare("($.apples / 5) <= 5", + Filter.range("apples", Long.MIN_VALUE, 5 * 5)); // [-2^63, 25] + + parseFilterAndCompare("($.apples / -5) > -5", + Filter.range("apples", Long.MIN_VALUE, -5 * -5 - 1)); // [-2^63, 24] + parseFilterAndCompare("($.apples / -5) >= -5", + Filter.range("apples", Long.MIN_VALUE, -5 * -5)); // [-2^63, 25] + parseFilterAndCompare("($.apples / -5) < -5", + Filter.range("apples", -5 * -5 + 1, Long.MAX_VALUE)); // [26, 2^63 - 1] + parseFilterAndCompare("($.apples / -5) <= -5", + 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] + parseFilterAndCompare("(90 / $.bananas) > 10", + Filter.range("bananas", 1, 90 / 10 - 1)); // [1,8] + parseFilterAndCompare("(90 / $.bananas) >= 10", + Filter.range("bananas", 1, 90 / 10)); // [1,9] + + // Not supported by secondary index filter + assertThat(parseFilter("(90 / $.bananas) < 10")).isNull(); + assertThat(parseFilter("(90 / $.bananas) <= 10")).isNull(); + + // Not supported by secondary index filter + assertThat(parseFilter("(90 / $.bananas) > -10")).isNull(); + assertThat(parseFilter("(90 / $.bananas) >= -10")).isNull(); + parseFilterAndCompare("(90 / $.bananas) < -10", + Filter.range("bananas", 90 / -10 + 1, -1)); // [-8, -1] + parseFilterAndCompare("(90 / $.bananas) <= -10", + Filter.range("bananas", 90 / -10, -1)); // [-8, -1] + + parseFilterAndCompare("(-90 / $.bananas) > 10", + Filter.range("bananas", -90 / 10 + 1, -1)); // [-8, -1] + parseFilterAndCompare("(90 / $.bananas) >= 10", + Filter.range("bananas", 1, 90 / 10)); // [1,9] + // Not supported by secondary index filter + assertThat(parseFilter("(-90 / $.bananas) < 10")).isNull(); + assertThat(parseFilter("(-90 / $.bananas) <= 10")).isNull(); + + // Not supported by secondary index filter + assertThat(parseFilter("(-90 / $.bananas) > -10")).isNull(); + assertThat(parseFilter("(-90 / $.bananas) >= -10")).isNull(); + parseFilterAndCompare("(-90 / $.bananas) < -10", + Filter.range("bananas", 1L, -90 / -10 - 1)); // [1, 8] + parseFilterAndCompare("(-90 / $.bananas) <= -10", + 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"); + // Not supported by secondary index filter + assertThat(parseFilter("(9 / $.bananas) > 10")).isNull(); // no integer numbers + assertThat(parseFilter("(9 / $.bananas) >= 10")).isNull(); // no integer numbers + assertThat(parseFilter("(9 / $.bananas) < 10")).isNull(); // maximal range is all numbers + assertThat(parseFilter("(9 / $.bananas) <= 10")).isNull(); // maximal range is all numbers + + assertThat(parseFilter("(9 / $.bananas) > -10")).isNull(); // maximal range is all numbers + assertThat(parseFilter("(9 / $.bananas) >= -10")).isNull(); // maximal range is all numbers + assertThat(parseFilter("(9 / $.bananas) < -10")).isNull(); // no integer numbers + assertThat(parseFilter("(9 / $.bananas) <= -10")).isNull(); // no integer numbers + + assertThat(parseFilter("(-9 / $.bananas) > 10")).isNull(); // no integer numbers + assertThat(parseFilter("(-9 / $.bananas) >= 10")).isNull(); // no integer numbers + assertThat(parseFilter("(-9 / $.bananas) < 10")).isNull(); // maximal range is all numbers + assertThat(parseFilter("(-9 / $.bananas) <= 10")).isNull(); // maximal range is all numbers + + assertThat(parseFilter("(-9 / $.bananas) > -10")).isNull(); // maximal range is all numbers + assertThat(parseFilter("(-9 / $.bananas) >= -10")).isNull(); // maximal range is all numbers + assertThat(parseFilter("(-9 / $.bananas) < -10")).isNull(); // no integer numbers + assertThat(parseFilter("(-9 / $.bananas) <= -10")).isNull(); // no integer numbers + + // Not supported by secondary index Filter + assertThat(parseFilter("(0 / $.bananas) > 10")).isNull(); // maximal range is all numbers + + // Not supported by secondary index Filter, cannot divide by zero + assertThat(parseFilter("(9 / $.bananas) > 0")).isNull(); // no integer numbers } @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] + // Not supported by secondary index filter + assertThat(parseFilter("(90 / $.bananas) > 90")).isNull(); // no integer numbers + parseFilterAndCompare("(90 / $.bananas) >= 90", + Filter.range("bananas", 90 / 90, 90 / 90)); // [1, 1] + assertThat(parseFilter("(90 / $.bananas) < 90")).isNull(); // maximal range is all numbers + assertThat(parseFilter("(90 / $.bananas) <= 90")).isNull(); // maximal range is all numbers + + assertThat(parseFilter("(-90 / $.bananas) > -90")).isNull(); // maximal range is all numbers + assertThat(parseFilter("(-90 / $.bananas) >= -90")).isNull(); // maximal range is all numbers + assertThat(parseFilter("(-90 / $.bananas) < -90")).isNull(); // no integer numbers + parseFilterAndCompare("(-90 / $.bananas) <= -90", + 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 index 1161383..dd796a4 100644 --- a/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java @@ -1,105 +1,101 @@ package com.aerospike.dsl.filter; import com.aerospike.client.query.Filter; -import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.client.query.IndexType; +import com.aerospike.dsl.index.Index; 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; +import static com.aerospike.dsl.util.TestUtils.parseFilter; +import static com.aerospike.dsl.util.TestUtils.parseFilterAndCompare; +import static org.assertj.core.api.Assertions.assertThat; 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"); + parseFilterAndCompare("$.intBin1 > 100", + Filter.range("intBin1", 101, Long.MAX_VALUE)); + parseFilterAndCompare("$.intBin1 > -100", + Filter.range("intBin1", -99, Long.MAX_VALUE)); + + // Comparing Strings is not supported by secondary index Filters + assertThat(parseFilter("$.stringBin1 > 'text'")).isNull(); + assertThat(parseFilter("$.stringBin1 > \"text\"")).isNull(); // "$.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"); + parseFilterAndCompare("100 < $.intBin1", + Filter.range("intBin1", 101, Long.MAX_VALUE)); + + // Comparing Strings is not supported by secondary index Filters + assertThat(parseFilter("'text' > $.stringBin1")).isNull(); + assertThat(parseFilter("\"text\" > $.stringBin1")).isNull(); + } + + @Test + void binGT_logical_combinations() { + List indexes = List.of( + Index.builder().bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), + Index.builder().bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(1).build() + ); + parseFilterAndCompare("$.intBin1 > 100 and $.intBin2 < 1000", "test", indexes, + Filter.range("intBin2", Long.MIN_VALUE, 999)); + + parseFilterAndCompare("$.intBin1 > 100 and $.intBin2 < 1000", + null); } @Test void binGE() { - parseFiltersAndCompare("$.intBin1 >= 100", - List.of(Filter.range("intBin1", 100, Long.MAX_VALUE))); + parseFilterAndCompare("$.intBin1 >= 100", + 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))); + parseFilterAndCompare("100 <= $.intBin1", + Filter.range("intBin1", 100, Long.MAX_VALUE)); } @Test void binLT() { - parseFiltersAndCompare("$.intBin1 < 100", - List.of(Filter.range("intBin1", Long.MIN_VALUE, 99))); + parseFilterAndCompare("$.intBin1 < 100", + Filter.range("intBin1", Long.MIN_VALUE, 99)); - parseFiltersAndCompare("100 > $.intBin1", - List.of(Filter.range("intBin1", Long.MIN_VALUE, 99))); + parseFilterAndCompare("100 > $.intBin1", + Filter.range("intBin1", Long.MIN_VALUE, 99)); } @Test void binLE() { - parseFiltersAndCompare("$.intBin1 <= 100", - List.of(Filter.range("intBin1", Long.MIN_VALUE, 100))); + parseFilterAndCompare("$.intBin1 <= 100", + Filter.range("intBin1", Long.MIN_VALUE, 100)); - parseFiltersAndCompare("100 >= $.intBin1", - List.of(Filter.range("intBin1", Long.MIN_VALUE, 100))); + parseFilterAndCompare("100 >= $.intBin1", + 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"))); + parseFilterAndCompare("$.intBin1 == 100", + Filter.equal("intBin1", 100)); + parseFilterAndCompare("100 == $.intBin1", + Filter.equal("intBin1", 100)); + + parseFilterAndCompare("$.stringBin1 == 'text'", + Filter.equal("stringBin1", "text")); + parseFilterAndCompare("$.stringBin1 == \"text\"", + 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"); + assertThat(parseFilter("$.intBin1 != 100")).isNull(); + assertThat(parseFilter("$.stringBin1 != 'text'")).isNull(); + assertThat(parseFilter("$.stringBin1 != \"text\"")).isNull(); + + assertThat(parseFilter("100 != $.intBin1")).isNull(); + assertThat(parseFilter("100 != 'text'")).isNull(); + assertThat(parseFilter("100 != \"text\"")).isNull(); } } diff --git a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java index 8fcf9db..427d042 100644 --- a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java @@ -2,45 +2,45 @@ import com.aerospike.client.query.Filter; import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.util.TestUtils; 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 com.aerospike.dsl.util.TestUtils.parseFilter; +import static org.assertj.core.api.Assertions.assertThat; 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))); + TestUtils.parseFilterAndCompare("$.intBin1.get(type: INT) > 5", + Filter.range("intBin1", 6, Long.MAX_VALUE)); - parseFiltersAndCompare("5 < $.intBin1.get(type: INT)", - List.of(Filter.range("intBin1", 6, Long.MAX_VALUE))); + TestUtils.parseFilterAndCompare("5 < $.intBin1.get(type: INT)", + Filter.range("intBin1", 6, Long.MAX_VALUE)); } @Test void stringComparison() { - parseFiltersAndCompare("$.stringBin1.get(type: STRING) == \"yes\"", - List.of(Filter.equal("stringBin1", "yes"))); + TestUtils.parseFilterAndCompare("$.stringBin1.get(type: STRING) == \"yes\"", + Filter.equal("stringBin1", "yes")); - parseFiltersAndCompare("$.stringBin1.get(type: STRING) == 'yes'", - List.of(Filter.equal("stringBin1", "yes"))); + TestUtils.parseFilterAndCompare("$.stringBin1.get(type: STRING) == 'yes'", + Filter.equal("stringBin1", "yes")); - parseFiltersAndCompare("\"yes\" == $.stringBin1.get(type: STRING)", - List.of(Filter.equal("stringBin1", "yes"))); + TestUtils.parseFilterAndCompare("\"yes\" == $.stringBin1.get(type: STRING)", + Filter.equal("stringBin1", "yes")); - parseFiltersAndCompare("'yes' == $.stringBin1.get(type: STRING)", - List.of(Filter.equal("stringBin1", "yes"))); + TestUtils.parseFilterAndCompare("'yes' == $.stringBin1.get(type: STRING)", + Filter.equal("stringBin1", "yes")); } @Test void stringComparisonNegativeTest() { // A String constant must be quoted - assertThatThrownBy(() -> parseFilters("$.stringBin1.get(type: STRING) == yes")) + assertThatThrownBy(() -> parseFilter("$.stringBin1.get(type: STRING) == yes")) .isInstanceOf(AerospikeDSLException.class) .hasMessage("Unable to parse right operand"); } @@ -49,133 +49,108 @@ void stringComparisonNegativeTest() { 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))); + TestUtils.parseFilterAndCompare("$.blobBin1.get(type: BLOB) == \"" + encodedString + "\"", + Filter.equal("blobBin1", data)); // Reverse - parseFiltersAndCompare("\"" + encodedString + "\" == $.blobBin1.get(type: BLOB)", - List.of(Filter.equal("blobBin1", data))); + TestUtils.parseFilterAndCompare("\"" + encodedString + "\" == $.blobBin1.get(type: BLOB)", + 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"); + assertThat(parseFilter("$.floatBin1.get(type: FLOAT) == 1.5")).isNull(); + assertThat(parseFilter("1.5 == $.floatBin1.get(type: FLOAT)")).isNull(); } @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"); + assertThat(parseFilter("$.boolBin1.get(type: BOOL) == true")).isNull(); + assertThat(parseFilter("true == $.boolBin1.get(type: BOOL)")).isNull(); } @Test void negativeBooleanComparison() { - assertThatThrownBy(() -> parseFilters("$.boolBin1.get(type: BOOL) == 5")) + assertThatThrownBy(() -> parseFilter("$.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"); + // Not supported by secondary index filter + assertThat(parseFilter("$.listBin1.get(type: LIST) == [100]")).isNull(); } @Test void listComparison_constantOnRightSide_NegativeTest() { - assertThatThrownBy(() -> parseFilters("$.listBin1.get(type: LIST) == [yes, of course]")) + assertThatThrownBy(() -> parseFilter("$.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"); + assertThat(parseFilter("[100] == $.listBin1.get(type: LIST)")).isNull(); } @Test void listComparison_constantOnLeftSide_NegativeTest() { - assertThatThrownBy(() -> parseFilters("[yes, of course] == $.listBin1.get(type: LIST)")) + assertThatThrownBy(() -> parseFilter("[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"); + assertThat(parseFilter("$.mapBin1.get(type: MAP) == {100:100}")).isNull(); } @Test void mapComparison_constantOnRightSide_NegativeTest() { - assertThatThrownBy(() -> parseFilters("$.mapBin1.get(type: MAP) == {yes, of course}")) + assertThatThrownBy(() -> parseFilter("$.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"); + assertThat(parseFilter("{100:100} == $.mapBin1.get(type: MAP)")).isNull(); } @Test void mapComparison_constantOnLeftSide_NegativeTest() { - assertThatThrownBy(() -> parseFilters("{yes, of course} == $.mapBin1.get(type: MAP)")) + assertThatThrownBy(() -> parseFilter("{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"); + assertThat(parseFilter("$.stringBin1.get(type: STRING) == $.stringBin2.get(type: STRING)")).isNull(); } @Test void twoIntegerBinsComparison() { - assertThatThrownBy(() -> parseFilters("$.intBin1.get(type: INT) == $.intBin2.get(type: INT)")) - .isInstanceOf(AerospikeDSLException.class) - .hasMessage("Operand type not supported: BIN_PART"); + assertThat(parseFilter("$.intBin1.get(type: INT) == $.intBin2.get(type: INT)")).isNull(); } @Test void twoFloatBinsComparison() { - assertThatThrownBy(() -> parseFilters("$.floatBin1.get(type: FLOAT) == $.floatBin2.get(type: FLOAT)")) - .isInstanceOf(AerospikeDSLException.class) - .hasMessage("Operand type not supported: BIN_PART"); + assertThat(parseFilter("$.floatBin1.get(type: FLOAT) == $.floatBin2.get(type: FLOAT)")).isNull(); } @Test void twoBlobBinsComparison() { - assertThatThrownBy(() -> parseFilters("$.blobBin1.get(type: BLOB) == $.blobBin2.get(type: BLOB)")) - .isInstanceOf(AerospikeDSLException.class) - .hasMessage("Operand type not supported: BIN_PART"); + assertThat(parseFilter("$.blobBin1.get(type: BLOB) == $.blobBin2.get(type: BLOB)")).isNull(); } @Test void negativeTwoDifferentBinTypesComparison() { - assertThatThrownBy(() -> parseFilters("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")) + assertThatThrownBy(() -> parseFilter("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")) .isInstanceOf(AerospikeDSLException.class) - .hasMessage("Operand type not supported: BIN_PART"); + .hasMessage("Cannot compare STRING to FLOAT"); } } diff --git a/src/test/java/com/aerospike/dsl/filter/ImplicitTypesFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ImplicitTypesFiltersTests.java index 15f4cb5..79690f8 100644 --- a/src/test/java/com/aerospike/dsl/filter/ImplicitTypesFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ImplicitTypesFiltersTests.java @@ -1,31 +1,24 @@ 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; +import static com.aerospike.dsl.util.TestUtils.parseFilter; +import static org.assertj.core.api.Assertions.assertThat; public class ImplicitTypesFiltersTests { @Test void implicitDefaultIntComparison() { - assertThatThrownBy(() -> parseFilters("$.intBin1 < $.intBin2")) - .isInstanceOf(AerospikeDSLException.class) - .hasMessage("Operand type not supported: BIN_PART"); + assertThat(parseFilter("$.intBin1 < $.intBin2")).isNull(); } @Test void floatComparison() { - assertThatThrownBy(() -> parseFilters("$.floatBin1 >= 100.25")) - .isInstanceOf(AerospikeDSLException.class) - .hasMessage("Operand type not supported: FLOAT_OPERAND"); + assertThat(parseFilter("$.floatBin1 >= 100.25")).isNull(); } @Test void booleanComparison() { - assertThatThrownBy(() -> parseFilters("$.boolBin1 == true")) - .isInstanceOf(AerospikeDSLException.class) - .hasMessage("Operand type not supported: BOOL_OPERAND"); + assertThat(parseFilter("$.boolBin1 == true")).isNull(); } } diff --git a/src/test/java/com/aerospike/dsl/util/TestUtils.java b/src/test/java/com/aerospike/dsl/util/TestUtils.java index b85a950..9a5587b 100644 --- a/src/test/java/com/aerospike/dsl/util/TestUtils.java +++ b/src/test/java/com/aerospike/dsl/util/TestUtils.java @@ -4,6 +4,7 @@ import com.aerospike.client.exp.Expression; import com.aerospike.client.query.Filter; import com.aerospike.dsl.DSLParserImpl; +import com.aerospike.dsl.index.Index; import lombok.experimental.UtilityClass; import java.util.List; @@ -15,22 +16,27 @@ public class TestUtils { private final DSLParserImpl parser = new DSLParserImpl(); - public static void parseExpression(String input) { - parser.parseExpression(input); + public static Expression parseFilterExp(String input) { + return parser.parseFilterExpression(input); } - public static void parseExpressionAndCompare(String input, Exp expected) { - Expression actualExpression = parser.parseExpression(input); + public static void parseFilterExpAndCompare(String input, Exp expected) { + Expression actualExpression = parser.parseFilterExpression(input); Expression expectedExpression = Exp.build(expected); assertEquals(actualExpression, expectedExpression); } - public static void parseFilters(String input) { - parser.parseFilters(input); + public static Filter parseFilter(String input) { + return parser.parseFilter(input, null, null); } - public static void parseFiltersAndCompare(String input, List expected) { - List actualFilter = parser.parseFilters(input); + public static void parseFilterAndCompare(String input, Filter expected) { + Filter actualFilter = parser.parseFilter(input, null, null); + assertEquals(actualFilter, expected); + } + + public static void parseFilterAndCompare(String input, String namespace, List indexes, Filter expected) { + Filter actualFilter = parser.parseFilter(input, namespace, indexes); assertEquals(actualFilter, expected); } } From 08045877c6cf1de1d4880ff5ff24469030f95df1 Mon Sep 17 00:00:00 2001 From: agrgr Date: Mon, 21 Apr 2025 16:23:58 +0300 Subject: [PATCH 02/20] process control structures and unary operators --- .../java/com/aerospike/dsl/DSLParserImpl.java | 13 +- .../com/aerospike/dsl/model/AbstractPart.java | 4 +- .../dsl/model/ExclusiveOperands.java | 16 ++ .../java/com/aerospike/dsl/model/Expr.java | 14 +- .../com/aerospike/dsl/model/WhenOperands.java | 16 ++ ...ithOperandsExpr.java => WithOperands.java} | 6 +- .../visitor/ExpressionConditionVisitor.java | 89 ++++----- .../aerospike/dsl/visitor/VisitorUtils.java | 185 +++++++++++++----- .../ArithmeticExpressionsTests.java | 2 - .../dsl/expression/ImplicitTypesTests.java | 14 +- .../expression/LogicalExpressionsTests.java | 2 - .../dsl/filter/ExplicitTypesFiltersTests.java | 6 +- 12 files changed, 242 insertions(+), 125 deletions(-) create mode 100644 src/main/java/com/aerospike/dsl/model/ExclusiveOperands.java create mode 100644 src/main/java/com/aerospike/dsl/model/WhenOperands.java rename src/main/java/com/aerospike/dsl/model/{WithOperandsExpr.java => WithOperands.java} (53%) diff --git a/src/main/java/com/aerospike/dsl/DSLParserImpl.java b/src/main/java/com/aerospike/dsl/DSLParserImpl.java index 762795b..b176019 100644 --- a/src/main/java/com/aerospike/dsl/DSLParserImpl.java +++ b/src/main/java/com/aerospike/dsl/DSLParserImpl.java @@ -8,6 +8,7 @@ import com.aerospike.dsl.exception.NoApplicableFilterException; import com.aerospike.dsl.index.Index; import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.model.Expr; import com.aerospike.dsl.visitor.ExpressionConditionVisitor; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; @@ -15,6 +16,8 @@ import java.util.Collection; +import static com.aerospike.dsl.visitor.VisitorUtils.*; + public class DSLParserImpl implements DSLParser { @Beta @@ -59,6 +62,9 @@ private Exp parseFilterExp(ParseTree parseTree) { throw new AerospikeDSLException("Could not parse given input, wrong syntax"); } + if (filterExprAbstractPart.getPartType() == AbstractPart.PartType.EXPR) { + return buildExpr((Expr) filterExprAbstractPart, null, null, true, false).getExp(); + } return filterExprAbstractPart.getExp(); } @@ -76,10 +82,9 @@ private Filter parseFilter(ParseTree parseTree, String namespace, Collection operands; + + public ExclusiveOperands(List operands) { + super(PartType.EXCLUSIVE_OPERANDS_LIST); + this.operands = operands; + } +} diff --git a/src/main/java/com/aerospike/dsl/model/Expr.java b/src/main/java/com/aerospike/dsl/model/Expr.java index 2308e40..828ba18 100644 --- a/src/main/java/com/aerospike/dsl/model/Expr.java +++ b/src/main/java/com/aerospike/dsl/model/Expr.java @@ -9,9 +9,11 @@ public class Expr extends AbstractPart { protected AbstractPart left; protected AbstractPart right; private ExprPartsOperation operationType; + private final boolean isUnary; public Expr(Exp exp) { super(PartType.EXPR, exp); + this.isUnary = false; } public Expr(AbstractPart left, AbstractPart right, ExprPartsOperation operationType) { @@ -19,12 +21,14 @@ public Expr(AbstractPart left, AbstractPart right, ExprPartsOperation operationT this.left = left; this.right = right; this.operationType = operationType; + this.isUnary = false; } public Expr(AbstractPart singleOperand, ExprPartsOperation operationType) { super(PartType.EXPR); - this.left = singleOperand; // TODO: unary operator + this.left = singleOperand; this.operationType = operationType; + this.isUnary = true; } public enum ExprPartsOperation { @@ -34,20 +38,22 @@ public enum ExprPartsOperation { MUL, MOD, INT_XOR, - INT_NOT, + INT_NOT, // unary INT_AND, INT_OR, L_SHIFT, R_SHIFT, AND, OR, + NOT, // unary EQ, NOTEQ, GT, GTEQ, LT, LTEQ, - WITH, - WHEN // TODO + WITH_OPERANDS, // unary + WHEN_OPERANDS, // unary + EXCLUSIVE_OPERANDS // unary } } diff --git a/src/main/java/com/aerospike/dsl/model/WhenOperands.java b/src/main/java/com/aerospike/dsl/model/WhenOperands.java new file mode 100644 index 0000000..850eebc --- /dev/null +++ b/src/main/java/com/aerospike/dsl/model/WhenOperands.java @@ -0,0 +1,16 @@ +package com.aerospike.dsl.model; + +import lombok.Getter; + +import java.util.List; + +@Getter +public class WhenOperands extends AbstractPart { + + private final List operands; + + public WhenOperands(List operands) { + super(PartType.WHEN_OPERANDS_LIST); + this.operands = operands; + } +} diff --git a/src/main/java/com/aerospike/dsl/model/WithOperandsExpr.java b/src/main/java/com/aerospike/dsl/model/WithOperands.java similarity index 53% rename from src/main/java/com/aerospike/dsl/model/WithOperandsExpr.java rename to src/main/java/com/aerospike/dsl/model/WithOperands.java index f3758e6..ca10727 100644 --- a/src/main/java/com/aerospike/dsl/model/WithOperandsExpr.java +++ b/src/main/java/com/aerospike/dsl/model/WithOperands.java @@ -5,12 +5,12 @@ import java.util.List; @Getter -public class WithOperandsExpr extends AbstractPart { +public class WithOperands extends AbstractPart { private final List operands; - public WithOperandsExpr(List operands) { - super(PartType.WITH_OPERAND_EXPR); + public WithOperands(List operands) { + super(PartType.WITH_OPERANDS_LIST); this.operands = operands; } } diff --git a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java index 5ebe864..a4b4f24 100644 --- a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java +++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java @@ -31,36 +31,42 @@ public class ExpressionConditionVisitor extends ConditionBaseVisitor { - private final boolean isFilterExp; - private final boolean isSIndexFilter; + private final boolean isFilterExpOnly; + private final boolean isSIndexFilterOnly; private final String namespace; private final Collection indexes; public ExpressionConditionVisitor() { - this.isFilterExp = false; - this.isSIndexFilter = false; + this.isFilterExpOnly = false; + this.isSIndexFilterOnly = false; this.namespace = null; this.indexes = null; } - public ExpressionConditionVisitor(boolean isFilterExp, boolean isSIndexFilter) { - this.isFilterExp = isFilterExp; - this.isSIndexFilter = isSIndexFilter; + public ExpressionConditionVisitor(boolean isFilterExpOnly, boolean isSIndexFilterOnly) { + if ((isFilterExpOnly && isSIndexFilterOnly) || (!isFilterExpOnly && !isSIndexFilterOnly)) { + throw new AerospikeDSLException("Error, expecting either isFilterExpOnly or isSIIndexFilterOnly flag"); + } + this.isFilterExpOnly = isFilterExpOnly; + this.isSIndexFilterOnly = isSIndexFilterOnly; this.namespace = null; this.indexes = null; } public ExpressionConditionVisitor(String namespace, Collection indexes) { - this.isFilterExp = false; - this.isSIndexFilter = false; + this.isFilterExpOnly = false; + this.isSIndexFilterOnly = false; this.namespace = namespace; this.indexes = indexes; } - public ExpressionConditionVisitor(String namespace, Collection indexes, boolean isFilterExp, - boolean isSIndexFilter) { - this.isFilterExp = isFilterExp; - this.isSIndexFilter = isSIndexFilter; + public ExpressionConditionVisitor(String namespace, Collection indexes, boolean isFilterExpOnly, + boolean isSIndexFilterOnly) { + if ((isFilterExpOnly && isSIndexFilterOnly) || (!isFilterExpOnly && !isSIndexFilterOnly)) { + throw new AerospikeDSLException("Error, expecting either isFilterExpOnly or isSIIndexFilterOnly flag"); + } + this.isFilterExpOnly = isFilterExpOnly; + this.isSIndexFilterOnly = isSIndexFilterOnly; this.namespace = namespace; this.indexes = indexes; } @@ -69,7 +75,7 @@ public ExpressionConditionVisitor(String namespace, Collection indexes, b public AbstractPart visitWithExpression(ConditionParser.WithExpressionContext ctx) { List expressions = new ArrayList<>(); - // iterate each definition + // iterate through each definition for (ConditionParser.VariableDefinitionContext vdc : ctx.variableDefinition()) { AbstractPart part = visit(vdc.expression()); WithOperand withOperand = new WithOperand(part, vdc.stringOperand().getText()); @@ -77,24 +83,22 @@ public AbstractPart visitWithExpression(ConditionParser.WithExpressionContext ct } // last expression is the action (described after "do") expressions.add(new WithOperand(visit(ctx.expression()), true)); - return new Expr(new WithOperandsExpr(expressions), Expr.ExprPartsOperation.WITH); + return new Expr(new WithOperands(expressions), Expr.ExprPartsOperation.WITH_OPERANDS); } @Override public AbstractPart visitWhenExpression(ConditionParser.WhenExpressionContext ctx) { - List expressions = new ArrayList<>(); - - // iterate each condition declaration + List parts = new ArrayList<>(); + // iterate through each definition declaration for (ConditionParser.ExpressionMappingContext emc : ctx.expressionMapping()) { // visit condition - expressions.add(visit(emc.expression(0)).getExp()); + parts.add(visit(emc.expression(0))); // visit action - expressions.add(visit(emc.expression(1)).getExp()); + parts.add(visit(emc.expression(1))); } - // visit default - expressions.add(visit(ctx.expression()).getExp()); - return new Expr(Exp.cond(expressions.toArray(new Exp[0]))); + parts.add(visit(ctx.expression())); + return new Expr(new WhenOperands(parts), Expr.ExprPartsOperation.WHEN_OPERANDS); } @Override @@ -120,7 +124,7 @@ public AbstractPart visitNotExpression(ConditionParser.NotExpressionContext ctx) Expr expr = (Expr) visit(ctx.expression()); logicalSetBinAsBooleanExpr(expr); - return new Expr(expr, Expr.ExprPartsOperation.LT); // TODO: unary operator + return new Expr(expr, Expr.ExprPartsOperation.NOT); } @Override @@ -128,15 +132,14 @@ public AbstractPart visitExclusiveExpression(ConditionParser.ExclusiveExpression if (ctx.expression().size() < 2) { throw new AerospikeDSLException("Exclusive logical operator requires 2 or more expressions"); } - List expressions = new ArrayList<>(); - - // iterate each condition declaration + List expressions = new ArrayList<>(); + // iterate through each definition for (ConditionParser.ExpressionContext ec : ctx.expression()) { Expr expr = (Expr) visit(ec); logicalSetBinAsBooleanExpr(expr); - expressions.add(expr.getExp()); + expressions.add(expr); } - return new Expr(Exp.exclusive(expressions.toArray(new Exp[0]))); + return new Expr(new ExclusiveOperands(expressions), Expr.ExprPartsOperation.EXCLUSIVE_OPERANDS); } @Override @@ -192,7 +195,7 @@ public AbstractPart visitAddExpression(ConditionParser.AddExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - if (!isFilterExp) validateNumericBinForFilter(left, right); + if (!isFilterExpOnly) validateNumericBinForFilter(left, right); return new Expr(left, right, ADD); } @@ -201,7 +204,7 @@ public AbstractPart visitSubExpression(ConditionParser.SubExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - if (!isFilterExp) validateNumericBinForFilter(left, right); + if (!isFilterExpOnly) validateNumericBinForFilter(left, right); return new Expr(left, right, SUB); } @@ -210,7 +213,7 @@ public AbstractPart visitMulExpression(ConditionParser.MulExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - if (!isFilterExp) validateNumericBinForFilter(left, right); + if (!isFilterExpOnly) validateNumericBinForFilter(left, right); return new Expr(left, right, MUL); } @@ -219,7 +222,7 @@ public AbstractPart visitDivExpression(ConditionParser.DivExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - if (!isFilterExp) validateNumericBinForFilter(left, right); + if (!isFilterExpOnly) validateNumericBinForFilter(left, right); return new Expr(left, right, DIV); } @@ -546,24 +549,4 @@ public AbstractPart visitMapPart(ConditionParser.MapPartContext ctx) { protected AbstractPart aggregateResult(AbstractPart aggregate, AbstractPart nextResult) { return nextResult == null ? aggregate : nextResult; } - - @Override - public AbstractPart visitChildren(RuleNode node) { - AbstractPart result = defaultResult(); - int n = node.getChildCount(); - for (int i=0; i operator) { if (operand == null) { - throw new AerospikeDSLException("Unable to parse operand"); + throw new AerospikeDSLException("Unable to parse unary operand"); } - // 1 Operand Expression is always a BIN Operand - String binName = ((BinPart) operand).getBinName(); + return switch (operand.getPartType()) { + case BIN_PART -> { + BinPart binPart = ((BinPart) operand); + // There is only 1 case of a single bin expression (Exp::not) + yield operator.apply(Exp.bin(binPart.getBinName(), binPart.getExpType())); + } + case METADATA_OPERAND -> { + MetadataOperand metadataOperand = ((MetadataOperand) operand); - // 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)); + // There is only 1 case of a single operand expression (int not) + yield operator.apply(metadataOperand.getExp()); + } + default -> throw new AerospikeDSLException("Unsupported part type for an unary expression"); + }; } static String getPathFunctionParam(ConditionParser.PathFunctionParamContext paramCtx, String paramName) { @@ -638,27 +688,85 @@ private FilterOperationType invertType(FilterOperationType type) { }; } - AbstractPart buildExpr(Expr expr, String namespace, Collection indexes, boolean isFilterExp) { - AbstractPart left = expr.getLeft(); - AbstractPart right = expr.getRight(); - Expr.ExprPartsOperation opType = expr.getOperationType(); + public AbstractPart buildExpr(Expr expr, String namespace, Collection indexes, + boolean isFilterExpOnly, boolean isSIFilterOnly) { Exp exp = null; + Filter sIndexFilter = null; try { - if (!isFilterExp) { - expr.setSIndexFilter(getFilter(expr, namespace, indexes)); + if (!isFilterExpOnly) { + sIndexFilter = getSIFilter(expr, namespace, indexes); } } catch (NoApplicableFilterException e) { // TODO: add cases with both Filter and Exp needed } - if (isFilterExp) { - processFilterExpressions(left, right); - exp = getExpOrFail(left, right, getExpOperator(opType)); + expr.setSIndexFilter(sIndexFilter); + + if (!isSIFilterOnly) { + exp = getFilterExp(expr); } expr.setExp(exp); return expr; } - private static Filter getFilter(Expr expr, String namespace, Collection indexes) { + private static Exp getFilterExp(Expr expr) { + return switch (expr.getOperationType()) { + case WITH_OPERANDS -> withOperandsToExp(expr); + case WHEN_OPERANDS -> whenOperandsToExp(expr); + case EXCLUSIVE_OPERANDS -> exclOperandsToExp(expr); + default -> exprToExp(expr); + }; + } + + private static Exp exprToExp(Expr expr) { + if (expr.isUnary()) { + return getExpOrFail(expr.getLeft(), getUnaryExpOperator(expr.getOperationType())); + } + return getExpOrFail(expr.getLeft(), expr.getRight(), getExpOperator(expr.getOperationType())); + } + + private static Exp withOperandsToExp(Expr expr) { + List expressions = new ArrayList<>(); + WithOperands withOperandsList = (WithOperands) expr.getLeft(); // extract unary Expr operand + List operands = withOperandsList.getOperands(); + for (WithOperand withOperand : operands) { + if (!withOperand.isLastPart()) { + expressions.add(Exp.def(withOperand.getString(), getExp(withOperand.getPart()))); + } else { + // the last expression is the action (described after "do") + expressions.add(getExp(withOperand.getPart())); + } + } + return Exp.let(expressions.toArray(new Exp[0])); + } + + private static Exp whenOperandsToExp(Expr expr) { + List expressions = new ArrayList<>(); + WhenOperands whenOperandsList = (WhenOperands) expr.getLeft(); // extract unary Expr operand + List operands = whenOperandsList.getOperands(); + for (AbstractPart part : operands) { + expressions.add(getExp(part)); + } + return Exp.cond(expressions.toArray(new Exp[0])); + } + + private static Exp exclOperandsToExp(Expr expr) { + List expressions = new ArrayList<>(); + ExclusiveOperands whenOperandsList = (ExclusiveOperands) expr.getLeft(); // extract unary Expr operand + List operands = whenOperandsList.getOperands(); + for (Expr part : operands) { + expressions.add(getExp(part)); + } + return Exp.exclusive(expressions.toArray(new Exp[0])); + } + + private static Exp getExp(AbstractPart part) { + if (part.getPartType() == EXPR) { + return getFilterExp((Expr) part); + } + return part.getExp(); + } + + private static Filter getSIFilter(Expr expr, String namespace, Collection indexes) { List exprs = getExprs(expr); Expr chosenExpr = chooseFilter(exprs, namespace, indexes); return chosenExpr == null ? null @@ -750,24 +858,6 @@ private static List getExprs(Expr expr) { return results; } - private void processFilterExpressions(AbstractPart left, AbstractPart right) { - // Process left Expr - if (left != null && left.getPartType() == EXPR) { - Expr leftExpr = (Expr) left; - Exp exp = getExpOrFail(leftExpr.getLeft(), leftExpr.getRight(), - getExpOperator(leftExpr.getOperationType())); - left.setExp(exp); - } - - // Process right Expr - if (right != null && right.getPartType() == EXPR) { - Expr rightExpr = (Expr) right; - Exp exp = getExpOrFail(rightExpr.getLeft(), rightExpr.getRight(), - getExpOperator(rightExpr.getOperationType())); - right.setExp(exp); - } - } - private static FilterOperationType getFilterOperation(Expr.ExprPartsOperation exprPartsOperation) { return switch (exprPartsOperation) { case GT -> FilterOperationType.GT; @@ -788,7 +878,6 @@ private static BinaryOperator getExpOperator(Expr.ExprPartsOperation exprPa case DIV -> Exp::div; case MOD -> Exp::mod; case INT_XOR -> Exp::intXor; -// case INT_NOT -> Exp::intNot; // TODO: unary operator case L_SHIFT -> Exp::lshift; case R_SHIFT -> Exp::rshift; case INT_AND -> Exp::intAnd; @@ -804,4 +893,12 @@ private static BinaryOperator getExpOperator(Expr.ExprPartsOperation exprPa default -> throw new NoApplicableFilterException("ExprPartsOperation has no matching BinaryOperator"); }; } + + private static UnaryOperator getUnaryExpOperator(Expr.ExprPartsOperation exprPartsOperation) { + return switch (exprPartsOperation) { + case INT_NOT -> Exp::intNot; + case NOT -> Exp::not; + default -> throw new NoApplicableFilterException("ExprPartsOperation has no matching UnaryOperator"); + }; + } } diff --git a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java index 1cd4a5e..368b803 100644 --- a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java @@ -2,7 +2,6 @@ import com.aerospike.client.exp.Exp; import com.aerospike.dsl.exception.AerospikeDSLException; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseFilterExp; @@ -98,7 +97,6 @@ void intXor() { Exp.ne(Exp.intXor(Exp.val(3), Exp.intBin("bananas")), Exp.val(10))); } - @Disabled // TODO: unary operator @Test void intNot() { parseFilterExpAndCompare("(~$.apples) != 10", diff --git a/src/test/java/com/aerospike/dsl/expression/ImplicitTypesTests.java b/src/test/java/com/aerospike/dsl/expression/ImplicitTypesTests.java index 8d9e43a..2765fff 100644 --- a/src/test/java/com/aerospike/dsl/expression/ImplicitTypesTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ImplicitTypesTests.java @@ -1,7 +1,6 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; @@ -26,17 +25,16 @@ void booleanComparison() { // Logical expressions are always treated on boolean operands // this can also be an expression that evaluates to a boolean result - @Disabled // TODO: unary operator @Test void binBooleanImplicitLogicalComparison() { - parseFilterExpAndCompare("$.boolBin1 and $.boolBin2", - Exp.and(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2"))); - parseFilterExpAndCompare("$.boolBin1 or $.boolBin2", - Exp.or(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2"))); +// parseFilterExpAndCompare("$.boolBin1 and $.boolBin2", +// Exp.and(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2"))); +// parseFilterExpAndCompare("$.boolBin1 or $.boolBin2", +// Exp.or(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2"))); parseFilterExpAndCompare("not($.boolBin1)", Exp.not(Exp.boolBin("boolBin1"))); - parseFilterExpAndCompare("exclusive($.boolBin1, $.boolBin2)", - Exp.exclusive(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2"))); +// parseFilterExpAndCompare("exclusive($.boolBin1, $.boolBin2)", +// Exp.exclusive(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2"))); } @Test diff --git a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java index 7f5565f..9329ce6 100644 --- a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java @@ -2,7 +2,6 @@ import com.aerospike.client.exp.Exp; import com.aerospike.dsl.exception.AerospikeDSLException; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; @@ -43,7 +42,6 @@ void binLogicalAndOrCombinations() { .isInstanceOf(AssertionFailedError.class); } - @Disabled // TODO: unary operator @Test void logicalNot() { parseFilterExpAndCompare("not($.keyExists())", Exp.not(Exp.keyExists())); diff --git a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java index 427d042..a75f6a4 100644 --- a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java @@ -148,9 +148,7 @@ void twoBlobBinsComparison() { } @Test - void negativeTwoDifferentBinTypesComparison() { - assertThatThrownBy(() -> parseFilter("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")) - .isInstanceOf(AerospikeDSLException.class) - .hasMessage("Cannot compare STRING to FLOAT"); + void differentBinTypes_nullResult() { + assertThat(parseFilter("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")).isNull(); } } From 80416c004cc0eabc975c924a8e7dba15d9a77a43 Mon Sep 17 00:00:00 2001 From: agrgr Date: Tue, 22 Apr 2025 14:37:28 +0300 Subject: [PATCH 03/20] unify building filter Exps and call it after the resulting tree is ready --- .../com/aerospike/dsl/model/AbstractPart.java | 5 - .../java/com/aerospike/dsl/model/BinPart.java | 8 +- .../aerospike/dsl/model/BooleanOperand.java | 6 +- .../java/com/aerospike/dsl/model/Expr.java | 5 +- .../com/aerospike/dsl/model/FloatOperand.java | 6 +- .../com/aerospike/dsl/model/IntOperand.java | 6 +- .../com/aerospike/dsl/model/ListOperand.java | 6 +- .../com/aerospike/dsl/model/MapOperand.java | 6 +- .../aerospike/dsl/model/MetadataOperand.java | 13 +- .../com/aerospike/dsl/model/PathOperand.java | 13 +- .../aerospike/dsl/model/StringOperand.java | 15 +- .../aerospike/dsl/model/VariableOperand.java | 6 +- .../visitor/ExpressionConditionVisitor.java | 3 +- .../dsl/visitor/FilterConditionVisitor.java | 129 --------------- .../aerospike/dsl/visitor/VisitorUtils.java | 156 +++++++----------- 15 files changed, 136 insertions(+), 247 deletions(-) delete mode 100644 src/main/java/com/aerospike/dsl/visitor/FilterConditionVisitor.java diff --git a/src/main/java/com/aerospike/dsl/model/AbstractPart.java b/src/main/java/com/aerospike/dsl/model/AbstractPart.java index c5cc595..6c34a98 100644 --- a/src/main/java/com/aerospike/dsl/model/AbstractPart.java +++ b/src/main/java/com/aerospike/dsl/model/AbstractPart.java @@ -19,11 +19,6 @@ protected AbstractPart(PartType partType) { this.exp = null; } - protected AbstractPart(PartType partType, Exp exp) { - this.partType = partType; - this.exp = exp; - } - protected AbstractPart(PartType partType, Filter filter) { this.partType = partType; this.sIndexFilter = filter; diff --git a/src/main/java/com/aerospike/dsl/model/BinPart.java b/src/main/java/com/aerospike/dsl/model/BinPart.java index 98098ac..2bedcdb 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((Exp) null); // Exp unknown + super(); this.binName = binName; this.partType = PartType.BIN_PART; this.expType = null; // Exp type unknown @@ -17,7 +17,9 @@ public BinPart(String binName) { public void updateExp(Exp.Type expType) { this.expType = expType; - // Update Expression of Abstract Part - super.exp = Exp.bin(this.binName, expType); + } + + public Exp getExp() { + return Exp.bin(this.binName, expType); } } diff --git a/src/main/java/com/aerospike/dsl/model/BooleanOperand.java b/src/main/java/com/aerospike/dsl/model/BooleanOperand.java index 7be9063..c072f58 100644 --- a/src/main/java/com/aerospike/dsl/model/BooleanOperand.java +++ b/src/main/java/com/aerospike/dsl/model/BooleanOperand.java @@ -9,7 +9,11 @@ public class BooleanOperand extends AbstractPart implements ParsedOperand { private final Boolean value; public BooleanOperand(Boolean value) { - super(PartType.BOOL_OPERAND, Exp.val(value)); + super(PartType.BOOL_OPERAND); this.value = value; } + + public Exp getExp() { + return Exp.val(value); + } } diff --git a/src/main/java/com/aerospike/dsl/model/Expr.java b/src/main/java/com/aerospike/dsl/model/Expr.java index 828ba18..0ab9363 100644 --- a/src/main/java/com/aerospike/dsl/model/Expr.java +++ b/src/main/java/com/aerospike/dsl/model/Expr.java @@ -1,6 +1,5 @@ package com.aerospike.dsl.model; -import com.aerospike.client.exp.Exp; import lombok.Getter; @Getter @@ -11,8 +10,8 @@ public class Expr extends AbstractPart { private ExprPartsOperation operationType; private final boolean isUnary; - public Expr(Exp exp) { - super(PartType.EXPR, exp); + public Expr() { + super(PartType.EXPR); this.isUnary = false; } diff --git a/src/main/java/com/aerospike/dsl/model/FloatOperand.java b/src/main/java/com/aerospike/dsl/model/FloatOperand.java index 4aa380b..51120b3 100644 --- a/src/main/java/com/aerospike/dsl/model/FloatOperand.java +++ b/src/main/java/com/aerospike/dsl/model/FloatOperand.java @@ -9,7 +9,11 @@ public class FloatOperand extends AbstractPart implements ParsedOperand { private final Double value; public FloatOperand(Double value) { - super(PartType.FLOAT_OPERAND, Exp.val(value)); + super(PartType.FLOAT_OPERAND); this.value = value; } + + public Exp getExp() { + return Exp.val(value); + } } diff --git a/src/main/java/com/aerospike/dsl/model/IntOperand.java b/src/main/java/com/aerospike/dsl/model/IntOperand.java index c414fc2..9436abb 100644 --- a/src/main/java/com/aerospike/dsl/model/IntOperand.java +++ b/src/main/java/com/aerospike/dsl/model/IntOperand.java @@ -9,7 +9,11 @@ public class IntOperand extends AbstractPart implements ParsedOperand { private final Long value; public IntOperand(Long value) { - super(AbstractPart.PartType.INT_OPERAND, Exp.val(value)); + super(AbstractPart.PartType.INT_OPERAND); this.value = value; } + + public Exp getExp() { + return Exp.val(value); + } } diff --git a/src/main/java/com/aerospike/dsl/model/ListOperand.java b/src/main/java/com/aerospike/dsl/model/ListOperand.java index ab7b9a5..5a55728 100644 --- a/src/main/java/com/aerospike/dsl/model/ListOperand.java +++ b/src/main/java/com/aerospike/dsl/model/ListOperand.java @@ -11,7 +11,11 @@ public class ListOperand extends AbstractPart implements ParsedOperand { private final List value; public ListOperand(List list) { - super(PartType.LIST_OPERAND, Exp.val(list)); + super(PartType.LIST_OPERAND); this.value = list; } + + public Exp getExp() { + return Exp.val(value); + } } diff --git a/src/main/java/com/aerospike/dsl/model/MapOperand.java b/src/main/java/com/aerospike/dsl/model/MapOperand.java index 6b49aca..c5e9bcc 100644 --- a/src/main/java/com/aerospike/dsl/model/MapOperand.java +++ b/src/main/java/com/aerospike/dsl/model/MapOperand.java @@ -11,7 +11,11 @@ public class MapOperand extends AbstractPart implements ParsedOperand { private final TreeMap value; public MapOperand(TreeMap map) { - super(PartType.MAP_OPERAND, Exp.val(map)); + super(PartType.MAP_OPERAND); this.value = map; } + + public Exp getExp() { + return Exp.val(value); + } } diff --git a/src/main/java/com/aerospike/dsl/model/MetadataOperand.java b/src/main/java/com/aerospike/dsl/model/MetadataOperand.java index e0359e1..9f1fd09 100644 --- a/src/main/java/com/aerospike/dsl/model/MetadataOperand.java +++ b/src/main/java/com/aerospike/dsl/model/MetadataOperand.java @@ -7,20 +7,23 @@ public class MetadataOperand extends Expr { private final String functionName; + private final Integer parameter; public MetadataOperand(String functionName) { - super(constructExp(functionName, null)); + super(); this.partType = PartType.METADATA_OPERAND; this.functionName = functionName; + this.parameter = null; } public MetadataOperand(String functionName, int parameter) { - super(constructExp(functionName, parameter)); + super(); this.partType = PartType.METADATA_OPERAND; this.functionName = functionName; + this.parameter = parameter; } - private static Exp constructExp(String functionName, Integer parameter) { + private Exp constructMetadataExp(String functionName, Integer parameter) { return switch (functionName) { case "deviceSize" -> Exp.deviceSize(); case "memorySize" -> Exp.memorySize(); @@ -59,4 +62,8 @@ public enum MetadataReturnType { STRING, BOOL, } + + public Exp getExp() { + return constructMetadataExp(functionName, parameter); + } } diff --git a/src/main/java/com/aerospike/dsl/model/PathOperand.java b/src/main/java/com/aerospike/dsl/model/PathOperand.java index 204f755..05a6713 100644 --- a/src/main/java/com/aerospike/dsl/model/PathOperand.java +++ b/src/main/java/com/aerospike/dsl/model/PathOperand.java @@ -15,8 +15,13 @@ @Getter public class PathOperand extends AbstractPart { - public PathOperand(Exp exp) { - super(PartType.PATH_OPERAND, exp); + private final BasePath basePath; + private final PathFunction pathFunction; + + public PathOperand(BasePath basePath, PathFunction pathFunction) { + super(PartType.PATH_OPERAND); + this.basePath = basePath; + this.pathFunction = pathFunction; } public static Exp processPath(BasePath basePath, PathFunction pathFunction) { @@ -39,4 +44,8 @@ public static Exp processPath(BasePath basePath, PathFunction pathFunction) { } return null; } + + public Exp getExp() { + return PathOperand.processPath(basePath, pathFunction); + } } diff --git a/src/main/java/com/aerospike/dsl/model/StringOperand.java b/src/main/java/com/aerospike/dsl/model/StringOperand.java index 805d1ea..4adb601 100644 --- a/src/main/java/com/aerospike/dsl/model/StringOperand.java +++ b/src/main/java/com/aerospike/dsl/model/StringOperand.java @@ -2,14 +2,27 @@ import com.aerospike.client.exp.Exp; import lombok.Getter; +import lombok.Setter; + +import java.util.Base64; @Getter public class StringOperand extends AbstractPart implements ParsedOperand { private final String value; + @Setter + private boolean isBlob = false; public StringOperand(String string) { - super(PartType.STRING_OPERAND, Exp.val(string)); + super(PartType.STRING_OPERAND); this.value = string; } + + public Exp getExp() { + if (isBlob) { + byte[] byteValue = Base64.getDecoder().decode(value); + return Exp.val(byteValue); + } + return Exp.val(value); + } } diff --git a/src/main/java/com/aerospike/dsl/model/VariableOperand.java b/src/main/java/com/aerospike/dsl/model/VariableOperand.java index 2af1fbf..c5da047 100644 --- a/src/main/java/com/aerospike/dsl/model/VariableOperand.java +++ b/src/main/java/com/aerospike/dsl/model/VariableOperand.java @@ -9,7 +9,11 @@ public class VariableOperand extends AbstractPart { private final String name; public VariableOperand(String name) { - super(PartType.VARIABLE_OPERAND, Exp.var(name)); + super(PartType.VARIABLE_OPERAND); this.name = name; } + + public Exp getExp() { + return Exp.var(name); + } } diff --git a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java index a4b4f24..28973ca 100644 --- a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java +++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java @@ -502,10 +502,9 @@ public AbstractPart visitPath(ConditionParser.PathContext ctx) { // if there are other parts except bin, get a corresponding Exp if (!parts.isEmpty() || ctx.pathFunction() != null && ctx.pathFunction().pathFunctionCount() != null) { - Exp exp = PathOperand.processPath(basePath, ctx.pathFunction() == null + return new PathOperand(basePath, ctx.pathFunction() == null ? null : (PathFunction) visit(ctx.pathFunction())); - return exp == null ? null : new PathOperand(exp); } return basePath.getBinPart(); } diff --git a/src/main/java/com/aerospike/dsl/visitor/FilterConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/FilterConditionVisitor.java deleted file mode 100644 index 87d820b..0000000 --- a/src/main/java/com/aerospike/dsl/visitor/FilterConditionVisitor.java +++ /dev/null @@ -1,129 +0,0 @@ -//package com.aerospike.dsl.visitor; -// -//import com.aerospike.client.query.Filter; -//import com.aerospike.dsl.ConditionParser; -//import com.aerospike.dsl.exception.NoApplicableFilterException; -//import com.aerospike.dsl.model.AbstractPart; -//import com.aerospike.dsl.model.Expr; -// -//import java.util.Collection; -//import java.util.stream.Stream; -// -//import static com.aerospike.dsl.model.Expr.ExprPartsOperation.*; -//import static com.aerospike.dsl.visitor.VisitorUtils.FilterOperationType.*; -//import static com.aerospike.dsl.visitor.VisitorUtils.*; -// -//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(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(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(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(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(filter); -// } -// -// @Override -// public AbstractPart visitInequalityExpression(ConditionParser.InequalityExpressionContext ctx) { -// throw new NoApplicableFilterException("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)); -// -// validateNumericBinForFilter(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)); -// -// validateNumericBinForFilter(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)); -// -// validateNumericBinForFilter(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)); -// -// validateNumericBinForFilter(left, right); -// return new Expr(left, right, MUL); -// } -// -// @Override -// public AbstractPart visitAndExpression(ConditionParser.AndExpressionContext ctx) { -// Expr left = (Expr) visit(ctx.expression(0)); -// Expr right = (Expr) visit(ctx.expression(1)); -// -// logicalSetBinsAsBooleanExpr(left, right); -// Collection filters = Stream.concat( -// left.getSIndexFilter().getFilter().stream(), -// right.getSIndexFilter().getFilter().stream() -// ).toList(); -// return new Expr(new SIndexFilter(filters)); -// } -// -// @Override -// public AbstractPart visitOrExpression(ConditionParser.OrExpressionContext ctx) { -// Expr left = (Expr) visit(ctx.expression(0)); -// Expr right = (Expr) visit(ctx.expression(1)); -// -// logicalSetBinsAsBooleanExpr(left, right); -// Collection filters = Stream.concat( -// left.getSIndexFilter().getFilter().stream(), -// right.getSIndexFilter().getFilter().stream() -// ).toList(); -// return new Expr(new SIndexFilter(filters)); -// } -//} diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index 4242a51..66f65f4 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -118,7 +118,13 @@ static boolean shouldVisitMapElement(int i, int size, ParseTree child) { } // 2 operands Expressions - static Exp getExpOrFail(AbstractPart left, AbstractPart right, BinaryOperator operator) { + static Exp exprToExp(Expr expr) { + if (expr.isUnary()) { + return getUnaryExpOrFail(expr.getLeft(), getUnaryExpOperator(expr.getOperationType())); + } + + AbstractPart left = expr.getLeft(); + AbstractPart right = expr.getRight(); if (left == null) { throw new AerospikeDSLException("Unable to parse left operand"); } @@ -126,56 +132,10 @@ static Exp getExpOrFail(AbstractPart left, AbstractPart right, BinaryOperator operator = getExpOperator(expr.getOperationType()); if (left.getPartType() == BIN_PART) { return getExpLeftBinTypeComparison((BinPart) left, right, operator); } @@ -185,117 +145,136 @@ static Exp getExpOrFail(AbstractPart left, AbstractPart right, BinaryOperator ops = List.of(WITH_OPERANDS, WHEN_OPERANDS, EXCLUSIVE_OPERANDS); + if (expr.isUnary()) { + if (!ops.contains(expr.getOperationType())) { + leftExp = getUnaryExpOrFail(part, getUnaryExpOperator(expr.getOperationType())); + part.setExp(leftExp); + } else { + leftExp = getFilterExp((Expr) part); + part.setExp(leftExp); + } + } else { + leftExp = getFilterExp((Expr) part); + part.setExp(leftExp); + } + } else if (part.getPartType() != BIN_PART && secondPartType != BIN_PART) { + leftExp = part.getExp(); + } + return leftExp; + } + static Exp getExpLeftBinTypeComparison(BinPart left, AbstractPart right, BinaryOperator operator) { - String binNameLeft = left.getBinName(); + Exp leftExp = Exp.bin(left.getBinName(), left.getExpType()); return switch (right.getPartType()) { case INT_OPERAND -> { validateComparableTypes(left.getExpType(), Exp.Type.INT); - yield operator.apply(left.getExp(), right.getExp()); + yield operator.apply(leftExp, right.getExp()); } case FLOAT_OPERAND -> { validateComparableTypes(left.getExpType(), Exp.Type.FLOAT); - yield operator.apply(left.getExp(), right.getExp()); + yield operator.apply(leftExp, right.getExp()); } case BOOL_OPERAND -> { validateComparableTypes(left.getExpType(), Exp.Type.BOOL); - yield operator.apply(left.getExp(), right.getExp()); + yield operator.apply(leftExp, 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)); + StringOperand stringRight = (StringOperand) right; + stringRight.setBlob(true); + yield operator.apply(leftExp, stringRight.getExp()); } else { // String validateComparableTypes(left.getExpType(), Exp.Type.STRING); - yield operator.apply(left.getExp(), right.getExp()); + yield operator.apply(leftExp, 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() - ); + leftExp = Exp.bin(left.getBinName(), binType); + yield operator.apply(leftExp, 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 EXPR, PATH_OPERAND -> operator.apply(leftExp, right.getExp()); // Can't validate with Expr on one side case BIN_PART -> { + // Left and right are both bin parts // Validate types if possible validateComparableTypes(left.getExpType(), right.getExpType()); - yield operator.apply(left.getExp(), right.getExp()); + yield operator.apply(leftExp, right.getExp()); } case LIST_OPERAND -> { validateComparableTypes(left.getExpType(), Exp.Type.LIST); - yield operator.apply(left.getExp(), right.getExp()); + yield operator.apply(leftExp, right.getExp()); } case MAP_OPERAND -> { validateComparableTypes(left.getExpType(), Exp.Type.MAP); - yield operator.apply(left.getExp(), right.getExp()); + yield operator.apply(leftExp, right.getExp()); } + case VARIABLE_OPERAND -> operator.apply(leftExp, 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(); + Exp rightExp = Exp.bin(right.getBinName(), right.getExpType()); return switch (left.getPartType()) { case INT_OPERAND -> { validateComparableTypes(Exp.Type.INT, right.getExpType()); - yield operator.apply(left.getExp(), right.getExp()); + yield operator.apply(left.getExp(), rightExp); } case FLOAT_OPERAND -> { validateComparableTypes(Exp.Type.FLOAT, right.getExpType()); - yield operator.apply(left.getExp(), right.getExp()); + yield operator.apply(left.getExp(), rightExp); } case BOOL_OPERAND -> { validateComparableTypes(Exp.Type.BOOL, right.getExpType()); - yield operator.apply(left.getExp(), right.getExp()); + yield operator.apply(left.getExp(), rightExp); } 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()); + StringOperand stringLeft = (StringOperand) left; + stringLeft.setBlob(true); + yield operator.apply(stringLeft.getExp(), rightExp); } else { // String validateComparableTypes(Exp.Type.STRING, right.getExpType()); - yield operator.apply(left.getExp(), right.getExp()); + yield operator.apply(left.getExp(), rightExp); } } 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) - ); + rightExp = Exp.bin(right.getBinName(), binType); + yield operator.apply(left.getExp(), rightExp); } 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()); + yield operator.apply(left.getExp(), rightExp); } case MAP_OPERAND -> { validateComparableTypes(Exp.Type.MAP, right.getExpType()); - yield operator.apply(left.getExp(), right.getExp()); + yield operator.apply(left.getExp(), rightExp); } + case VARIABLE_OPERAND -> operator.apply(left.getExp(), rightExp); default -> throw new AerospikeDSLException("Operand type not supported: %s".formatted(left.getPartType())); }; } // 1 operand Expressions - static Exp getExpOrFail(AbstractPart operand, UnaryOperator operator) { + static Exp getUnaryExpOrFail(AbstractPart operand, UnaryOperator operator) { if (operand == null) { throw new AerospikeDSLException("Unable to parse unary operand"); } @@ -303,13 +282,11 @@ static Exp getExpOrFail(AbstractPart operand, UnaryOperator operator) { return switch (operand.getPartType()) { case BIN_PART -> { BinPart binPart = ((BinPart) operand); - // There is only 1 case of a single bin expression (Exp::not) + // There is only 1 case of a single bin expression yield operator.apply(Exp.bin(binPart.getBinName(), binPart.getExpType())); } case METADATA_OPERAND -> { MetadataOperand metadataOperand = ((MetadataOperand) operand); - - // There is only 1 case of a single operand expression (int not) yield operator.apply(metadataOperand.getExp()); } default -> throw new AerospikeDSLException("Unsupported part type for an unary expression"); @@ -717,13 +694,6 @@ private static Exp getFilterExp(Expr expr) { }; } - private static Exp exprToExp(Expr expr) { - if (expr.isUnary()) { - return getExpOrFail(expr.getLeft(), getUnaryExpOperator(expr.getOperationType())); - } - return getExpOrFail(expr.getLeft(), expr.getRight(), getExpOperator(expr.getOperationType())); - } - private static Exp withOperandsToExp(Expr expr) { List expressions = new ArrayList<>(); WithOperands withOperandsList = (WithOperands) expr.getLeft(); // extract unary Expr operand From 70787665b4f9dc6f25ec7b00a2a3e07bd2cc7350 Mon Sep 17 00:00:00 2001 From: agrgr Date: Tue, 22 Apr 2025 15:56:05 +0300 Subject: [PATCH 04/20] use namespace, update API --- .../java/com/aerospike/dsl/DSLParser.java | 75 ++++++++++++++++++- .../java/com/aerospike/dsl/DSLParserImpl.java | 74 ++++++++++-------- .../com/aerospike/dsl/ParsedExpression.java | 13 +++- .../java/com/aerospike/dsl/index/Index.java | 3 +- .../aerospike/dsl/visitor/VisitorUtils.java | 9 ++- .../aerospike/dsl/filter/BinFiltersTests.java | 6 +- 6 files changed, 139 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/aerospike/dsl/DSLParser.java b/src/main/java/com/aerospike/dsl/DSLParser.java index 55aa61a..77c4dd8 100644 --- a/src/main/java/com/aerospike/dsl/DSLParser.java +++ b/src/main/java/com/aerospike/dsl/DSLParser.java @@ -1,5 +1,6 @@ package com.aerospike.dsl; +import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.Expression; import com.aerospike.client.query.Filter; import com.aerospike.dsl.exception.AerospikeDSLException; @@ -233,11 +234,83 @@ public interface DSLParser { * * * @param input String consisting of dot separated elements, typically bin name and optional context - * @return Expression for filtering records + * @return {@link Expression} for filtering records * @throws AerospikeDSLException in case of or invalid syntax */ Expression parseFilterExpression(String input); + /** + * Parse String DSL path into Aerospike filter Exp. + *

+ * Examples: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Path element
$.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
+ *
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
A nested element
$.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 {@link Exp} for filtering records + * @throws AerospikeDSLException in case of or invalid syntax + */ + Exp parseFilterExp(String input); + /** * Parse String DSL path into Aerospike secondary index Filter. *

diff --git a/src/main/java/com/aerospike/dsl/DSLParserImpl.java b/src/main/java/com/aerospike/dsl/DSLParserImpl.java index b176019..9b5bf4b 100644 --- a/src/main/java/com/aerospike/dsl/DSLParserImpl.java +++ b/src/main/java/com/aerospike/dsl/DSLParserImpl.java @@ -16,36 +16,36 @@ import java.util.Collection; -import static com.aerospike.dsl.visitor.VisitorUtils.*; +import static com.aerospike.dsl.model.AbstractPart.PartType.EXPR; +import static com.aerospike.dsl.visitor.VisitorUtils.buildExpr; public class DSLParserImpl implements DSLParser { @Beta public ParsedExpression parseDslExpression(String input) { ParseTree parseTree = getParseTree(input); - Filter sIndexFilter = parseFilter(parseTree, "test", null); - Expression expResult = Exp.build(parseFilterExp(parseTree)); - return new ParsedExpression(expResult, sIndexFilter); + return getParsedExpression(parseTree, null, null); } @Beta public ParsedExpression parseDslExpression(String input, String namespace, Collection indexes) { ParseTree parseTree = getParseTree(input); - Expression expResult = Exp.build(parseFilterExp(parseTree)); - Filter sIndexFilter = parseFilter(parseTree, namespace, indexes); - return new ParsedExpression(expResult, sIndexFilter); + return getParsedExpression(parseTree, namespace, indexes); } @Beta public Expression parseFilterExpression(String input) { - Exp result = parseFilterExp(getParseTree(input)); - if (result == null) return null; - return Exp.build(result); + return getFilterExpression(getParseTree(input), null, null); + } + + @Beta + public Exp parseFilterExp(String input) { + return getFilterExp(getParseTree(input), null, null); } @Beta public Filter parseFilter(String input, String namespace, Collection indexes) { - return parseFilter(getParseTree(input), namespace, indexes); + return getSIFilter(getParseTree(input), namespace, indexes); } private ParseTree getParseTree(String input) { @@ -54,37 +54,51 @@ private ParseTree getParseTree(String input) { return parser.parse(); } - private Exp parseFilterExp(ParseTree parseTree) { - AbstractPart filterExprAbstractPart = new ExpressionConditionVisitor(true, false).visit(parseTree); - - // When we can't identify a specific case of syntax error, we throw a generic DSL syntax error instead of NPE - if (filterExprAbstractPart == null) { - throw new AerospikeDSLException("Could not parse given input, wrong syntax"); - } - - if (filterExprAbstractPart.getPartType() == AbstractPart.PartType.EXPR) { - return buildExpr((Expr) filterExprAbstractPart, null, null, true, false).getExp(); - } - return filterExprAbstractPart.getExp(); + private ParsedExpression getParsedExpression(ParseTree parseTree, String namespace, Collection indexes) { + return getParsedExpression(parseTree, namespace, indexes, false, false); } - private Filter parseFilter(ParseTree parseTree, String namespace, Collection indexes) { + private ParsedExpression getParsedExpression(ParseTree parseTree, String namespace, Collection indexes, + boolean isFilterExpOnly, boolean isSIFilterOnly) { boolean isEmptyList = false; - AbstractPart sIndexFiltersAbstractPart = null; + AbstractPart resultingPart = null; try { - sIndexFiltersAbstractPart = new ExpressionConditionVisitor(namespace, indexes, false, true).visit(parseTree); + resultingPart = + new ExpressionConditionVisitor(namespace, indexes, isFilterExpOnly, isSIFilterOnly).visit(parseTree); } catch (NoApplicableFilterException e) { isEmptyList = true; } // When we can't identify a specific case of syntax error, we throw a generic DSL syntax error instead of NPE - if (!isEmptyList && sIndexFiltersAbstractPart == null) { + if (!isEmptyList && resultingPart == null) { throw new AerospikeDSLException("Could not parse given input, wrong syntax"); } - if (sIndexFiltersAbstractPart != null && sIndexFiltersAbstractPart.getPartType() == AbstractPart.PartType.EXPR) { - return buildExpr((Expr) sIndexFiltersAbstractPart, namespace, indexes, false, true).getSIndexFilter(); + if (resultingPart != null) { + if (resultingPart.getPartType() == EXPR) { + AbstractPart result = + buildExpr((Expr) resultingPart, namespace, indexes, isFilterExpOnly, isSIFilterOnly); + return new ParsedExpression(result.getExp(), result.getSIndexFilter()); + } else { + Filter filter = null; + if (!isFilterExpOnly) filter = resultingPart.getSIndexFilter(); + Exp exp = null; + if (!isSIFilterOnly) exp = resultingPart.getExp(); + return new ParsedExpression(exp, filter); + } } - return sIndexFiltersAbstractPart != null ? sIndexFiltersAbstractPart.getSIndexFilter() : null; + return new ParsedExpression(null, null); + } + + private Exp getFilterExp(ParseTree parseTree, String namespace, Collection indexes) { + return getParsedExpression(parseTree, namespace, indexes, true, false).getFilterExp(); + } + + private Expression getFilterExpression(ParseTree parseTree, String namespace, Collection indexes) { + return getParsedExpression(parseTree, namespace, indexes, true, false).getFilterExpression(); + } + + private Filter getSIFilter(ParseTree parseTree, String namespace, Collection indexes) { + return getParsedExpression(parseTree, namespace, indexes, false, true).getSIFilter(); } } diff --git a/src/main/java/com/aerospike/dsl/ParsedExpression.java b/src/main/java/com/aerospike/dsl/ParsedExpression.java index 10e3e7a..75c389d 100644 --- a/src/main/java/com/aerospike/dsl/ParsedExpression.java +++ b/src/main/java/com/aerospike/dsl/ParsedExpression.java @@ -1,5 +1,6 @@ package com.aerospike.dsl; +import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.Expression; import com.aerospike.client.query.Filter; import com.aerospike.dsl.annotation.Beta; @@ -19,7 +20,7 @@ @SuppressWarnings("LombokGetterMayBeUsed") public class ParsedExpression { - Expression filterExpression; + Exp filterExp; Filter siFilter; /** @@ -27,7 +28,15 @@ public class ParsedExpression { * @throws AerospikeDSLException If there was an error */ public Expression getFilterExpression() { - return filterExpression; + return filterExp == null ? null : Exp.build(filterExp); + } + + /** + * @return filter {@link Exp}. Can be null + * @throws AerospikeDSLException If there was an error + */ + public Exp getFilterExp() { + return filterExp; } /** diff --git a/src/main/java/com/aerospike/dsl/index/Index.java b/src/main/java/com/aerospike/dsl/index/Index.java index 2baee03..955e89c 100644 --- a/src/main/java/com/aerospike/dsl/index/Index.java +++ b/src/main/java/com/aerospike/dsl/index/Index.java @@ -17,7 +17,8 @@ @Getter public class Index { + private final String namespace; private final String bin; private final IndexType indexType; - private int binValuesRatio; + private int binValuesRatio = Integer.MIN_VALUE; } diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index 66f65f4..d6f5f86 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -738,7 +738,7 @@ private static Exp getExp(AbstractPart part) { private static Filter getSIFilter(Expr expr, String namespace, Collection indexes) { List exprs = getExprs(expr); - Expr chosenExpr = chooseFilter(exprs, namespace, indexes); + Expr chosenExpr = chooseExpr(exprs, namespace, indexes); return chosenExpr == null ? null : getFilterOrFail(chosenExpr.getLeft(), chosenExpr.getRight(), @@ -746,18 +746,19 @@ private static Filter getSIFilter(Expr expr, String namespace, Collection ); } - private static Expr chooseFilter(List exprs, String namespace, Collection indexes) { + private static Expr chooseExpr(List exprs, String namespace, Collection indexes) { if (exprs.size() == 1) return exprs.get(0); if (exprs.size() > 1 && (indexes == null || indexes.isEmpty())) return null; Expr resultExpr = null; int maxRatio = Integer.MIN_VALUE; - for (Expr expr : exprs) { BinPart binPart = getBinPart(expr); for (Index index : indexes) { if (binPart.getBinName().equals(index.getBin()) - && expTypeToIndexType.get(binPart.getExpType()) == index.getIndexType()) { + && expTypeToIndexType.get(binPart.getExpType()) == index.getIndexType() + && namespace.equals(index.getNamespace()) + ) { if (index.getBinValuesRatio() > maxRatio) { maxRatio = index.getBinValuesRatio(); resultExpr = expr; diff --git a/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java index dd796a4..07ab76d 100644 --- a/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java @@ -36,10 +36,10 @@ void binGT() { @Test void binGT_logical_combinations() { List indexes = List.of( - Index.builder().bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), - Index.builder().bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(1).build() + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(1).build() ); - parseFilterAndCompare("$.intBin1 > 100 and $.intBin2 < 1000", "test", indexes, + parseFilterAndCompare("$.intBin1 > 100 and $.intBin2 < 1000", "test1", indexes, Filter.range("intBin2", Long.MIN_VALUE, 999)); parseFilterAndCompare("$.intBin1 > 100 and $.intBin2 < 1000", From c3e1e019a0b21a55e93ea645d2cfeab0441876f0 Mon Sep 17 00:00:00 2001 From: agrgr Date: Thu, 24 Apr 2025 13:25:28 +0300 Subject: [PATCH 05/20] update processing logical structures, add alphabetical choosing, update API, add tests --- .../java/com/aerospike/dsl/DSLParserImpl.java | 12 +- .../com/aerospike/dsl/ParsedExpression.java | 18 +- .../java/com/aerospike/dsl/index/Index.java | 6 +- .../com/aerospike/dsl/model/AbstractPart.java | 6 +- ...eOperands.java => ExclusiveStructure.java} | 6 +- .../{WhenOperands.java => WhenStructure.java} | 6 +- .../{WithOperands.java => WithStructure.java} | 6 +- .../visitor/ExpressionConditionVisitor.java | 41 +-- .../aerospike/dsl/visitor/VisitorUtils.java | 74 +++-- .../LogicalParsedExpressionTests.java | 271 ++++++++++++++++++ .../com/aerospike/dsl/util/TestUtils.java | 14 + 11 files changed, 369 insertions(+), 91 deletions(-) rename src/main/java/com/aerospike/dsl/model/{ExclusiveOperands.java => ExclusiveStructure.java} (52%) rename src/main/java/com/aerospike/dsl/model/{WhenOperands.java => WhenStructure.java} (54%) rename src/main/java/com/aerospike/dsl/model/{WithOperands.java => WithStructure.java} (54%) create mode 100644 src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java diff --git a/src/main/java/com/aerospike/dsl/DSLParserImpl.java b/src/main/java/com/aerospike/dsl/DSLParserImpl.java index 9b5bf4b..587aa5f 100644 --- a/src/main/java/com/aerospike/dsl/DSLParserImpl.java +++ b/src/main/java/com/aerospike/dsl/DSLParserImpl.java @@ -15,9 +15,11 @@ import org.antlr.v4.runtime.tree.ParseTree; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import static com.aerospike.dsl.model.AbstractPart.PartType.EXPR; -import static com.aerospike.dsl.visitor.VisitorUtils.buildExpr; +import static com.aerospike.dsl.visitor.VisitorUtils.*; public class DSLParserImpl implements DSLParser { @@ -62,9 +64,13 @@ private ParsedExpression getParsedExpression(ParseTree parseTree, String namespa boolean isFilterExpOnly, boolean isSIFilterOnly) { boolean isEmptyList = false; AbstractPart resultingPart = null; + Map indexesMap = new HashMap<>(); + if (indexes != null && !indexes.isEmpty()) { + indexes.forEach(idx -> indexesMap.put(idx.getNamespace() + INDEX_NAME_SEPARATOR + idx.getBin(), idx)); + } try { resultingPart = - new ExpressionConditionVisitor(namespace, indexes, isFilterExpOnly, isSIFilterOnly).visit(parseTree); + new ExpressionConditionVisitor(isFilterExpOnly, isSIFilterOnly).visit(parseTree); } catch (NoApplicableFilterException e) { isEmptyList = true; } @@ -77,7 +83,7 @@ private ParsedExpression getParsedExpression(ParseTree parseTree, String namespa if (resultingPart != null) { if (resultingPart.getPartType() == EXPR) { AbstractPart result = - buildExpr((Expr) resultingPart, namespace, indexes, isFilterExpOnly, isSIFilterOnly); + buildExpr((Expr) resultingPart, namespace, indexesMap, isFilterExpOnly, isSIFilterOnly); return new ParsedExpression(result.getExp(), result.getSIndexFilter()); } else { Filter filter = null; diff --git a/src/main/java/com/aerospike/dsl/ParsedExpression.java b/src/main/java/com/aerospike/dsl/ParsedExpression.java index 75c389d..ead132e 100644 --- a/src/main/java/com/aerospike/dsl/ParsedExpression.java +++ b/src/main/java/com/aerospike/dsl/ParsedExpression.java @@ -5,7 +5,6 @@ import com.aerospike.client.query.Filter; import com.aerospike.dsl.annotation.Beta; import com.aerospike.dsl.exception.AerospikeDSLException; -import lombok.AllArgsConstructor; /** @@ -15,20 +14,29 @@ *
* List of Filters can be an empty if no suitable secondary index Filter was found. */ -@AllArgsConstructor @Beta @SuppressWarnings("LombokGetterMayBeUsed") public class ParsedExpression { - Exp filterExp; - Filter siFilter; + private final Exp filterExp; + private Expression filterExpression; + private final Filter siFilter; + + public ParsedExpression(Exp filterExp, Filter siFilter) { + this.filterExp = filterExp; + this.siFilter = siFilter; + } /** * @return filter {@link Expression}. Can be null * @throws AerospikeDSLException If there was an error */ public Expression getFilterExpression() { - return filterExp == null ? null : Exp.build(filterExp); + if (filterExp == null) { + return null; + } + if (filterExpression == null) filterExpression = Exp.build(filterExp); + return filterExpression; } /** diff --git a/src/main/java/com/aerospike/dsl/index/Index.java b/src/main/java/com/aerospike/dsl/index/Index.java index 955e89c..cfd7a58 100644 --- a/src/main/java/com/aerospike/dsl/index/Index.java +++ b/src/main/java/com/aerospike/dsl/index/Index.java @@ -1,18 +1,14 @@ package com.aerospike.dsl.index; import com.aerospike.client.query.IndexType; -import lombok.AllArgsConstructor; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; -import lombok.RequiredArgsConstructor; /** * This class represents a secondary index created in the cluster. */ @Builder -@RequiredArgsConstructor -@AllArgsConstructor @EqualsAndHashCode @Getter public class Index { @@ -20,5 +16,5 @@ public class Index { private final String namespace; private final String bin; private final IndexType indexType; - private int binValuesRatio = Integer.MIN_VALUE; + private int binValuesRatio; } diff --git a/src/main/java/com/aerospike/dsl/model/AbstractPart.java b/src/main/java/com/aerospike/dsl/model/AbstractPart.java index 6c34a98..037ddc5 100644 --- a/src/main/java/com/aerospike/dsl/model/AbstractPart.java +++ b/src/main/java/com/aerospike/dsl/model/AbstractPart.java @@ -32,9 +32,9 @@ public enum PartType { LIST_OPERAND, MAP_OPERAND, WITH_OPERAND, - WITH_OPERANDS_LIST, - WHEN_OPERANDS_LIST, - EXCLUSIVE_OPERANDS_LIST, + WITH_STRUCTURE, + WHEN_STRUCTURE, + EXCLUSIVE_STRUCTURE, BASE_PATH, BIN_PART, LIST_PART, diff --git a/src/main/java/com/aerospike/dsl/model/ExclusiveOperands.java b/src/main/java/com/aerospike/dsl/model/ExclusiveStructure.java similarity index 52% rename from src/main/java/com/aerospike/dsl/model/ExclusiveOperands.java rename to src/main/java/com/aerospike/dsl/model/ExclusiveStructure.java index c5479fd..96c2c0e 100644 --- a/src/main/java/com/aerospike/dsl/model/ExclusiveOperands.java +++ b/src/main/java/com/aerospike/dsl/model/ExclusiveStructure.java @@ -5,12 +5,12 @@ import java.util.List; @Getter -public class ExclusiveOperands extends AbstractPart { +public class ExclusiveStructure extends AbstractPart { private final List operands; - public ExclusiveOperands(List operands) { - super(PartType.EXCLUSIVE_OPERANDS_LIST); + public ExclusiveStructure(List operands) { + super(PartType.EXCLUSIVE_STRUCTURE); this.operands = operands; } } diff --git a/src/main/java/com/aerospike/dsl/model/WhenOperands.java b/src/main/java/com/aerospike/dsl/model/WhenStructure.java similarity index 54% rename from src/main/java/com/aerospike/dsl/model/WhenOperands.java rename to src/main/java/com/aerospike/dsl/model/WhenStructure.java index 850eebc..066686b 100644 --- a/src/main/java/com/aerospike/dsl/model/WhenOperands.java +++ b/src/main/java/com/aerospike/dsl/model/WhenStructure.java @@ -5,12 +5,12 @@ import java.util.List; @Getter -public class WhenOperands extends AbstractPart { +public class WhenStructure extends AbstractPart { private final List operands; - public WhenOperands(List operands) { - super(PartType.WHEN_OPERANDS_LIST); + public WhenStructure(List operands) { + super(PartType.WHEN_STRUCTURE); this.operands = operands; } } diff --git a/src/main/java/com/aerospike/dsl/model/WithOperands.java b/src/main/java/com/aerospike/dsl/model/WithStructure.java similarity index 54% rename from src/main/java/com/aerospike/dsl/model/WithOperands.java rename to src/main/java/com/aerospike/dsl/model/WithStructure.java index ca10727..b517745 100644 --- a/src/main/java/com/aerospike/dsl/model/WithOperands.java +++ b/src/main/java/com/aerospike/dsl/model/WithStructure.java @@ -5,12 +5,12 @@ import java.util.List; @Getter -public class WithOperands extends AbstractPart { +public class WithStructure extends AbstractPart { private final List operands; - public WithOperands(List operands) { - super(PartType.WITH_OPERANDS_LIST); + public WithStructure(List operands) { + super(PartType.WITH_STRUCTURE); this.operands = operands; } } diff --git a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java index 28973ca..01e1bd4 100644 --- a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java +++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java @@ -4,7 +4,6 @@ import com.aerospike.dsl.ConditionBaseVisitor; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.index.Index; import com.aerospike.dsl.model.*; import com.aerospike.dsl.model.cdt.list.ListIndex; import com.aerospike.dsl.model.cdt.list.ListIndexRange; @@ -21,7 +20,6 @@ import org.antlr.v4.runtime.tree.RuleNode; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.TreeMap; @@ -32,43 +30,12 @@ public class ExpressionConditionVisitor extends ConditionBaseVisitor { private final boolean isFilterExpOnly; - private final boolean isSIndexFilterOnly; - private final String namespace; - private final Collection indexes; - - public ExpressionConditionVisitor() { - this.isFilterExpOnly = false; - this.isSIndexFilterOnly = false; - this.namespace = null; - this.indexes = null; - } public ExpressionConditionVisitor(boolean isFilterExpOnly, boolean isSIndexFilterOnly) { - if ((isFilterExpOnly && isSIndexFilterOnly) || (!isFilterExpOnly && !isSIndexFilterOnly)) { - throw new AerospikeDSLException("Error, expecting either isFilterExpOnly or isSIIndexFilterOnly flag"); - } - this.isFilterExpOnly = isFilterExpOnly; - this.isSIndexFilterOnly = isSIndexFilterOnly; - this.namespace = null; - this.indexes = null; - } - - public ExpressionConditionVisitor(String namespace, Collection indexes) { - this.isFilterExpOnly = false; - this.isSIndexFilterOnly = false; - this.namespace = namespace; - this.indexes = indexes; - } - - public ExpressionConditionVisitor(String namespace, Collection indexes, boolean isFilterExpOnly, - boolean isSIndexFilterOnly) { - if ((isFilterExpOnly && isSIndexFilterOnly) || (!isFilterExpOnly && !isSIndexFilterOnly)) { + if (isFilterExpOnly && isSIndexFilterOnly) { throw new AerospikeDSLException("Error, expecting either isFilterExpOnly or isSIIndexFilterOnly flag"); } this.isFilterExpOnly = isFilterExpOnly; - this.isSIndexFilterOnly = isSIndexFilterOnly; - this.namespace = namespace; - this.indexes = indexes; } @Override @@ -83,7 +50,7 @@ public AbstractPart visitWithExpression(ConditionParser.WithExpressionContext ct } // last expression is the action (described after "do") expressions.add(new WithOperand(visit(ctx.expression()), true)); - return new Expr(new WithOperands(expressions), Expr.ExprPartsOperation.WITH_OPERANDS); + return new Expr(new WithStructure(expressions), Expr.ExprPartsOperation.WITH_OPERANDS); } @Override @@ -98,7 +65,7 @@ public AbstractPart visitWhenExpression(ConditionParser.WhenExpressionContext ct } // visit default parts.add(visit(ctx.expression())); - return new Expr(new WhenOperands(parts), Expr.ExprPartsOperation.WHEN_OPERANDS); + return new Expr(new WhenStructure(parts), Expr.ExprPartsOperation.WHEN_OPERANDS); } @Override @@ -139,7 +106,7 @@ public AbstractPart visitExclusiveExpression(ConditionParser.ExclusiveExpression logicalSetBinAsBooleanExpr(expr); expressions.add(expr); } - return new Expr(new ExclusiveOperands(expressions), Expr.ExprPartsOperation.EXCLUSIVE_OPERANDS); + return new Expr(new ExclusiveStructure(expressions), Expr.ExprPartsOperation.EXCLUSIVE_OPERANDS); } @Override diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index d6f5f86..3a12858 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -14,7 +14,9 @@ import java.util.ArrayList; import java.util.Base64; -import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -30,8 +32,9 @@ @UtilityClass public class VisitorUtils { - Map expTypeToIndexType = Map.of(Exp.Type.INT, IndexType.NUMERIC, - Exp.Type.STRING, IndexType.STRING); + public final String INDEX_NAME_SEPARATOR = "||||"; + private final Map expTypeToIndexType = Map.of(Exp.Type.INT, IndexType.NUMERIC, + Exp.Type.STRING, IndexType.STRING, Exp.Type.BLOB, IndexType.BLOB); protected enum FilterOperationType { GT, @@ -665,7 +668,7 @@ private FilterOperationType invertType(FilterOperationType type) { }; } - public AbstractPart buildExpr(Expr expr, String namespace, Collection indexes, + public AbstractPart buildExpr(Expr expr, String namespace, Map indexes, boolean isFilterExpOnly, boolean isSIFilterOnly) { Exp exp = null; Filter sIndexFilter = null; @@ -673,8 +676,7 @@ public AbstractPart buildExpr(Expr expr, String namespace, Collection ind if (!isFilterExpOnly) { sIndexFilter = getSIFilter(expr, namespace, indexes); } - } catch (NoApplicableFilterException e) { - // TODO: add cases with both Filter and Exp needed + } catch (NoApplicableFilterException ignored) { } expr.setSIndexFilter(sIndexFilter); @@ -686,6 +688,9 @@ public AbstractPart buildExpr(Expr expr, String namespace, Collection ind } private static Exp getFilterExp(Expr expr) { + // if a Filter is already set in an OR query + if (expr.getOperationType() == OR && expr.getSIndexFilter() != null) return null; + return switch (expr.getOperationType()) { case WITH_OPERANDS -> withOperandsToExp(expr); case WHEN_OPERANDS -> whenOperandsToExp(expr); @@ -696,7 +701,7 @@ private static Exp getFilterExp(Expr expr) { private static Exp withOperandsToExp(Expr expr) { List expressions = new ArrayList<>(); - WithOperands withOperandsList = (WithOperands) expr.getLeft(); // extract unary Expr operand + WithStructure withOperandsList = (WithStructure) expr.getLeft(); // extract unary Expr operand List operands = withOperandsList.getOperands(); for (WithOperand withOperand : operands) { if (!withOperand.isLastPart()) { @@ -711,7 +716,7 @@ private static Exp withOperandsToExp(Expr expr) { private static Exp whenOperandsToExp(Expr expr) { List expressions = new ArrayList<>(); - WhenOperands whenOperandsList = (WhenOperands) expr.getLeft(); // extract unary Expr operand + WhenStructure whenOperandsList = (WhenStructure) expr.getLeft(); // extract unary Expr operand List operands = whenOperandsList.getOperands(); for (AbstractPart part : operands) { expressions.add(getExp(part)); @@ -721,7 +726,7 @@ private static Exp whenOperandsToExp(Expr expr) { private static Exp exclOperandsToExp(Expr expr) { List expressions = new ArrayList<>(); - ExclusiveOperands whenOperandsList = (ExclusiveOperands) expr.getLeft(); // extract unary Expr operand + ExclusiveStructure whenOperandsList = (ExclusiveStructure) expr.getLeft(); // extract unary Expr operand List operands = whenOperandsList.getOperands(); for (Expr part : operands) { expressions.add(getExp(part)); @@ -736,8 +741,8 @@ private static Exp getExp(AbstractPart part) { return part.getExp(); } - private static Filter getSIFilter(Expr expr, String namespace, Collection indexes) { - List exprs = getExprs(expr); + private static Filter getSIFilter(Expr expr, String namespace, Map indexes) { + List exprs = flattenExprs(expr); Expr chosenExpr = chooseExpr(exprs, namespace, indexes); return chosenExpr == null ? null : getFilterOrFail(chosenExpr.getLeft(), @@ -746,29 +751,40 @@ private static Filter getSIFilter(Expr expr, String namespace, Collection ); } - private static Expr chooseExpr(List exprs, String namespace, Collection indexes) { + private static Expr chooseExpr(List exprs, String namespace, Map indexes) { if (exprs.size() == 1) return exprs.get(0); if (exprs.size() > 1 && (indexes == null || indexes.isEmpty())) return null; - Expr resultExpr = null; - int maxRatio = Integer.MIN_VALUE; + Map> exprsPerCardinality = new HashMap<>(); for (Expr expr : exprs) { BinPart binPart = getBinPart(expr); - for (Index index : indexes) { - if (binPart.getBinName().equals(index.getBin()) - && expTypeToIndexType.get(binPart.getExpType()) == index.getIndexType() - && namespace.equals(index.getNamespace()) - ) { - if (index.getBinValuesRatio() > maxRatio) { - maxRatio = index.getBinValuesRatio(); - resultExpr = expr; + Index index = indexes.get(namespace + INDEX_NAME_SEPARATOR + binPart.getBinName()); + if (index == null) continue; + if (expTypeToIndexType.get(binPart.getExpType()) == index.getIndexType()) { + List exprsList = exprsPerCardinality.get(index.getBinValuesRatio()); + if (exprsList != null) { + exprsList.add(expr); + } else { + exprsList = new ArrayList<>(); + exprsList.add(expr); } - break; // Assuming one Index corresponds to one Expr based on the criteria + exprsPerCardinality.put(index.getBinValuesRatio(), exprsList); } - } } - return resultExpr; + // Find the entry with the largest key and put it in a new Map + Map> largestCardinalityMap = exprsPerCardinality.entrySet().stream() + .max(Map.Entry.comparingByKey()) + .map(entry -> Map.of(entry.getKey(), entry.getValue())) + .orElse(Collections.emptyMap()); + List largestCardinalityExprs = largestCardinalityMap.values().iterator().next(); + if (largestCardinalityExprs.size() > 1) { + // Choosing alphabetically + return largestCardinalityExprs.stream() + .min(Comparator.comparing(expr -> getBinPart(expr).getBinName())) + .orElse(null); + } + return largestCardinalityExprs.get(0); } private static BinPart getBinPart(Expr expr) { @@ -799,13 +815,13 @@ private static BinPart getBinPart(Expr expr) { return result; } - private static List getExprs(Expr expr) { + private static List flattenExprs(Expr expr) { List results = new ArrayList<>(); - if (expr.getOperationType() == AND) { + if (expr.getOperationType() == AND || expr.getOperationType() == OR) { if (expr.getLeft() != null && expr.getLeft().getPartType() == EXPR) { Expr leftExpr = (Expr) expr.getLeft(); if (leftExpr.getOperationType() == AND || leftExpr.getOperationType() == OR) { - Stream stream = getExprs(leftExpr).stream(); + Stream stream = flattenExprs(leftExpr).stream(); results = Stream.concat(results.stream(), stream).toList(); } else { Stream stream = Stream.of(leftExpr); @@ -816,7 +832,7 @@ private static List getExprs(Expr expr) { if (expr.getRight() != null && expr.getRight().getPartType() == EXPR) { Expr rightExpr = (Expr) expr.getRight(); if (rightExpr.getOperationType() == AND || rightExpr.getOperationType() == OR) { - Stream stream = getExprs(rightExpr).stream(); + Stream stream = flattenExprs(rightExpr).stream(); results = Stream.concat(results.stream(), stream).toList(); } else { Stream stream = Stream.of(rightExpr); diff --git a/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java b/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java new file mode 100644 index 0000000..7985a41 --- /dev/null +++ b/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java @@ -0,0 +1,271 @@ +package com.aerospike.dsl.parsedExpression; + +import com.aerospike.client.exp.Exp; +import com.aerospike.client.query.Filter; +import com.aerospike.client.query.IndexType; +import com.aerospike.dsl.ParsedExpression; +import com.aerospike.dsl.index.Index; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare; + +public class LogicalParsedExpressionTests { + + @Test + void binLogical_AND_2_no_indexes() { + Filter filter = null; + Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", expected); + } + + @Test + void binLogical_AND_2_all_indexes() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(1).build() + ); + String namespace = "test1"; + Filter filter = Filter.range("intBin2", 101, Long.MAX_VALUE); + Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", namespace, indexes, expected); + } + + @Test + void binLogical_AND_2_all_indexes_no_cardinality() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).build(), + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).build() + ); + String namespace = "test1"; + // Filter is chosen alphabetically because no cardinality is given + Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); + Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", namespace, indexes, expected); + } + + @Test + void binLogical_AND_2_one_index() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build()); + String namespace = "test1"; + Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); + Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", namespace, indexes, expected); + } + + @Test + void binLogical_AND_3_all_indexes() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(1).build(), + Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).binValuesRatio(0).build() + ); + String namespace = "test1"; + Filter filter = Filter.range("intBin2", 101, Long.MAX_VALUE); + Exp exp = Exp.and( + Exp.and( + Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), + Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) + ); + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", namespace, indexes, expected); + } + + @Test + void binLogical_AND_3_all_indexes_same_cardinality() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(100).build(), + Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).binValuesRatio(100).build(), + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(100).build() + ); + String namespace = "test1"; + Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); + Exp exp = Exp.and( + Exp.and( + Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), + Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) + ); + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", namespace, indexes, expected); + } + + @Test + void binLogical_AND_3_all_indexes_no_cardinality() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).build(), + Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).build(), + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).build() + ); + String namespace = "test1"; + Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); + Exp exp = Exp.and( + Exp.and( + Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), + Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) + ); + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", namespace, indexes, expected); + } + + @Test + void binLogical_AND_3_all_indexes_partial_data() { + List indexes = List.of( + Index.builder().bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), + Index.builder().namespace("test1").bin("intBin2").binValuesRatio(1).build(), + Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.STRING).binValuesRatio(0).build(), + // The only matching index with full data + Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).binValuesRatio(0).build() + ); + String namespace = "test1"; + // The only matching index with full data is for intBin3 + Filter filter = Filter.range("intBin3", 101, Long.MAX_VALUE); + Exp exp = Exp.and( + Exp.and( + Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), + Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) + ); + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", namespace, indexes, expected); + } + + @Test + void binLogical_AND_3_two_indexes() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(1).build(), + Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).binValuesRatio(0).build() + ); + String namespace = "test1"; + Filter filter = Filter.range("intBin2", 101, Long.MAX_VALUE); + Exp exp = Exp.and( + Exp.and( + Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), + Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) + ); + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", namespace, indexes, expected); + } + + @Test + void binLogical_OR_2_no_indexes() { + Filter filter = null; + Exp exp = Exp.or(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", expected); + } + + @Test + void binLogical_OR_2_all_indexes() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(1).build() + ); + String namespace = "test1"; + Filter filter = Filter.range("intBin2", 101, Long.MAX_VALUE); + Exp exp = null; + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", namespace, indexes, expected); + } + + @Test + void binLogical_OR_2_one_index() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build() + ); + String namespace = "test1"; + Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); + Exp exp = null; + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", namespace, indexes, expected); + } + + @Test + void binLogical_OR_3_all_indexes() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(1).build(), + Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).binValuesRatio(0).build() + ); + String namespace = "test1"; + Filter filter = Filter.range("intBin2", 101, Long.MAX_VALUE); + Exp exp = null; + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100 or $.intBin3 > 100", namespace, indexes, expected); + } + + @Test + void binLogical_OR_3_all_indexes_no_cardinality() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).build(), + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).build(), + Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).build() + ); + String namespace = "test1"; + Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); + Exp exp = null; + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100 or $.intBin3 > 100", namespace, indexes, expected); + } + + @Test + void binLogical_OR_3_all_indexes_same_cardinality() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(100).build(), + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(100).build(), + Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).binValuesRatio(100).build() + ); + String namespace = "test1"; + Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); + Exp exp = null; + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100 or $.intBin3 > 100", namespace, indexes, expected); + } + + @Test + void binLogical_AND_OR_indexed() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), + Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).binValuesRatio(1).build() + ); + String namespace = "test1"; + Filter filter = Filter.range("intBin3", 101, Long.MAX_VALUE); + Exp exp = null; + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 or $.intBin3 > 100", namespace, indexes, expected); + parseExpressionAndCompare("($.intBin1 > 100 and $.intBin2 > 100) or $.intBin3 > 100", namespace, indexes, expected); + } + + @Disabled // TODO: complex logical structures + @Test + void binLogical_AND_indexed_OR() { + List indexes = List.of( + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(1).build(), + Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).binValuesRatio(0).build() + ); + String namespace = "test1"; + Filter filter = Filter.range("intBin3", 101, Long.MAX_VALUE); + Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100)));; + ParsedExpression expected = new ParsedExpression(exp, filter); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 or $.intBin3 > 100", namespace, indexes, expected); + parseExpressionAndCompare("($.intBin1 > 100 and $.intBin2 > 100) or $.intBin3 > 100", namespace, indexes, expected); + } +} diff --git a/src/test/java/com/aerospike/dsl/util/TestUtils.java b/src/test/java/com/aerospike/dsl/util/TestUtils.java index 9a5587b..e34a739 100644 --- a/src/test/java/com/aerospike/dsl/util/TestUtils.java +++ b/src/test/java/com/aerospike/dsl/util/TestUtils.java @@ -4,6 +4,7 @@ import com.aerospike.client.exp.Expression; import com.aerospike.client.query.Filter; import com.aerospike.dsl.DSLParserImpl; +import com.aerospike.dsl.ParsedExpression; import com.aerospike.dsl.index.Index; import lombok.experimental.UtilityClass; @@ -39,4 +40,17 @@ public static void parseFilterAndCompare(String input, String namespace, List indexes, + ParsedExpression expected) { + ParsedExpression actualExpression = parser.parseDslExpression(input, namespace, indexes); + assertEquals(actualExpression.getFilterExpression(), expected.getFilterExpression()); + assertEquals(actualExpression.getSIFilter(), expected.getSIFilter()); + } } From fcaa1599897b60ea0c55fc88b5bf280779ce94f7 Mon Sep 17 00:00:00 2001 From: agrgr Date: Sun, 27 Apr 2025 09:56:13 +0300 Subject: [PATCH 06/20] code format --- .../java/com/aerospike/dsl/model/BinPart.java | 3 +- .../aerospike/dsl/model/BooleanOperand.java | 1 + .../java/com/aerospike/dsl/model/Expr.java | 6 ++-- .../com/aerospike/dsl/model/FloatOperand.java | 3 +- .../com/aerospike/dsl/model/IntOperand.java | 3 +- .../com/aerospike/dsl/model/ListOperand.java | 3 +- .../com/aerospike/dsl/model/MapOperand.java | 3 +- .../aerospike/dsl/model/MetadataOperand.java | 3 +- .../aerospike/dsl/model/StringOperand.java | 5 +++ .../aerospike/dsl/model/VariableOperand.java | 3 +- .../visitor/ExpressionConditionVisitor.java | 6 ++-- .../aerospike/dsl/visitor/VisitorUtils.java | 33 ++++++++++++------- 12 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/aerospike/dsl/model/BinPart.java b/src/main/java/com/aerospike/dsl/model/BinPart.java index 2bedcdb..04cb9e4 100644 --- a/src/main/java/com/aerospike/dsl/model/BinPart.java +++ b/src/main/java/com/aerospike/dsl/model/BinPart.java @@ -20,6 +20,7 @@ public void updateExp(Exp.Type expType) { } public Exp getExp() { - return Exp.bin(this.binName, expType); + if (exp == null) exp = Exp.bin(this.binName, expType); + return exp; } } diff --git a/src/main/java/com/aerospike/dsl/model/BooleanOperand.java b/src/main/java/com/aerospike/dsl/model/BooleanOperand.java index c072f58..42dea15 100644 --- a/src/main/java/com/aerospike/dsl/model/BooleanOperand.java +++ b/src/main/java/com/aerospike/dsl/model/BooleanOperand.java @@ -14,6 +14,7 @@ public BooleanOperand(Boolean value) { } public Exp getExp() { + if (exp == null) exp = Exp.val(value); return Exp.val(value); } } diff --git a/src/main/java/com/aerospike/dsl/model/Expr.java b/src/main/java/com/aerospike/dsl/model/Expr.java index 0ab9363..e6d1b60 100644 --- a/src/main/java/com/aerospike/dsl/model/Expr.java +++ b/src/main/java/com/aerospike/dsl/model/Expr.java @@ -51,8 +51,8 @@ public enum ExprPartsOperation { GTEQ, LT, LTEQ, - WITH_OPERANDS, // unary - WHEN_OPERANDS, // unary - EXCLUSIVE_OPERANDS // unary + WITH_STRUCTURE_HOLDER, // unary + WHEN_STRUCTURE_HOLDER, // unary + EXCLUSIVE_STRUCTURE_HOLDER // unary } } diff --git a/src/main/java/com/aerospike/dsl/model/FloatOperand.java b/src/main/java/com/aerospike/dsl/model/FloatOperand.java index 51120b3..b8e6bdc 100644 --- a/src/main/java/com/aerospike/dsl/model/FloatOperand.java +++ b/src/main/java/com/aerospike/dsl/model/FloatOperand.java @@ -14,6 +14,7 @@ public FloatOperand(Double value) { } public Exp getExp() { - return Exp.val(value); + if (exp == null) exp = Exp.val(value); + return exp; } } diff --git a/src/main/java/com/aerospike/dsl/model/IntOperand.java b/src/main/java/com/aerospike/dsl/model/IntOperand.java index 9436abb..93abf3e 100644 --- a/src/main/java/com/aerospike/dsl/model/IntOperand.java +++ b/src/main/java/com/aerospike/dsl/model/IntOperand.java @@ -14,6 +14,7 @@ public IntOperand(Long value) { } public Exp getExp() { - return Exp.val(value); + if (exp == null) exp = Exp.val(value); + return exp; } } diff --git a/src/main/java/com/aerospike/dsl/model/ListOperand.java b/src/main/java/com/aerospike/dsl/model/ListOperand.java index 5a55728..9369b5b 100644 --- a/src/main/java/com/aerospike/dsl/model/ListOperand.java +++ b/src/main/java/com/aerospike/dsl/model/ListOperand.java @@ -16,6 +16,7 @@ public ListOperand(List list) { } public Exp getExp() { - return Exp.val(value); + if (exp == null) exp = Exp.val(value); + return exp; } } diff --git a/src/main/java/com/aerospike/dsl/model/MapOperand.java b/src/main/java/com/aerospike/dsl/model/MapOperand.java index c5e9bcc..f75fba4 100644 --- a/src/main/java/com/aerospike/dsl/model/MapOperand.java +++ b/src/main/java/com/aerospike/dsl/model/MapOperand.java @@ -16,6 +16,7 @@ public MapOperand(TreeMap map) { } public Exp getExp() { - return Exp.val(value); + if (exp == null) exp = Exp.val(value); + return exp; } } diff --git a/src/main/java/com/aerospike/dsl/model/MetadataOperand.java b/src/main/java/com/aerospike/dsl/model/MetadataOperand.java index 9f1fd09..c99fd8c 100644 --- a/src/main/java/com/aerospike/dsl/model/MetadataOperand.java +++ b/src/main/java/com/aerospike/dsl/model/MetadataOperand.java @@ -64,6 +64,7 @@ public enum MetadataReturnType { } public Exp getExp() { - return constructMetadataExp(functionName, parameter); + if (exp == null) exp = constructMetadataExp(functionName, parameter); + return exp; } } diff --git a/src/main/java/com/aerospike/dsl/model/StringOperand.java b/src/main/java/com/aerospike/dsl/model/StringOperand.java index 4adb601..3409bbd 100644 --- a/src/main/java/com/aerospike/dsl/model/StringOperand.java +++ b/src/main/java/com/aerospike/dsl/model/StringOperand.java @@ -19,6 +19,11 @@ public StringOperand(String string) { } public Exp getExp() { + if (exp == null) exp = getStringExp(); + return exp; + } + + private Exp getStringExp() { if (isBlob) { byte[] byteValue = Base64.getDecoder().decode(value); return Exp.val(byteValue); diff --git a/src/main/java/com/aerospike/dsl/model/VariableOperand.java b/src/main/java/com/aerospike/dsl/model/VariableOperand.java index c5da047..7ad3ff7 100644 --- a/src/main/java/com/aerospike/dsl/model/VariableOperand.java +++ b/src/main/java/com/aerospike/dsl/model/VariableOperand.java @@ -14,6 +14,7 @@ public VariableOperand(String name) { } public Exp getExp() { - return Exp.var(name); + if (exp == null) exp = Exp.var(name); + return exp; } } diff --git a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java index 01e1bd4..4b426d0 100644 --- a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java +++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java @@ -50,7 +50,7 @@ public AbstractPart visitWithExpression(ConditionParser.WithExpressionContext ct } // last expression is the action (described after "do") expressions.add(new WithOperand(visit(ctx.expression()), true)); - return new Expr(new WithStructure(expressions), Expr.ExprPartsOperation.WITH_OPERANDS); + return new Expr(new WithStructure(expressions), Expr.ExprPartsOperation.WITH_STRUCTURE_HOLDER); } @Override @@ -65,7 +65,7 @@ public AbstractPart visitWhenExpression(ConditionParser.WhenExpressionContext ct } // visit default parts.add(visit(ctx.expression())); - return new Expr(new WhenStructure(parts), Expr.ExprPartsOperation.WHEN_OPERANDS); + return new Expr(new WhenStructure(parts), Expr.ExprPartsOperation.WHEN_STRUCTURE_HOLDER); } @Override @@ -106,7 +106,7 @@ public AbstractPart visitExclusiveExpression(ConditionParser.ExclusiveExpression logicalSetBinAsBooleanExpr(expr); expressions.add(expr); } - return new Expr(new ExclusiveStructure(expressions), Expr.ExprPartsOperation.EXCLUSIVE_OPERANDS); + return new Expr(new ExclusiveStructure(expressions), Expr.ExprPartsOperation.EXCLUSIVE_STRUCTURE_HOLDER); } @Override diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index 3a12858..db5deaa 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -33,8 +33,17 @@ public class VisitorUtils { public final String INDEX_NAME_SEPARATOR = "||||"; - private final Map expTypeToIndexType = Map.of(Exp.Type.INT, IndexType.NUMERIC, - Exp.Type.STRING, IndexType.STRING, Exp.Type.BLOB, IndexType.BLOB); + private final Map expTypeToIndexType = Map.of( + Exp.Type.INT, IndexType.NUMERIC, + Exp.Type.STRING, IndexType.STRING, + Exp.Type.BLOB, IndexType.BLOB + ); + private final List CTRL_STRUCTURE_HOLDERS = List.of( + WITH_STRUCTURE_HOLDER, + WHEN_STRUCTURE_HOLDER, + EXCLUSIVE_STRUCTURE_HOLDER + ); + protected enum FilterOperationType { GT, @@ -151,9 +160,9 @@ static Exp exprToExp(Expr expr) { private static Exp getFilterExpression(Expr expr, AbstractPart part, AbstractPart.PartType secondPartType) { Exp leftExp = null; if (part.getPartType() == EXPR) { - List ops = List.of(WITH_OPERANDS, WHEN_OPERANDS, EXCLUSIVE_OPERANDS); if (expr.isUnary()) { - if (!ops.contains(expr.getOperationType())) { + if (!CTRL_STRUCTURE_HOLDERS.contains(expr.getOperationType())) { + // If the expression holds a control structure leftExp = getUnaryExpOrFail(part, getUnaryExpOperator(expr.getOperationType())); part.setExp(leftExp); } else { @@ -692,14 +701,14 @@ private static Exp getFilterExp(Expr expr) { if (expr.getOperationType() == OR && expr.getSIndexFilter() != null) return null; return switch (expr.getOperationType()) { - case WITH_OPERANDS -> withOperandsToExp(expr); - case WHEN_OPERANDS -> whenOperandsToExp(expr); - case EXCLUSIVE_OPERANDS -> exclOperandsToExp(expr); + case WITH_STRUCTURE_HOLDER -> withStructureHolderToExp(expr); + case WHEN_STRUCTURE_HOLDER -> whenStructureHolderToExp(expr); + case EXCLUSIVE_STRUCTURE_HOLDER -> exclStructureHolderToExp(expr); default -> exprToExp(expr); }; } - private static Exp withOperandsToExp(Expr expr) { + private static Exp withStructureHolderToExp(Expr expr) { List expressions = new ArrayList<>(); WithStructure withOperandsList = (WithStructure) expr.getLeft(); // extract unary Expr operand List operands = withOperandsList.getOperands(); @@ -714,7 +723,7 @@ private static Exp withOperandsToExp(Expr expr) { return Exp.let(expressions.toArray(new Exp[0])); } - private static Exp whenOperandsToExp(Expr expr) { + private static Exp whenStructureHolderToExp(Expr expr) { List expressions = new ArrayList<>(); WhenStructure whenOperandsList = (WhenStructure) expr.getLeft(); // extract unary Expr operand List operands = whenOperandsList.getOperands(); @@ -724,7 +733,7 @@ private static Exp whenOperandsToExp(Expr expr) { return Exp.cond(expressions.toArray(new Exp[0])); } - private static Exp exclOperandsToExp(Expr expr) { + private static Exp exclStructureHolderToExp(Expr expr) { List expressions = new ArrayList<>(); ExclusiveStructure whenOperandsList = (ExclusiveStructure) expr.getLeft(); // extract unary Expr operand List operands = whenOperandsList.getOperands(); @@ -743,7 +752,7 @@ private static Exp getExp(AbstractPart part) { private static Filter getSIFilter(Expr expr, String namespace, Map indexes) { List exprs = flattenExprs(expr); - Expr chosenExpr = chooseExpr(exprs, namespace, indexes); + Expr chosenExpr = chooseExprForFilter(exprs, namespace, indexes); return chosenExpr == null ? null : getFilterOrFail(chosenExpr.getLeft(), chosenExpr.getRight(), @@ -751,7 +760,7 @@ private static Filter getSIFilter(Expr expr, String namespace, Map exprs, String namespace, Map indexes) { + private static Expr chooseExprForFilter(List exprs, String namespace, Map indexes) { if (exprs.size() == 1) return exprs.get(0); if (exprs.size() > 1 && (indexes == null || indexes.isEmpty())) return null; From 16c4e0f128e0f77ce8368949adac55d633b02ad1 Mon Sep 17 00:00:00 2001 From: agrgr Date: Mon, 28 Apr 2025 13:20:28 +0300 Subject: [PATCH 07/20] distribute models into packages, always build a Pair, add resulting tree and pair of results to ParsedExpression, refactoring --- .../java/com/aerospike/dsl/DSLParser.java | 182 +----------------- .../java/com/aerospike/dsl/DSLParserImpl.java | 73 ++----- src/main/java/com/aerospike/dsl/Index.java | 34 ++++ src/main/java/com/aerospike/dsl/Pair.java | 12 ++ .../com/aerospike/dsl/ParsedExpression.java | 53 ++--- .../java/com/aerospike/dsl/index/Index.java | 20 -- .../com/aerospike/dsl/model/AbstractPart.java | 6 +- .../dsl/model/ExclusiveStructure.java | 16 -- .../{Expr.java => ExpressionContainer.java} | 20 +- .../aerospike/dsl/model/MetadataOperand.java | 11 +- .../dsl/model/{ => cdt}/ListOperand.java | 7 +- .../dsl/model/{ => cdt}/MapOperand.java | 7 +- .../dsl/model/{cdt => cdt_part}/CdtPart.java | 17 +- .../{cdt => cdt_part}/list/ListIndex.java | 4 +- .../list/ListIndexRange.java | 4 +- .../{cdt => cdt_part}/list/ListPart.java | 6 +- .../{cdt => cdt_part}/list/ListRank.java | 4 +- .../{cdt => cdt_part}/list/ListRankRange.java | 4 +- .../list/ListRankRangeRelative.java | 4 +- .../list/ListTypeDesignator.java | 6 +- .../{cdt => cdt_part}/list/ListValue.java | 4 +- .../{cdt => cdt_part}/list/ListValueList.java | 4 +- .../list/ListValueRange.java | 4 +- .../model/{cdt => cdt_part}/map/MapIndex.java | 4 +- .../{cdt => cdt_part}/map/MapIndexRange.java | 4 +- .../map/MapIndexRangeRelative.java | 4 +- .../model/{cdt => cdt_part}/map/MapKey.java | 4 +- .../{cdt => cdt_part}/map/MapKeyList.java | 4 +- .../{cdt => cdt_part}/map/MapKeyRange.java | 4 +- .../model/{cdt => cdt_part}/map/MapPart.java | 6 +- .../model/{cdt => cdt_part}/map/MapRank.java | 4 +- .../{cdt => cdt_part}/map/MapRankRange.java | 4 +- .../map/MapRankRangeRelative.java | 4 +- .../map/MapTypeDesignator.java | 6 +- .../model/{cdt => cdt_part}/map/MapValue.java | 4 +- .../{cdt => cdt_part}/map/MapValueList.java | 4 +- .../{cdt => cdt_part}/map/MapValueRange.java | 4 +- .../ctrl_structure/ExclusiveStructure.java | 18 ++ .../{ => ctrl_structure}/WhenStructure.java | 3 +- .../{ => ctrl_structure}/WithOperand.java | 3 +- .../{ => ctrl_structure}/WithStructure.java | 3 +- .../dsl/model/{ => path}/BasePath.java | 7 +- .../dsl/model/{ => path}/BinPart.java | 8 +- .../{PathOperand.java => path/Path.java} | 15 +- .../dsl/model/{ => path}/PathFunction.java | 3 +- .../model/{ => simple}/BooleanOperand.java | 5 +- .../dsl/model/{ => simple}/FloatOperand.java | 7 +- .../dsl/model/{ => simple}/IntOperand.java | 7 +- .../dsl/model/{ => simple}/StringOperand.java | 9 +- .../model/{ => simple}/VariableOperand.java | 6 +- .../aerospike/dsl/util/PathOperandUtils.java | 26 ++- .../com/aerospike/dsl/util/TypeUtils.java | 4 +- .../visitor/ExpressionConditionVisitor.java | 114 +++++------ .../aerospike/dsl/visitor/VisitorUtils.java | 179 +++++++++-------- .../ArithmeticExpressionsTests.java | 66 +++---- .../dsl/expression/BinExpressionsTests.java | 48 ++--- .../dsl/expression/CastingTests.java | 12 +- .../expression/ControlStructuresTests.java | 14 +- .../dsl/expression/ExplicitTypesTests.java | 138 ++++++------- .../dsl/expression/ImplicitTypesTests.java | 32 +-- .../dsl/expression/ListExpressionsTests.java | 122 ++++++------ .../expression/LogicalExpressionsTests.java | 32 +-- .../MapAndListExpressionsTests.java | 24 +-- .../dsl/expression/MapExpressionsTests.java | 162 ++++++++-------- .../dsl/expression/RecordMetadataTests.java | 48 ++--- .../aerospike/dsl/filter/BinFiltersTests.java | 2 +- .../dsl/filter/ExplicitTypesFiltersTests.java | 6 +- .../LogicalParsedExpressionTests.java | 141 +++++++------- .../com/aerospike/dsl/util/TestUtils.java | 41 ++-- 69 files changed, 842 insertions(+), 1025 deletions(-) create mode 100644 src/main/java/com/aerospike/dsl/Index.java create mode 100644 src/main/java/com/aerospike/dsl/Pair.java delete mode 100644 src/main/java/com/aerospike/dsl/index/Index.java delete mode 100644 src/main/java/com/aerospike/dsl/model/ExclusiveStructure.java rename src/main/java/com/aerospike/dsl/model/{Expr.java => ExpressionContainer.java} (61%) rename src/main/java/com/aerospike/dsl/model/{ => cdt}/ListOperand.java (69%) rename src/main/java/com/aerospike/dsl/model/{ => cdt}/MapOperand.java (70%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/CdtPart.java (53%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/list/ListIndex.java (90%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/list/ListIndexRange.java (96%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/list/ListPart.java (89%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/list/ListRank.java (90%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/list/ListRankRange.java (96%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/list/ListRankRangeRelative.java (97%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/list/ListTypeDesignator.java (89%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/list/ListValue.java (94%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/list/ListValueList.java (96%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/list/ListValueRange.java (95%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapIndex.java (90%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapIndexRange.java (96%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapIndexRangeRelative.java (97%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapKey.java (93%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapKeyList.java (95%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapKeyRange.java (96%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapPart.java (90%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapRank.java (90%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapRankRange.java (96%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapRankRangeRelative.java (97%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapTypeDesignator.java (88%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapValue.java (94%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapValueList.java (96%) rename src/main/java/com/aerospike/dsl/model/{cdt => cdt_part}/map/MapValueRange.java (96%) create mode 100644 src/main/java/com/aerospike/dsl/model/ctrl_structure/ExclusiveStructure.java rename src/main/java/com/aerospike/dsl/model/{ => ctrl_structure}/WhenStructure.java (75%) rename src/main/java/com/aerospike/dsl/model/{ => ctrl_structure}/WithOperand.java (86%) rename src/main/java/com/aerospike/dsl/model/{ => ctrl_structure}/WithStructure.java (75%) rename src/main/java/com/aerospike/dsl/model/{ => path}/BasePath.java (79%) rename src/main/java/com/aerospike/dsl/model/{ => path}/BinPart.java (68%) rename src/main/java/com/aerospike/dsl/model/{PathOperand.java => path/Path.java} (79%) rename src/main/java/com/aerospike/dsl/model/{ => path}/PathFunction.java (93%) rename src/main/java/com/aerospike/dsl/model/{ => simple}/BooleanOperand.java (73%) rename src/main/java/com/aerospike/dsl/model/{ => simple}/FloatOperand.java (66%) rename src/main/java/com/aerospike/dsl/model/{ => simple}/IntOperand.java (66%) rename src/main/java/com/aerospike/dsl/model/{ => simple}/StringOperand.java (80%) rename src/main/java/com/aerospike/dsl/model/{ => simple}/VariableOperand.java (72%) diff --git a/src/main/java/com/aerospike/dsl/DSLParser.java b/src/main/java/com/aerospike/dsl/DSLParser.java index 77c4dd8..f1b28cd 100644 --- a/src/main/java/com/aerospike/dsl/DSLParser.java +++ b/src/main/java/com/aerospike/dsl/DSLParser.java @@ -1,10 +1,6 @@ package com.aerospike.dsl; -import com.aerospike.client.exp.Exp; -import com.aerospike.client.exp.Expression; -import com.aerospike.client.query.Filter; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.index.Index; import java.util.Collection; @@ -88,11 +84,11 @@ public interface DSLParser { * * * - * @param input String consisting of dot separated elements, typically bin name and optional context - * @return ParsedExpression object + * @param input String consisting of dot separated elements, typically bin name and optional context + * @return ParsedExpression object * @throws AerospikeDSLException in case of invalid syntax */ - ParsedExpression parseDslExpression(String input); + ParsedExpression parseExpression(String input); /** * Parse String DSL path into Aerospike filter Expression. @@ -162,177 +158,9 @@ public interface DSLParser { * * @param input String consisting of dot separated elements, typically bin name and optional context * @param namespace Namespace to use + * @param indexes Collection of {@link Index} objects that represent created secondary indexes * @return ParsedExpression object * @throws AerospikeDSLException in case of or invalid syntax */ - ParsedExpression parseDslExpression(String input, String namespace, Collection indexes); - - /** - * Parse String DSL path into Aerospike filter Expression. - *

- * Examples: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Path element
$.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
- *
- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
A nested element
$.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 {@link Expression} for filtering records - * @throws AerospikeDSLException in case of or invalid syntax - */ - Expression parseFilterExpression(String input); - - /** - * Parse String DSL path into Aerospike filter Exp. - *

- * Examples: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Path element
$.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
- *
- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
A nested element
$.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 {@link Exp} for filtering records - * @throws AerospikeDSLException in case of or invalid syntax - */ - Exp parseFilterExp(String input); - - /** - * Parse String DSL path into Aerospike secondary index Filter. - *

- * Examples: - * - * - * - * - * - * - * - * - * - * - * - *
Filter for a bin
$.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 - * @param namespace Namespace to use - * @param indexes List of indexes to choose from. Can be null - * @return List of Filter objects - * @throws AerospikeDSLException in case of invalid syntax - */ - Filter parseFilter(String input, String namespace, Collection indexes); + ParsedExpression parseExpression(String input, String namespace, Collection indexes); } diff --git a/src/main/java/com/aerospike/dsl/DSLParserImpl.java b/src/main/java/com/aerospike/dsl/DSLParserImpl.java index 587aa5f..4a796f5 100644 --- a/src/main/java/com/aerospike/dsl/DSLParserImpl.java +++ b/src/main/java/com/aerospike/dsl/DSLParserImpl.java @@ -1,14 +1,12 @@ package com.aerospike.dsl; 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.exception.NoApplicableFilterException; -import com.aerospike.dsl.index.Index; import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.Expr; +import com.aerospike.dsl.model.ExpressionContainer; import com.aerospike.dsl.visitor.ExpressionConditionVisitor; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; @@ -18,38 +16,23 @@ import java.util.HashMap; import java.util.Map; -import static com.aerospike.dsl.model.AbstractPart.PartType.EXPR; +import static com.aerospike.dsl.model.AbstractPart.PartType.EXPRESSION_CONTAINER; import static com.aerospike.dsl.visitor.VisitorUtils.*; public class DSLParserImpl implements DSLParser { @Beta - public ParsedExpression parseDslExpression(String input) { + public ParsedExpression parseExpression(String input) { ParseTree parseTree = getParseTree(input); return getParsedExpression(parseTree, null, null); } @Beta - public ParsedExpression parseDslExpression(String input, String namespace, Collection indexes) { + public ParsedExpression parseExpression(String input, String namespace, Collection indexes) { ParseTree parseTree = getParseTree(input); return getParsedExpression(parseTree, namespace, indexes); } - @Beta - public Expression parseFilterExpression(String input) { - return getFilterExpression(getParseTree(input), null, null); - } - - @Beta - public Exp parseFilterExp(String input) { - return getFilterExp(getParseTree(input), null, null); - } - - @Beta - public Filter parseFilter(String input, String namespace, Collection indexes) { - return getSIFilter(getParseTree(input), namespace, indexes); - } - private ParseTree getParseTree(String input) { ConditionLexer lexer = new ConditionLexer(CharStreams.fromString(input)); ConditionParser parser = new ConditionParser(new CommonTokenStream(lexer)); @@ -57,12 +40,7 @@ private ParseTree getParseTree(String input) { } private ParsedExpression getParsedExpression(ParseTree parseTree, String namespace, Collection indexes) { - return getParsedExpression(parseTree, namespace, indexes, false, false); - } - - private ParsedExpression getParsedExpression(ParseTree parseTree, String namespace, Collection indexes, - boolean isFilterExpOnly, boolean isSIFilterOnly) { - boolean isEmptyList = false; + boolean hasFilterParsingError = false; AbstractPart resultingPart = null; Map indexesMap = new HashMap<>(); if (indexes != null && !indexes.isEmpty()) { @@ -70,41 +48,32 @@ private ParsedExpression getParsedExpression(ParseTree parseTree, String namespa } try { resultingPart = - new ExpressionConditionVisitor(isFilterExpOnly, isSIFilterOnly).visit(parseTree); + new ExpressionConditionVisitor().visit(parseTree); } catch (NoApplicableFilterException e) { - isEmptyList = true; + hasFilterParsingError = true; } - // When we can't identify a specific case of syntax error, we throw a generic DSL syntax error instead of NPE - if (!isEmptyList && resultingPart == null) { + // When we can't identify a specific case of syntax error, we throw a generic DSL syntax error + if (!hasFilterParsingError && resultingPart == null) { throw new AerospikeDSLException("Could not parse given input, wrong syntax"); } + // Transfer the parsed tree along with namespace and indexes Map + return new ParsedExpression(resultingPart, namespace, indexesMap); + } + public static Pair getResultPair(AbstractPart resultingPart, String namespace, + Map indexesMap) { if (resultingPart != null) { - if (resultingPart.getPartType() == EXPR) { + if (resultingPart.getPartType() == EXPRESSION_CONTAINER) { AbstractPart result = - buildExpr((Expr) resultingPart, namespace, indexesMap, isFilterExpOnly, isSIFilterOnly); - return new ParsedExpression(result.getExp(), result.getSIndexFilter()); + buildExpr((ExpressionContainer) resultingPart, namespace, indexesMap); + return new Pair<>(result.getFilter(), result.getExp()); } else { - Filter filter = null; - if (!isFilterExpOnly) filter = resultingPart.getSIndexFilter(); - Exp exp = null; - if (!isSIFilterOnly) exp = resultingPart.getExp(); - return new ParsedExpression(exp, filter); + Filter filter = resultingPart.getFilter(); + Exp exp = resultingPart.getExp(); + return new Pair<>(filter, exp); } } - return new ParsedExpression(null, null); - } - - private Exp getFilterExp(ParseTree parseTree, String namespace, Collection indexes) { - return getParsedExpression(parseTree, namespace, indexes, true, false).getFilterExp(); - } - - private Expression getFilterExpression(ParseTree parseTree, String namespace, Collection indexes) { - return getParsedExpression(parseTree, namespace, indexes, true, false).getFilterExpression(); - } - - private Filter getSIFilter(ParseTree parseTree, String namespace, Collection indexes) { - return getParsedExpression(parseTree, namespace, indexes, false, true).getSIFilter(); + return new Pair<>(null, null); } } diff --git a/src/main/java/com/aerospike/dsl/Index.java b/src/main/java/com/aerospike/dsl/Index.java new file mode 100644 index 0000000..7c75761 --- /dev/null +++ b/src/main/java/com/aerospike/dsl/Index.java @@ -0,0 +1,34 @@ +package com.aerospike.dsl; + +import com.aerospike.client.query.IndexType; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +/** + * This class represents a secondary index created in the cluster. + */ +@Builder +@EqualsAndHashCode +@Getter +public class Index { + + /** + * Namespace of the indexed bin + */ + private final String namespace; + /** + * Name of the indexed bin + */ + private final String bin; + /** + * {@link IndexType} of the index + */ + private final IndexType indexType; + /** + * Cardinality of the index calculated using "sindex-stat" command and looking at the ratio of entries + * to unique bin values for the given secondary index on the node (entries_per_bval) + * + */ + private int binValuesRatio; +} diff --git a/src/main/java/com/aerospike/dsl/Pair.java b/src/main/java/com/aerospike/dsl/Pair.java new file mode 100644 index 0000000..86b6748 --- /dev/null +++ b/src/main/java/com/aerospike/dsl/Pair.java @@ -0,0 +1,12 @@ +package com.aerospike.dsl; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class Pair { + + A filter; + B exp; +} diff --git a/src/main/java/com/aerospike/dsl/ParsedExpression.java b/src/main/java/com/aerospike/dsl/ParsedExpression.java index ead132e..582c102 100644 --- a/src/main/java/com/aerospike/dsl/ParsedExpression.java +++ b/src/main/java/com/aerospike/dsl/ParsedExpression.java @@ -5,52 +5,37 @@ 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.Getter; + +import java.util.Map; /** - * A class to store the results of DSL expression parsing: secondary index {@link Filter} or/and filter {@link Expression}. - *
- * Expression exists as long as DSL input String is valid. - *
- * List of Filters can be an empty if no suitable secondary index Filter was found. + * A class to build and store the results of DSL expression parsing: secondary index {@link Filter} + * and/or filter {@link Exp} and {@link Expression}. */ @Beta -@SuppressWarnings("LombokGetterMayBeUsed") +@Getter public class ParsedExpression { - private final Exp filterExp; - private Expression filterExpression; - private final Filter siFilter; - - public ParsedExpression(Exp filterExp, Filter siFilter) { - this.filterExp = filterExp; - this.siFilter = siFilter; - } + private final AbstractPart resultingPart; + private final String namespace; + private final Map indexesMap; + private Pair resultPair; - /** - * @return filter {@link Expression}. Can be null - * @throws AerospikeDSLException If there was an error - */ - public Expression getFilterExpression() { - if (filterExp == null) { - return null; - } - if (filterExpression == null) filterExpression = Exp.build(filterExp); - return filterExpression; + public ParsedExpression(AbstractPart resultingPart, String namespace, Map indexesMap) { + this.resultingPart = resultingPart; + this.namespace = namespace; + this.indexesMap = indexesMap; } /** - * @return filter {@link Exp}. Can be null + * @return Pair of secondary index {@link Filter} and filter {@link Exp}. Each can be null in case of an invalid or + * not supported DSL string * @throws AerospikeDSLException If there was an error */ - public Exp getFilterExp() { - return filterExp; - } - - /** - * @return secondary index {@link Filter}. Can be null - */ - public Filter getSIFilter() { - return siFilter; + public Pair getResultPair() { + return DSLParserImpl.getResultPair(resultingPart, namespace, indexesMap); } } diff --git a/src/main/java/com/aerospike/dsl/index/Index.java b/src/main/java/com/aerospike/dsl/index/Index.java deleted file mode 100644 index cfd7a58..0000000 --- a/src/main/java/com/aerospike/dsl/index/Index.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.aerospike.dsl.index; - -import com.aerospike.client.query.IndexType; -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Getter; - -/** - * This class represents a secondary index created in the cluster. - */ -@Builder -@EqualsAndHashCode -@Getter -public class Index { - - private final String namespace; - private final String bin; - private final IndexType indexType; - private int binValuesRatio; -} diff --git a/src/main/java/com/aerospike/dsl/model/AbstractPart.java b/src/main/java/com/aerospike/dsl/model/AbstractPart.java index 037ddc5..fad7d71 100644 --- a/src/main/java/com/aerospike/dsl/model/AbstractPart.java +++ b/src/main/java/com/aerospike/dsl/model/AbstractPart.java @@ -12,7 +12,7 @@ public abstract class AbstractPart { protected Exp.Type expType; protected PartType partType; protected Exp exp; - protected Filter sIndexFilter; + protected Filter filter; protected AbstractPart(PartType partType) { this.partType = partType; @@ -21,7 +21,7 @@ protected AbstractPart(PartType partType) { protected AbstractPart(PartType partType, Filter filter) { this.partType = partType; - this.sIndexFilter = filter; + this.filter = filter; } public enum PartType { @@ -42,7 +42,7 @@ public enum PartType { PATH_OPERAND, PATH_FUNCTION, METADATA_OPERAND, - EXPR, + EXPRESSION_CONTAINER, VARIABLE_OPERAND } } diff --git a/src/main/java/com/aerospike/dsl/model/ExclusiveStructure.java b/src/main/java/com/aerospike/dsl/model/ExclusiveStructure.java deleted file mode 100644 index 96c2c0e..0000000 --- a/src/main/java/com/aerospike/dsl/model/ExclusiveStructure.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.aerospike.dsl.model; - -import lombok.Getter; - -import java.util.List; - -@Getter -public class ExclusiveStructure extends AbstractPart { - - private final List operands; - - public ExclusiveStructure(List operands) { - super(PartType.EXCLUSIVE_STRUCTURE); - this.operands = operands; - } -} diff --git a/src/main/java/com/aerospike/dsl/model/Expr.java b/src/main/java/com/aerospike/dsl/model/ExpressionContainer.java similarity index 61% rename from src/main/java/com/aerospike/dsl/model/Expr.java rename to src/main/java/com/aerospike/dsl/model/ExpressionContainer.java index e6d1b60..c0772d4 100644 --- a/src/main/java/com/aerospike/dsl/model/Expr.java +++ b/src/main/java/com/aerospike/dsl/model/ExpressionContainer.java @@ -3,28 +3,28 @@ import lombok.Getter; @Getter -public class Expr extends AbstractPart { +public class ExpressionContainer extends AbstractPart { protected AbstractPart left; protected AbstractPart right; private ExprPartsOperation operationType; private final boolean isUnary; - public Expr() { - super(PartType.EXPR); + public ExpressionContainer() { + super(PartType.EXPRESSION_CONTAINER); this.isUnary = false; } - public Expr(AbstractPart left, AbstractPart right, ExprPartsOperation operationType) { - super(PartType.EXPR); + public ExpressionContainer(AbstractPart left, AbstractPart right, ExprPartsOperation operationType) { + super(PartType.EXPRESSION_CONTAINER); this.left = left; this.right = right; this.operationType = operationType; this.isUnary = false; } - public Expr(AbstractPart singleOperand, ExprPartsOperation operationType) { - super(PartType.EXPR); + public ExpressionContainer(AbstractPart singleOperand, ExprPartsOperation operationType) { + super(PartType.EXPRESSION_CONTAINER); this.left = singleOperand; this.operationType = operationType; this.isUnary = true; @@ -51,8 +51,8 @@ public enum ExprPartsOperation { GTEQ, LT, LTEQ, - WITH_STRUCTURE_HOLDER, // unary - WHEN_STRUCTURE_HOLDER, // unary - EXCLUSIVE_STRUCTURE_HOLDER // unary + WITH_STRUCTURE, // unary + WHEN_STRUCTURE, // unary + EXCLUSIVE_STRUCTURE // unary } } diff --git a/src/main/java/com/aerospike/dsl/model/MetadataOperand.java b/src/main/java/com/aerospike/dsl/model/MetadataOperand.java index c99fd8c..adfe3f4 100644 --- a/src/main/java/com/aerospike/dsl/model/MetadataOperand.java +++ b/src/main/java/com/aerospike/dsl/model/MetadataOperand.java @@ -4,7 +4,7 @@ import lombok.Getter; @Getter -public class MetadataOperand extends Expr { +public class MetadataOperand extends ExpressionContainer { private final String functionName; private final Integer parameter; @@ -40,6 +40,10 @@ private Exp constructMetadataExp(String functionName, Integer parameter) { }; } + public Exp getExp() { + return constructMetadataExp(functionName, parameter); + } + public MetadataReturnType getMetadataType() { return switch (functionName) { case "deviceSize", @@ -62,9 +66,4 @@ public enum MetadataReturnType { STRING, BOOL, } - - public Exp getExp() { - if (exp == null) exp = constructMetadataExp(functionName, parameter); - return exp; - } } diff --git a/src/main/java/com/aerospike/dsl/model/ListOperand.java b/src/main/java/com/aerospike/dsl/model/cdt/ListOperand.java similarity index 69% rename from src/main/java/com/aerospike/dsl/model/ListOperand.java rename to src/main/java/com/aerospike/dsl/model/cdt/ListOperand.java index 9369b5b..c86b38a 100644 --- a/src/main/java/com/aerospike/dsl/model/ListOperand.java +++ b/src/main/java/com/aerospike/dsl/model/cdt/ListOperand.java @@ -1,6 +1,8 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.cdt; import com.aerospike.client.exp.Exp; +import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.model.ParsedOperand; import lombok.Getter; import java.util.List; @@ -16,7 +18,6 @@ public ListOperand(List list) { } public Exp getExp() { - if (exp == null) exp = Exp.val(value); - return exp; + return Exp.val(value); } } diff --git a/src/main/java/com/aerospike/dsl/model/MapOperand.java b/src/main/java/com/aerospike/dsl/model/cdt/MapOperand.java similarity index 70% rename from src/main/java/com/aerospike/dsl/model/MapOperand.java rename to src/main/java/com/aerospike/dsl/model/cdt/MapOperand.java index f75fba4..0b8b0f3 100644 --- a/src/main/java/com/aerospike/dsl/model/MapOperand.java +++ b/src/main/java/com/aerospike/dsl/model/cdt/MapOperand.java @@ -1,6 +1,8 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.cdt; import com.aerospike.client.exp.Exp; +import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.model.ParsedOperand; import lombok.Getter; import java.util.TreeMap; @@ -16,7 +18,6 @@ public MapOperand(TreeMap map) { } public Exp getExp() { - if (exp == null) exp = Exp.val(value); - return exp; + return Exp.val(value); } } diff --git a/src/main/java/com/aerospike/dsl/model/cdt/CdtPart.java b/src/main/java/com/aerospike/dsl/model/cdt_part/CdtPart.java similarity index 53% rename from src/main/java/com/aerospike/dsl/model/cdt/CdtPart.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/CdtPart.java index fcf8ea0..a25f6fd 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/CdtPart.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/CdtPart.java @@ -1,11 +1,11 @@ -package com.aerospike.dsl.model.cdt; +package com.aerospike.dsl.model.cdt_part; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.dsl.exception.AerospikeDSLException; import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.BasePath; -import com.aerospike.dsl.model.PathFunction; +import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.model.path.PathFunction; public abstract class CdtPart extends AbstractPart { @@ -13,17 +13,6 @@ protected CdtPart(PartType partType) { super(partType); } - public static Exp getExpVal(Exp.Type valueType, Object cdtValue) { - return switch (valueType) { - case BOOL -> Exp.val((Boolean) cdtValue); - case INT -> Exp.val((Integer) cdtValue); - case STRING -> Exp.val((String) cdtValue); - case FLOAT -> Exp.val((Float) cdtValue); - default -> throw new IllegalStateException( - "Get by value from a CDT: unexpected value '%s'".formatted(valueType)); - }; - } - public abstract Exp constructExp(BasePath basePath, Exp.Type valueType, int cdtReturnType, CTX[] context); public CTX getContext() { diff --git a/src/main/java/com/aerospike/dsl/model/cdt/list/ListIndex.java b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListIndex.java similarity index 90% rename from src/main/java/com/aerospike/dsl/model/cdt/list/ListIndex.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/list/ListIndex.java index 9862142..c6d0e3a 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/list/ListIndex.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListIndex.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.model.cdt.list; +package com.aerospike.dsl.model.cdt_part.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; public class ListIndex extends ListPart { private final int index; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/list/ListIndexRange.java b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListIndexRange.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt/list/ListIndexRange.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/list/ListIndexRange.java index 2fc5d6f..2f9cc90 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/list/ListIndexRange.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListIndexRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.list; +package com.aerospike.dsl.model.cdt_part.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/list/ListPart.java b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListPart.java similarity index 89% rename from src/main/java/com/aerospike/dsl/model/cdt/list/ListPart.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/list/ListPart.java index d9d5761..bf342de 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/list/ListPart.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListPart.java @@ -1,9 +1,9 @@ -package com.aerospike.dsl.model.cdt.list; +package com.aerospike.dsl.model.cdt_part.list; import com.aerospike.client.cdt.ListReturnType; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.PathFunction; -import com.aerospike.dsl.model.cdt.CdtPart; +import com.aerospike.dsl.model.path.PathFunction; +import com.aerospike.dsl.model.cdt_part.CdtPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/model/cdt/list/ListRank.java b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRank.java similarity index 90% rename from src/main/java/com/aerospike/dsl/model/cdt/list/ListRank.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRank.java index d78e3a5..6459fa5 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/list/ListRank.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRank.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.model.cdt.list; +package com.aerospike.dsl.model.cdt_part.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; public class ListRank extends ListPart { private final int rank; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/list/ListRankRange.java b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRankRange.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt/list/ListRankRange.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRankRange.java index 6064cef..2e35909 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/list/ListRankRange.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRankRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.list; +package com.aerospike.dsl.model.cdt_part.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/list/ListRankRangeRelative.java b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRankRangeRelative.java similarity index 97% rename from src/main/java/com/aerospike/dsl/model/cdt/list/ListRankRangeRelative.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRankRangeRelative.java index cad2325..ddb3881 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/list/ListRankRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRankRangeRelative.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.list; +package com.aerospike.dsl.model.cdt_part.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/list/ListTypeDesignator.java b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListTypeDesignator.java similarity index 89% rename from src/main/java/com/aerospike/dsl/model/cdt/list/ListTypeDesignator.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/list/ListTypeDesignator.java index 7ef6e2d..57562ab 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/list/ListTypeDesignator.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListTypeDesignator.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.model.cdt.list; +package com.aerospike.dsl.model.cdt_part.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.BasePath; -import com.aerospike.dsl.model.cdt.CdtPart; +import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.model.cdt_part.CdtPart; import java.util.Collections; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/list/ListValue.java b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValue.java similarity index 94% rename from src/main/java/com/aerospike/dsl/model/cdt/list/ListValue.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValue.java index 580ec96..c3d6434 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/list/ListValue.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValue.java @@ -1,11 +1,11 @@ -package com.aerospike.dsl.model.cdt.list; +package com.aerospike.dsl.model.cdt_part.list; import com.aerospike.client.Value; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/list/ListValueList.java b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValueList.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt/list/ListValueList.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValueList.java index de762e4..702024e 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/list/ListValueList.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValueList.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.list; +package com.aerospike.dsl.model.cdt_part.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/list/ListValueRange.java b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValueRange.java similarity index 95% rename from src/main/java/com/aerospike/dsl/model/cdt/list/ListValueRange.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValueRange.java index 25a321c..2ac5a7a 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/list/ListValueRange.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValueRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.list; +package com.aerospike.dsl.model.cdt_part.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; public class ListValueRange extends ListPart { private final boolean inverted; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapIndex.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndex.java similarity index 90% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapIndex.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndex.java index 3120ca5..7ca6bf6 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapIndex.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndex.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; public class MapIndex extends MapPart { private final int index; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapIndexRange.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndexRange.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapIndexRange.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndexRange.java index 72f8bf6..fc92829 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapIndexRange.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndexRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapIndexRangeRelative.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndexRangeRelative.java similarity index 97% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapIndexRangeRelative.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndexRangeRelative.java index e0fc6c6..1dfc787 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapIndexRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndexRangeRelative.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapKey.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKey.java similarity index 93% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapKey.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKey.java index 8bd7774..53c379a 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapKey.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKey.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.Value; import com.aerospike.client.cdt.CTX; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyList.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKeyList.java similarity index 95% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyList.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKeyList.java index be5c428..1072bcd 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyList.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKeyList.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyRange.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKeyRange.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyRange.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKeyRange.java index 1c223da..fe91368 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyRange.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKeyRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import java.util.Optional; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapPart.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapPart.java similarity index 90% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapPart.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapPart.java index 7209268..4fc1fba 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapPart.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapPart.java @@ -1,8 +1,8 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.cdt.MapReturnType; -import com.aerospike.dsl.model.PathFunction; -import com.aerospike.dsl.model.cdt.CdtPart; +import com.aerospike.dsl.model.path.PathFunction; +import com.aerospike.dsl.model.cdt_part.CdtPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapRank.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRank.java similarity index 90% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapRank.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRank.java index 642155c..4da997b 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapRank.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRank.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; public class MapRank extends MapPart { private final int rank; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapRankRange.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRankRange.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapRankRange.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRankRange.java index d84adf2..e2a1c44 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapRankRange.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRankRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapRankRangeRelative.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRankRangeRelative.java similarity index 97% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapRankRangeRelative.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRankRangeRelative.java index 7afef60..c2d866e 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapRankRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRankRangeRelative.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapTypeDesignator.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapTypeDesignator.java similarity index 88% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapTypeDesignator.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapTypeDesignator.java index 49eea10..4507c16 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapTypeDesignator.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapTypeDesignator.java @@ -1,9 +1,9 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.BasePath; -import com.aerospike.dsl.model.cdt.CdtPart; +import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.model.cdt_part.CdtPart; /** * Designates that the element to the left is a Map. diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapValue.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValue.java similarity index 94% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapValue.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValue.java index 4427e9d..3655291 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapValue.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValue.java @@ -1,11 +1,11 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.Value; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapValueList.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValueList.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapValueList.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValueList.java index e0be45c..f061155 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapValueList.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValueList.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapValueRange.java b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValueRange.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt/map/MapValueRange.java rename to src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValueRange.java index 89ecbfb..38eac4b 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapValueRange.java +++ b/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValueRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt.map; +package com.aerospike.dsl.model.cdt_part.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.BasePath; +import com.aerospike.dsl.model.path.BasePath; public class MapValueRange extends MapPart { private final boolean inverted; diff --git a/src/main/java/com/aerospike/dsl/model/ctrl_structure/ExclusiveStructure.java b/src/main/java/com/aerospike/dsl/model/ctrl_structure/ExclusiveStructure.java new file mode 100644 index 0000000..f030a45 --- /dev/null +++ b/src/main/java/com/aerospike/dsl/model/ctrl_structure/ExclusiveStructure.java @@ -0,0 +1,18 @@ +package com.aerospike.dsl.model.ctrl_structure; + +import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.model.ExpressionContainer; +import lombok.Getter; + +import java.util.List; + +@Getter +public class ExclusiveStructure extends AbstractPart { + + private final List operands; + + public ExclusiveStructure(List operands) { + super(PartType.EXCLUSIVE_STRUCTURE); + this.operands = operands; + } +} diff --git a/src/main/java/com/aerospike/dsl/model/WhenStructure.java b/src/main/java/com/aerospike/dsl/model/ctrl_structure/WhenStructure.java similarity index 75% rename from src/main/java/com/aerospike/dsl/model/WhenStructure.java rename to src/main/java/com/aerospike/dsl/model/ctrl_structure/WhenStructure.java index 066686b..7ca507e 100644 --- a/src/main/java/com/aerospike/dsl/model/WhenStructure.java +++ b/src/main/java/com/aerospike/dsl/model/ctrl_structure/WhenStructure.java @@ -1,5 +1,6 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.ctrl_structure; +import com.aerospike.dsl.model.AbstractPart; import lombok.Getter; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/WithOperand.java b/src/main/java/com/aerospike/dsl/model/ctrl_structure/WithOperand.java similarity index 86% rename from src/main/java/com/aerospike/dsl/model/WithOperand.java rename to src/main/java/com/aerospike/dsl/model/ctrl_structure/WithOperand.java index a91af51..ef06fba 100644 --- a/src/main/java/com/aerospike/dsl/model/WithOperand.java +++ b/src/main/java/com/aerospike/dsl/model/ctrl_structure/WithOperand.java @@ -1,5 +1,6 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.ctrl_structure; +import com.aerospike.dsl.model.AbstractPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/model/WithStructure.java b/src/main/java/com/aerospike/dsl/model/ctrl_structure/WithStructure.java similarity index 75% rename from src/main/java/com/aerospike/dsl/model/WithStructure.java rename to src/main/java/com/aerospike/dsl/model/ctrl_structure/WithStructure.java index b517745..89d6fdb 100644 --- a/src/main/java/com/aerospike/dsl/model/WithStructure.java +++ b/src/main/java/com/aerospike/dsl/model/ctrl_structure/WithStructure.java @@ -1,5 +1,6 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.ctrl_structure; +import com.aerospike.dsl.model.AbstractPart; import lombok.Getter; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/BasePath.java b/src/main/java/com/aerospike/dsl/model/path/BasePath.java similarity index 79% rename from src/main/java/com/aerospike/dsl/model/BasePath.java rename to src/main/java/com/aerospike/dsl/model/path/BasePath.java index b061d60..45894a2 100644 --- a/src/main/java/com/aerospike/dsl/model/BasePath.java +++ b/src/main/java/com/aerospike/dsl/model/path/BasePath.java @@ -1,6 +1,7 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.path; import com.aerospike.client.exp.Exp; +import com.aerospike.dsl.model.AbstractPart; import lombok.Getter; import java.util.List; @@ -20,12 +21,12 @@ public BasePath(BinPart binOperand, List parts) { // Bin type is determined by the base path's first element public Exp.Type getBinType() { if (!parts.isEmpty()) { - return switch (parts.get(0).partType) { + return switch (parts.get(0).getPartType()) { case MAP_PART -> Exp.Type.MAP; case LIST_PART -> Exp.Type.LIST; default -> null; }; } - return binPart.expType; + return binPart.getExpType(); } } diff --git a/src/main/java/com/aerospike/dsl/model/BinPart.java b/src/main/java/com/aerospike/dsl/model/path/BinPart.java similarity index 68% rename from src/main/java/com/aerospike/dsl/model/BinPart.java rename to src/main/java/com/aerospike/dsl/model/path/BinPart.java index 04cb9e4..2a442f9 100644 --- a/src/main/java/com/aerospike/dsl/model/BinPart.java +++ b/src/main/java/com/aerospike/dsl/model/path/BinPart.java @@ -1,10 +1,11 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.path; import com.aerospike.client.exp.Exp; +import com.aerospike.dsl.model.ExpressionContainer; import lombok.Getter; @Getter -public class BinPart extends Expr { +public class BinPart extends ExpressionContainer { private final String binName; @@ -20,7 +21,6 @@ public void updateExp(Exp.Type expType) { } public Exp getExp() { - if (exp == null) exp = Exp.bin(this.binName, expType); - return exp; + return Exp.bin(this.binName, expType); } } diff --git a/src/main/java/com/aerospike/dsl/model/PathOperand.java b/src/main/java/com/aerospike/dsl/model/path/Path.java similarity index 79% rename from src/main/java/com/aerospike/dsl/model/PathOperand.java rename to src/main/java/com/aerospike/dsl/model/path/Path.java index 05a6713..9bd819a 100644 --- a/src/main/java/com/aerospike/dsl/model/PathOperand.java +++ b/src/main/java/com/aerospike/dsl/model/path/Path.java @@ -1,7 +1,8 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.path; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.cdt.CdtPart; +import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.model.cdt_part.CdtPart; import lombok.Getter; import java.util.List; @@ -13,20 +14,20 @@ import static com.aerospike.dsl.util.PathOperandUtils.updateWithCdtTypeDesignator; @Getter -public class PathOperand extends AbstractPart { +public class Path extends AbstractPart { private final BasePath basePath; private final PathFunction pathFunction; - public PathOperand(BasePath basePath, PathFunction pathFunction) { + public Path(BasePath basePath, PathFunction pathFunction) { super(PartType.PATH_OPERAND); this.basePath = basePath; this.pathFunction = pathFunction; } - public static Exp processPath(BasePath basePath, PathFunction pathFunction) { + public Exp processPath(BasePath basePath, PathFunction pathFunction) { List parts = basePath.getParts(); - basePath = updateWithCdtTypeDesignator(basePath, pathFunction); + updateWithCdtTypeDesignator(basePath, pathFunction); AbstractPart lastPathPart = !parts.isEmpty() ? parts.get(parts.size() - 1) : null; pathFunction = processPathFunction(basePath, lastPathPart, pathFunction); Exp.Type valueType = processValueType(lastPathPart, pathFunction); @@ -46,6 +47,6 @@ public static Exp processPath(BasePath basePath, PathFunction pathFunction) { } public Exp getExp() { - return PathOperand.processPath(basePath, pathFunction); + return processPath(basePath, pathFunction); } } diff --git a/src/main/java/com/aerospike/dsl/model/PathFunction.java b/src/main/java/com/aerospike/dsl/model/path/PathFunction.java similarity index 93% rename from src/main/java/com/aerospike/dsl/model/PathFunction.java rename to src/main/java/com/aerospike/dsl/model/path/PathFunction.java index d04e9b6..263d29b 100644 --- a/src/main/java/com/aerospike/dsl/model/PathFunction.java +++ b/src/main/java/com/aerospike/dsl/model/path/PathFunction.java @@ -1,6 +1,7 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.path; import com.aerospike.client.exp.Exp; +import com.aerospike.dsl.model.AbstractPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/model/BooleanOperand.java b/src/main/java/com/aerospike/dsl/model/simple/BooleanOperand.java similarity index 73% rename from src/main/java/com/aerospike/dsl/model/BooleanOperand.java rename to src/main/java/com/aerospike/dsl/model/simple/BooleanOperand.java index 42dea15..a629e36 100644 --- a/src/main/java/com/aerospike/dsl/model/BooleanOperand.java +++ b/src/main/java/com/aerospike/dsl/model/simple/BooleanOperand.java @@ -1,6 +1,8 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.simple; import com.aerospike.client.exp.Exp; +import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.model.ParsedOperand; import lombok.Getter; @Getter @@ -14,7 +16,6 @@ public BooleanOperand(Boolean value) { } public Exp getExp() { - if (exp == null) exp = Exp.val(value); return Exp.val(value); } } diff --git a/src/main/java/com/aerospike/dsl/model/FloatOperand.java b/src/main/java/com/aerospike/dsl/model/simple/FloatOperand.java similarity index 66% rename from src/main/java/com/aerospike/dsl/model/FloatOperand.java rename to src/main/java/com/aerospike/dsl/model/simple/FloatOperand.java index b8e6bdc..0ad19cb 100644 --- a/src/main/java/com/aerospike/dsl/model/FloatOperand.java +++ b/src/main/java/com/aerospike/dsl/model/simple/FloatOperand.java @@ -1,6 +1,8 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.simple; import com.aerospike.client.exp.Exp; +import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.model.ParsedOperand; import lombok.Getter; @Getter @@ -14,7 +16,6 @@ public FloatOperand(Double value) { } public Exp getExp() { - if (exp == null) exp = Exp.val(value); - return exp; + return Exp.val(value); } } diff --git a/src/main/java/com/aerospike/dsl/model/IntOperand.java b/src/main/java/com/aerospike/dsl/model/simple/IntOperand.java similarity index 66% rename from src/main/java/com/aerospike/dsl/model/IntOperand.java rename to src/main/java/com/aerospike/dsl/model/simple/IntOperand.java index 93abf3e..1916d2a 100644 --- a/src/main/java/com/aerospike/dsl/model/IntOperand.java +++ b/src/main/java/com/aerospike/dsl/model/simple/IntOperand.java @@ -1,6 +1,8 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.simple; import com.aerospike.client.exp.Exp; +import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.model.ParsedOperand; import lombok.Getter; @Getter @@ -14,7 +16,6 @@ public IntOperand(Long value) { } public Exp getExp() { - if (exp == null) exp = Exp.val(value); - return exp; + return Exp.val(value); } } diff --git a/src/main/java/com/aerospike/dsl/model/StringOperand.java b/src/main/java/com/aerospike/dsl/model/simple/StringOperand.java similarity index 80% rename from src/main/java/com/aerospike/dsl/model/StringOperand.java rename to src/main/java/com/aerospike/dsl/model/simple/StringOperand.java index 3409bbd..bbea02f 100644 --- a/src/main/java/com/aerospike/dsl/model/StringOperand.java +++ b/src/main/java/com/aerospike/dsl/model/simple/StringOperand.java @@ -1,6 +1,8 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.simple; import com.aerospike.client.exp.Exp; +import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.model.ParsedOperand; import lombok.Getter; import lombok.Setter; @@ -19,11 +21,6 @@ public StringOperand(String string) { } public Exp getExp() { - if (exp == null) exp = getStringExp(); - return exp; - } - - private Exp getStringExp() { if (isBlob) { byte[] byteValue = Base64.getDecoder().decode(value); return Exp.val(byteValue); diff --git a/src/main/java/com/aerospike/dsl/model/VariableOperand.java b/src/main/java/com/aerospike/dsl/model/simple/VariableOperand.java similarity index 72% rename from src/main/java/com/aerospike/dsl/model/VariableOperand.java rename to src/main/java/com/aerospike/dsl/model/simple/VariableOperand.java index 7ad3ff7..f842f0f 100644 --- a/src/main/java/com/aerospike/dsl/model/VariableOperand.java +++ b/src/main/java/com/aerospike/dsl/model/simple/VariableOperand.java @@ -1,6 +1,7 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.model.simple; import com.aerospike.client.exp.Exp; +import com.aerospike.dsl.model.AbstractPart; import lombok.Getter; @Getter @@ -14,7 +15,6 @@ public VariableOperand(String name) { } public Exp getExp() { - if (exp == null) exp = Exp.var(name); - return exp; + return Exp.var(name); } } diff --git a/src/main/java/com/aerospike/dsl/util/PathOperandUtils.java b/src/main/java/com/aerospike/dsl/util/PathOperandUtils.java index a9688ac..07a2913 100644 --- a/src/main/java/com/aerospike/dsl/util/PathOperandUtils.java +++ b/src/main/java/com/aerospike/dsl/util/PathOperandUtils.java @@ -5,14 +5,14 @@ import com.aerospike.client.exp.ListExp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.BasePath; -import com.aerospike.dsl.model.BinPart; -import com.aerospike.dsl.model.PathFunction; -import com.aerospike.dsl.model.cdt.CdtPart; -import com.aerospike.dsl.model.cdt.list.ListPart; -import com.aerospike.dsl.model.cdt.list.ListTypeDesignator; -import com.aerospike.dsl.model.cdt.map.MapPart; -import com.aerospike.dsl.model.cdt.map.MapTypeDesignator; +import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.model.path.BinPart; +import com.aerospike.dsl.model.path.PathFunction; +import com.aerospike.dsl.model.cdt_part.CdtPart; +import com.aerospike.dsl.model.cdt_part.list.ListPart; +import com.aerospike.dsl.model.cdt_part.list.ListTypeDesignator; +import com.aerospike.dsl.model.cdt_part.map.MapPart; +import com.aerospike.dsl.model.cdt_part.map.MapTypeDesignator; import lombok.experimental.UtilityClass; import java.util.ArrayList; @@ -21,9 +21,9 @@ import static com.aerospike.dsl.model.AbstractPart.PartType.LIST_PART; import static com.aerospike.dsl.model.AbstractPart.PartType.MAP_PART; -import static com.aerospike.dsl.model.PathFunction.PathFunctionType.*; -import static com.aerospike.dsl.model.cdt.list.ListPart.ListPartType.*; -import static com.aerospike.dsl.model.cdt.map.MapPart.MapPartType.MAP_TYPE_DESIGNATOR; +import static com.aerospike.dsl.model.path.PathFunction.PathFunctionType.*; +import static com.aerospike.dsl.model.cdt_part.list.ListPart.ListPartType.*; +import static com.aerospike.dsl.model.cdt_part.map.MapPart.MapPartType.MAP_TYPE_DESIGNATOR; @UtilityClass public class PathOperandUtils { @@ -201,15 +201,13 @@ private static Exp processMapPartSize(BasePath basePath, AbstractPart lastPathPa return MapExp.size(Exp.bin(bin.getBinName(), basePath.getBinType()), context); } - public static BasePath updateWithCdtTypeDesignator(BasePath basePath, PathFunction pathFunction) { + public static void updateWithCdtTypeDesignator(BasePath basePath, PathFunction pathFunction) { if (mustHaveCdtDesignator(pathFunction, basePath.getParts())) { // For cases like list.count() and map.count() with no explicit designator ([] is for List, {} is for Map) // When the last path part is CDT and potentially ambiguous, we apply List designator by default AbstractPart lastPathPart = new ListTypeDesignator(); basePath.getParts().add(lastPathPart); - return basePath; } - return basePath; } private static boolean mustHaveCdtDesignator(PathFunction pathFunction, diff --git a/src/main/java/com/aerospike/dsl/util/TypeUtils.java b/src/main/java/com/aerospike/dsl/util/TypeUtils.java index 58a76fe..f66c18c 100644 --- a/src/main/java/com/aerospike/dsl/util/TypeUtils.java +++ b/src/main/java/com/aerospike/dsl/util/TypeUtils.java @@ -2,8 +2,8 @@ import com.aerospike.client.exp.Exp; import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.cdt.map.MapPart; -import com.aerospike.dsl.model.cdt.map.MapTypeDesignator; +import com.aerospike.dsl.model.cdt_part.map.MapPart; +import com.aerospike.dsl.model.cdt_part.map.MapTypeDesignator; import lombok.experimental.UtilityClass; @UtilityClass diff --git a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java index 4b426d0..6d84eb1 100644 --- a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java +++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java @@ -5,16 +5,32 @@ import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; import com.aerospike.dsl.model.*; -import com.aerospike.dsl.model.cdt.list.ListIndex; -import com.aerospike.dsl.model.cdt.list.ListIndexRange; -import com.aerospike.dsl.model.cdt.list.ListRank; -import com.aerospike.dsl.model.cdt.list.ListRankRange; -import com.aerospike.dsl.model.cdt.list.ListRankRangeRelative; -import com.aerospike.dsl.model.cdt.list.ListTypeDesignator; -import com.aerospike.dsl.model.cdt.list.ListValue; -import com.aerospike.dsl.model.cdt.list.ListValueList; -import com.aerospike.dsl.model.cdt.list.ListValueRange; -import com.aerospike.dsl.model.cdt.map.*; +import com.aerospike.dsl.model.cdt_part.list.ListIndex; +import com.aerospike.dsl.model.cdt_part.list.ListIndexRange; +import com.aerospike.dsl.model.cdt_part.list.ListRank; +import com.aerospike.dsl.model.cdt_part.list.ListRankRange; +import com.aerospike.dsl.model.cdt_part.list.ListRankRangeRelative; +import com.aerospike.dsl.model.cdt_part.list.ListTypeDesignator; +import com.aerospike.dsl.model.cdt_part.list.ListValue; +import com.aerospike.dsl.model.cdt_part.list.ListValueList; +import com.aerospike.dsl.model.cdt_part.list.ListValueRange; +import com.aerospike.dsl.model.cdt_part.map.*; +import com.aerospike.dsl.model.cdt.ListOperand; +import com.aerospike.dsl.model.cdt.MapOperand; +import com.aerospike.dsl.model.ctrl_structure.ExclusiveStructure; +import com.aerospike.dsl.model.ctrl_structure.WhenStructure; +import com.aerospike.dsl.model.ctrl_structure.WithOperand; +import com.aerospike.dsl.model.ctrl_structure.WithStructure; +import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.model.path.BinPart; +import com.aerospike.dsl.model.MetadataOperand; +import com.aerospike.dsl.model.path.Path; +import com.aerospike.dsl.model.path.PathFunction; +import com.aerospike.dsl.model.simple.BooleanOperand; +import com.aerospike.dsl.model.simple.FloatOperand; +import com.aerospike.dsl.model.simple.IntOperand; +import com.aerospike.dsl.model.simple.StringOperand; +import com.aerospike.dsl.model.simple.VariableOperand; import com.aerospike.dsl.util.TypeUtils; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.RuleNode; @@ -23,21 +39,11 @@ import java.util.List; import java.util.TreeMap; -import static com.aerospike.dsl.model.Expr.ExprPartsOperation.*; import static com.aerospike.dsl.util.ParsingUtils.unquote; import static com.aerospike.dsl.visitor.VisitorUtils.*; public class ExpressionConditionVisitor extends ConditionBaseVisitor { - private final boolean isFilterExpOnly; - - public ExpressionConditionVisitor(boolean isFilterExpOnly, boolean isSIndexFilterOnly) { - if (isFilterExpOnly && isSIndexFilterOnly) { - throw new AerospikeDSLException("Error, expecting either isFilterExpOnly or isSIIndexFilterOnly flag"); - } - this.isFilterExpOnly = isFilterExpOnly; - } - @Override public AbstractPart visitWithExpression(ConditionParser.WithExpressionContext ctx) { List expressions = new ArrayList<>(); @@ -50,7 +56,8 @@ public AbstractPart visitWithExpression(ConditionParser.WithExpressionContext ct } // last expression is the action (described after "do") expressions.add(new WithOperand(visit(ctx.expression()), true)); - return new Expr(new WithStructure(expressions), Expr.ExprPartsOperation.WITH_STRUCTURE_HOLDER); + return new ExpressionContainer(new WithStructure(expressions), + ExpressionContainer.ExprPartsOperation.WITH_STRUCTURE); } @Override @@ -65,33 +72,33 @@ public AbstractPart visitWhenExpression(ConditionParser.WhenExpressionContext ct } // visit default parts.add(visit(ctx.expression())); - return new Expr(new WhenStructure(parts), Expr.ExprPartsOperation.WHEN_STRUCTURE_HOLDER); + return new ExpressionContainer(new WhenStructure(parts), ExpressionContainer.ExprPartsOperation.WHEN_STRUCTURE); } @Override public AbstractPart visitAndExpression(ConditionParser.AndExpressionContext ctx) { - Expr left = (Expr) visit(ctx.expression(0)); - Expr right = (Expr) visit(ctx.expression(1)); + ExpressionContainer left = (ExpressionContainer) visit(ctx.expression(0)); + ExpressionContainer right = (ExpressionContainer) visit(ctx.expression(1)); logicalSetBinsAsBooleanExpr(left, right); - return new Expr(left, right, Expr.ExprPartsOperation.AND); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.AND); } @Override public AbstractPart visitOrExpression(ConditionParser.OrExpressionContext ctx) { - Expr left = (Expr) visit(ctx.expression(0)); - Expr right = (Expr) visit(ctx.expression(1)); + ExpressionContainer left = (ExpressionContainer) visit(ctx.expression(0)); + ExpressionContainer right = (ExpressionContainer) visit(ctx.expression(1)); logicalSetBinsAsBooleanExpr(left, right); - return new Expr(left, right, Expr.ExprPartsOperation.OR); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.OR); } @Override public AbstractPart visitNotExpression(ConditionParser.NotExpressionContext ctx) { - Expr expr = (Expr) visit(ctx.expression()); + ExpressionContainer expr = (ExpressionContainer) visit(ctx.expression()); logicalSetBinAsBooleanExpr(expr); - return new Expr(expr, Expr.ExprPartsOperation.NOT); + return new ExpressionContainer(expr, ExpressionContainer.ExprPartsOperation.NOT); } @Override @@ -99,14 +106,15 @@ public AbstractPart visitExclusiveExpression(ConditionParser.ExclusiveExpression if (ctx.expression().size() < 2) { throw new AerospikeDSLException("Exclusive logical operator requires 2 or more expressions"); } - List expressions = new ArrayList<>(); + List expressions = new ArrayList<>(); // iterate through each definition for (ConditionParser.ExpressionContext ec : ctx.expression()) { - Expr expr = (Expr) visit(ec); + ExpressionContainer expr = (ExpressionContainer) visit(ec); logicalSetBinAsBooleanExpr(expr); expressions.add(expr); } - return new Expr(new ExclusiveStructure(expressions), Expr.ExprPartsOperation.EXCLUSIVE_STRUCTURE_HOLDER); + return new ExpressionContainer(new ExclusiveStructure(expressions), + ExpressionContainer.ExprPartsOperation.EXCLUSIVE_STRUCTURE); } @Override @@ -114,7 +122,7 @@ public AbstractPart visitGreaterThanExpression(ConditionParser.GreaterThanExpres AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - return new Expr(left, right, Expr.ExprPartsOperation.GT); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.GT); } @Override @@ -122,7 +130,7 @@ public AbstractPart visitGreaterThanOrEqualExpression(ConditionParser.GreaterTha AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - return new Expr(left, right, Expr.ExprPartsOperation.GTEQ); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.GTEQ); } @Override @@ -130,7 +138,7 @@ public AbstractPart visitLessThanExpression(ConditionParser.LessThanExpressionCo AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - return new Expr(left, right, Expr.ExprPartsOperation.LT); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.LT); } @Override @@ -138,7 +146,7 @@ public AbstractPart visitLessThanOrEqualExpression(ConditionParser.LessThanOrEqu AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - return new Expr(left, right, Expr.ExprPartsOperation.LTEQ); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.LTEQ); } @Override @@ -146,7 +154,7 @@ public AbstractPart visitEqualityExpression(ConditionParser.EqualityExpressionCo AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - return new Expr(left, right, Expr.ExprPartsOperation.EQ); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.EQ); } @Override @@ -154,7 +162,7 @@ public AbstractPart visitInequalityExpression(ConditionParser.InequalityExpressi AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - return new Expr(left, right, Expr.ExprPartsOperation.NOTEQ); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.NOTEQ); } @Override @@ -162,8 +170,7 @@ public AbstractPart visitAddExpression(ConditionParser.AddExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - if (!isFilterExpOnly) validateNumericBinForFilter(left, right); - return new Expr(left, right, ADD); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.ADD); } @Override @@ -171,8 +178,7 @@ public AbstractPart visitSubExpression(ConditionParser.SubExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - if (!isFilterExpOnly) validateNumericBinForFilter(left, right); - return new Expr(left, right, SUB); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.SUB); } @Override @@ -180,8 +186,7 @@ public AbstractPart visitMulExpression(ConditionParser.MulExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - if (!isFilterExpOnly) validateNumericBinForFilter(left, right); - return new Expr(left, right, MUL); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.MUL); } @Override @@ -189,8 +194,7 @@ public AbstractPart visitDivExpression(ConditionParser.DivExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - if (!isFilterExpOnly) validateNumericBinForFilter(left, right); - return new Expr(left, right, DIV); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.DIV); } @Override @@ -198,7 +202,7 @@ public AbstractPart visitModExpression(ConditionParser.ModExpressionContext ctx) AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - return new Expr(left, right, MOD); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.MOD); } @Override @@ -206,7 +210,7 @@ public AbstractPart visitIntAndExpression(ConditionParser.IntAndExpressionContex AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - return new Expr(left, right, INT_AND); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.INT_AND); } @Override @@ -214,7 +218,7 @@ public AbstractPart visitIntOrExpression(ConditionParser.IntOrExpressionContext AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - return new Expr(left, right, INT_OR); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.INT_OR); } @Override @@ -222,14 +226,14 @@ public AbstractPart visitIntXorExpression(ConditionParser.IntXorExpressionContex AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - return new Expr(left, right, INT_XOR); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.INT_XOR); } @Override public AbstractPart visitIntNotExpression(ConditionParser.IntNotExpressionContext ctx) { AbstractPart operand = visit(ctx.operand()); - return new Expr(operand, INT_NOT); + return new ExpressionContainer(operand, ExpressionContainer.ExprPartsOperation.INT_NOT); } @Override @@ -237,7 +241,7 @@ public AbstractPart visitIntLShiftExpression(ConditionParser.IntLShiftExpression AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - return new Expr(left, right, L_SHIFT); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.L_SHIFT); } @Override @@ -245,7 +249,7 @@ public AbstractPart visitIntRShiftExpression(ConditionParser.IntRShiftExpression AbstractPart left = visit(ctx.operand(0)); AbstractPart right = visit(ctx.operand(1)); - return new Expr(left, right, R_SHIFT); + return new ExpressionContainer(left, right, ExpressionContainer.ExprPartsOperation.R_SHIFT); } @Override @@ -469,7 +473,7 @@ public AbstractPart visitPath(ConditionParser.PathContext ctx) { // if there are other parts except bin, get a corresponding Exp if (!parts.isEmpty() || ctx.pathFunction() != null && ctx.pathFunction().pathFunctionCount() != null) { - return new PathOperand(basePath, ctx.pathFunction() == null + return new Path(basePath, ctx.pathFunction() == null ? null : (PathFunction) visit(ctx.pathFunction())); } diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index db5deaa..e94e9da 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -6,8 +6,16 @@ import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; import com.aerospike.dsl.exception.NoApplicableFilterException; -import com.aerospike.dsl.index.Index; +import com.aerospike.dsl.Index; import com.aerospike.dsl.model.*; +import com.aerospike.dsl.model.path.BinPart; +import com.aerospike.dsl.model.ctrl_structure.ExclusiveStructure; +import com.aerospike.dsl.model.simple.IntOperand; +import com.aerospike.dsl.model.MetadataOperand; +import com.aerospike.dsl.model.simple.StringOperand; +import com.aerospike.dsl.model.ctrl_structure.WhenStructure; +import com.aerospike.dsl.model.ctrl_structure.WithOperand; +import com.aerospike.dsl.model.ctrl_structure.WithStructure; import lombok.experimental.UtilityClass; import org.antlr.v4.runtime.misc.Pair; import org.antlr.v4.runtime.tree.ParseTree; @@ -25,23 +33,23 @@ import java.util.stream.Stream; import static com.aerospike.dsl.model.AbstractPart.PartType.*; -import static com.aerospike.dsl.model.Expr.ExprPartsOperation.*; +import static com.aerospike.dsl.model.ExpressionContainer.ExprPartsOperation.*; import static com.aerospike.dsl.util.ValidationUtils.validateComparableTypes; import static com.aerospike.dsl.visitor.VisitorUtils.ArithmeticTermType.*; @UtilityClass public class VisitorUtils { - public final String INDEX_NAME_SEPARATOR = "||||"; + public final String INDEX_NAME_SEPARATOR = "."; private final Map expTypeToIndexType = Map.of( Exp.Type.INT, IndexType.NUMERIC, Exp.Type.STRING, IndexType.STRING, Exp.Type.BLOB, IndexType.BLOB ); - private final List CTRL_STRUCTURE_HOLDERS = List.of( - WITH_STRUCTURE_HOLDER, - WHEN_STRUCTURE_HOLDER, - EXCLUSIVE_STRUCTURE_HOLDER + private final List CTRL_STRUCTURE_HOLDERS = List.of( + ExpressionContainer.ExprPartsOperation.WITH_STRUCTURE, + ExpressionContainer.ExprPartsOperation.WHEN_STRUCTURE, + ExpressionContainer.ExprPartsOperation.EXCLUSIVE_STRUCTURE ); @@ -103,12 +111,12 @@ static Exp.Type detectImplicitTypeFromUpperTree(ParseTree ctx) { return null; } - static void logicalSetBinsAsBooleanExpr(Expr left, Expr right) { + static void logicalSetBinsAsBooleanExpr(ExpressionContainer left, ExpressionContainer right) { logicalSetBinAsBooleanExpr(left); logicalSetBinAsBooleanExpr(right); } - static void logicalSetBinAsBooleanExpr(Expr expr) { + static void logicalSetBinAsBooleanExpr(ExpressionContainer expr) { if (expr instanceof BinPart) { ((BinPart) expr).updateExp(Exp.Type.BOOL); } @@ -130,7 +138,7 @@ static boolean shouldVisitMapElement(int i, int size, ParseTree child) { } // 2 operands Expressions - static Exp exprToExp(Expr expr) { + static Exp exprToExp(ExpressionContainer expr) { if (expr.isUnary()) { return getUnaryExpOrFail(expr.getLeft(), getUnaryExpOperator(expr.getOperationType())); } @@ -157,20 +165,20 @@ static Exp exprToExp(Expr expr) { return operator.apply(leftExp, rightExp); } - private static Exp getFilterExpression(Expr expr, AbstractPart part, AbstractPart.PartType secondPartType) { + private static Exp getFilterExpression(ExpressionContainer expr, AbstractPart part, AbstractPart.PartType secondPartType) { Exp leftExp = null; - if (part.getPartType() == EXPR) { + if (part.getPartType() == EXPRESSION_CONTAINER) { if (expr.isUnary()) { if (!CTRL_STRUCTURE_HOLDERS.contains(expr.getOperationType())) { // If the expression holds a control structure leftExp = getUnaryExpOrFail(part, getUnaryExpOperator(expr.getOperationType())); part.setExp(leftExp); } else { - leftExp = getFilterExp((Expr) part); + leftExp = getFilterExp((ExpressionContainer) part); part.setExp(leftExp); } } else { - leftExp = getFilterExp((Expr) part); + leftExp = getFilterExp((ExpressionContainer) part); part.setExp(leftExp); } } else if (part.getPartType() != BIN_PART && secondPartType != BIN_PART) { @@ -214,7 +222,7 @@ static Exp getExpLeftBinTypeComparison(BinPart left, AbstractPart right, BinaryO leftExp = Exp.bin(left.getBinName(), binType); yield operator.apply(leftExp, right.getExp()); } - case EXPR, PATH_OPERAND -> operator.apply(leftExp, right.getExp()); // Can't validate with Expr on one side + case EXPRESSION_CONTAINER, PATH_OPERAND -> operator.apply(leftExp, right.getExp()); // Can't validate with Expr on one side case BIN_PART -> { // Left and right are both bin parts // Validate types if possible @@ -269,7 +277,7 @@ static Exp getExpRightBinTypeComparison(AbstractPart left, BinPart right, Binary rightExp = Exp.bin(right.getBinName(), binType); yield operator.apply(left.getExp(), rightExp); } - case EXPR, PATH_OPERAND -> + case EXPRESSION_CONTAINER, 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 -> { @@ -360,46 +368,54 @@ static Filter getFilterOrFail(AbstractPart left, AbstractPart right, FilterOpera } // Handle non Bin operands cases - if (left instanceof Expr leftExpr) { + if (left.getPartType() == EXPRESSION_CONTAINER) { + ExpressionContainer leftExpr = (ExpressionContainer) left; return getFilterOrFail(leftExpr.getLeft(), leftExpr.getRight(), leftExpr.getOperationType(), right, type); } - if (right instanceof Expr rightExpr) { + if (right.getPartType() == EXPRESSION_CONTAINER) { + ExpressionContainer rightExpr = (ExpressionContainer) right; 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, + static Filter getFilterOrFail(AbstractPart exprLeft, AbstractPart exprRight, ExpressionContainer.ExprPartsOperation operationType, AbstractPart right, FilterOperationType type) { if (exprLeft == null) { - throw new AerospikeDSLException("Unable to parse left operand of expression"); + throw new NoApplicableFilterException("Unable to parse left operand of expression"); } if (exprRight == null) { - throw new AerospikeDSLException("Unable to parse right operand of expression"); + throw new NoApplicableFilterException("Unable to parse right operand of expression"); } if (exprLeft.getPartType() == BIN_PART) { // bin is on the left side - if (exprRight instanceof IntOperand leftOperand && right instanceof IntOperand rightOperand) { + if (exprRight.getPartType() == INT_OPERAND && right.getPartType() == INT_OPERAND) { +// validateNumericBinForFilter(left, right); + IntOperand leftOperand = (IntOperand) exprRight; + IntOperand rightOperand = (IntOperand) right; validateComparableTypes(exprLeft.getExpType(), Exp.Type.INT); return applyFilterOperator(((BinPart) exprLeft).getBinName(), leftOperand, rightOperand, - operationType, type, getTermType(operationType, true)); + operationType, type, getFilterTermType(operationType, true)); } - throw new AerospikeDSLException( + throw new NoApplicableFilterException( String.format("Operands not supported in secondary index Filter: %s, %s", exprRight, right)); } if (exprRight.getPartType() == BIN_PART) { // bin is on the right side - if (exprLeft instanceof IntOperand leftOperand && right instanceof IntOperand rightOperand) { + if (exprLeft.getPartType() == INT_OPERAND && right.getPartType() == INT_OPERAND) { + IntOperand leftOperand = (IntOperand) exprLeft; + IntOperand rightOperand = (IntOperand) right; validateComparableTypes(exprRight.getExpType(), Exp.Type.INT); return applyFilterOperator(((BinPart) exprRight).getBinName(), leftOperand, rightOperand, - operationType, type, getTermType(operationType, false)); + operationType, type, getFilterTermType(operationType, false)); } - throw new AerospikeDSLException( + throw new NoApplicableFilterException( String.format("Operands not supported in secondary index Filter: %s, %s", exprRight, right)); } // Handle non Bin operands cases - if (exprLeft instanceof Expr leftExpr) { + if (exprLeft.getPartType() == EXPRESSION_CONTAINER) { + ExpressionContainer leftExpr = (ExpressionContainer) exprLeft; return getFilterOrFail(leftExpr.getLeft(), leftExpr.getRight(), type); } return null; @@ -416,13 +432,15 @@ private static boolean isNumericBin(AbstractPart left, AbstractPart right) { || (right.getPartType() == BIN_PART && left.getPartType() == INT_OPERAND); } - private static ArithmeticTermType getTermType(Expr.ExprPartsOperation operationType, boolean isLeftTerm) { + private static ArithmeticTermType getFilterTermType(ExpressionContainer.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); + default -> throw new NoApplicableFilterException( + "Operation type is not supported to get arithmetic term type: " + operationType); }; } @@ -592,7 +610,7 @@ private static Filter getFilter(BinPart bin, AbstractPart operand, FilterOperati } private static Filter applyFilterOperator(String binName, IntOperand leftOperand, IntOperand rightOperand, - Expr.ExprPartsOperation operationType, FilterOperationType type, + ExpressionContainer.ExprPartsOperation operationType, FilterOperationType type, ArithmeticTermType termType) { long leftValue = leftOperand.getValue(); long rightValue = rightOperand.getValue(); @@ -677,38 +695,30 @@ private FilterOperationType invertType(FilterOperationType type) { }; } - public AbstractPart buildExpr(Expr expr, String namespace, Map indexes, - boolean isFilterExpOnly, boolean isSIFilterOnly) { - Exp exp = null; + public AbstractPart buildExpr(ExpressionContainer expr, String namespace, Map indexes) { + Exp exp; Filter sIndexFilter = null; try { - if (!isFilterExpOnly) { - sIndexFilter = getSIFilter(expr, namespace, indexes); - } + sIndexFilter = getSIFilter(expr, namespace, indexes); } catch (NoApplicableFilterException ignored) { } - expr.setSIndexFilter(sIndexFilter); + expr.setFilter(sIndexFilter); - if (!isSIFilterOnly) { - exp = getFilterExp(expr); - } + exp = getFilterExp(expr); expr.setExp(exp); return expr; } - private static Exp getFilterExp(Expr expr) { - // if a Filter is already set in an OR query - if (expr.getOperationType() == OR && expr.getSIndexFilter() != null) return null; - + private static Exp getFilterExp(ExpressionContainer expr) { return switch (expr.getOperationType()) { - case WITH_STRUCTURE_HOLDER -> withStructureHolderToExp(expr); - case WHEN_STRUCTURE_HOLDER -> whenStructureHolderToExp(expr); - case EXCLUSIVE_STRUCTURE_HOLDER -> exclStructureHolderToExp(expr); + case WITH_STRUCTURE -> withStructureHolderToExp(expr); + case WHEN_STRUCTURE -> whenStructureHolderToExp(expr); + case EXCLUSIVE_STRUCTURE -> exclStructureHolderToExp(expr); default -> exprToExp(expr); }; } - private static Exp withStructureHolderToExp(Expr expr) { + private static Exp withStructureHolderToExp(ExpressionContainer expr) { List expressions = new ArrayList<>(); WithStructure withOperandsList = (WithStructure) expr.getLeft(); // extract unary Expr operand List operands = withOperandsList.getOperands(); @@ -723,7 +733,7 @@ private static Exp withStructureHolderToExp(Expr expr) { return Exp.let(expressions.toArray(new Exp[0])); } - private static Exp whenStructureHolderToExp(Expr expr) { + private static Exp whenStructureHolderToExp(ExpressionContainer expr) { List expressions = new ArrayList<>(); WhenStructure whenOperandsList = (WhenStructure) expr.getLeft(); // extract unary Expr operand List operands = whenOperandsList.getOperands(); @@ -733,26 +743,29 @@ private static Exp whenStructureHolderToExp(Expr expr) { return Exp.cond(expressions.toArray(new Exp[0])); } - private static Exp exclStructureHolderToExp(Expr expr) { + private static Exp exclStructureHolderToExp(ExpressionContainer expr) { List expressions = new ArrayList<>(); ExclusiveStructure whenOperandsList = (ExclusiveStructure) expr.getLeft(); // extract unary Expr operand - List operands = whenOperandsList.getOperands(); - for (Expr part : operands) { + List operands = whenOperandsList.getOperands(); + for (ExpressionContainer part : operands) { expressions.add(getExp(part)); } return Exp.exclusive(expressions.toArray(new Exp[0])); } private static Exp getExp(AbstractPart part) { - if (part.getPartType() == EXPR) { - return getFilterExp((Expr) part); + if (part.getPartType() == EXPRESSION_CONTAINER) { + return getFilterExp((ExpressionContainer) part); } return part.getExp(); } - private static Filter getSIFilter(Expr expr, String namespace, Map indexes) { - List exprs = flattenExprs(expr); - Expr chosenExpr = chooseExprForFilter(exprs, namespace, indexes); + private static Filter getSIFilter(ExpressionContainer expr, String namespace, Map indexes) { + // If it is an OR query + if (expr.getOperationType() == OR) return null; + + List exprs = flattenExprs(expr); + ExpressionContainer chosenExpr = chooseExprForFilter(exprs, namespace, indexes); return chosenExpr == null ? null : getFilterOrFail(chosenExpr.getLeft(), chosenExpr.getRight(), @@ -760,17 +773,17 @@ private static Filter getSIFilter(Expr expr, String namespace, Map exprs, String namespace, Map indexes) { + private static ExpressionContainer chooseExprForFilter(List exprs, String namespace, Map indexes) { if (exprs.size() == 1) return exprs.get(0); if (exprs.size() > 1 && (indexes == null || indexes.isEmpty())) return null; - Map> exprsPerCardinality = new HashMap<>(); - for (Expr expr : exprs) { + Map> exprsPerCardinality = new HashMap<>(); + for (ExpressionContainer expr : exprs) { BinPart binPart = getBinPart(expr); Index index = indexes.get(namespace + INDEX_NAME_SEPARATOR + binPart.getBinName()); if (index == null) continue; if (expTypeToIndexType.get(binPart.getExpType()) == index.getIndexType()) { - List exprsList = exprsPerCardinality.get(index.getBinValuesRatio()); + List exprsList = exprsPerCardinality.get(index.getBinValuesRatio()); if (exprsList != null) { exprsList.add(expr); } else { @@ -782,11 +795,11 @@ private static Expr chooseExprForFilter(List exprs, String namespace, Map< } // Find the entry with the largest key and put it in a new Map - Map> largestCardinalityMap = exprsPerCardinality.entrySet().stream() + Map> largestCardinalityMap = exprsPerCardinality.entrySet().stream() .max(Map.Entry.comparingByKey()) .map(entry -> Map.of(entry.getKey(), entry.getValue())) .orElse(Collections.emptyMap()); - List largestCardinalityExprs = largestCardinalityMap.values().iterator().next(); + List largestCardinalityExprs = largestCardinalityMap.values().iterator().next(); if (largestCardinalityExprs.size() > 1) { // Choosing alphabetically return largestCardinalityExprs.stream() @@ -796,18 +809,18 @@ private static Expr chooseExprForFilter(List exprs, String namespace, Map< return largestCardinalityExprs.get(0); } - private static BinPart getBinPart(Expr expr) { + private static BinPart getBinPart(ExpressionContainer expr) { BinPart result = null; if (expr.getOperationType() == AND || expr.getOperationType() == OR) { - Expr leftExpr = (Expr) expr.getLeft(); - if (leftExpr.getLeft() != null && leftExpr.getLeft().getPartType() == EXPR) { + ExpressionContainer leftExpr = (ExpressionContainer) expr.getLeft(); + if (leftExpr.getLeft() != null && leftExpr.getLeft().getPartType() == EXPRESSION_CONTAINER) { result = getBinPart(leftExpr); if (result != null) return result; } - if (expr.getRight() != null && expr.getRight().getPartType() == EXPR) { - Expr rightExpr = (Expr) expr.getRight(); - if (rightExpr.getRight() != null && rightExpr.getRight().getPartType() == EXPR) { + if (expr.getRight() != null && expr.getRight().getPartType() == EXPRESSION_CONTAINER) { + ExpressionContainer rightExpr = (ExpressionContainer) expr.getRight(); + if (rightExpr.getRight() != null && rightExpr.getRight().getPartType() == EXPRESSION_CONTAINER) { result = getBinPart(rightExpr); if (result != null) return result; } @@ -824,27 +837,27 @@ private static BinPart getBinPart(Expr expr) { return result; } - private static List flattenExprs(Expr expr) { - List results = new ArrayList<>(); + private static List flattenExprs(ExpressionContainer expr) { + List results = new ArrayList<>(); if (expr.getOperationType() == AND || expr.getOperationType() == OR) { - if (expr.getLeft() != null && expr.getLeft().getPartType() == EXPR) { - Expr leftExpr = (Expr) expr.getLeft(); + if (expr.getLeft() != null && expr.getLeft().getPartType() == EXPRESSION_CONTAINER) { + ExpressionContainer leftExpr = (ExpressionContainer) expr.getLeft(); if (leftExpr.getOperationType() == AND || leftExpr.getOperationType() == OR) { - Stream stream = flattenExprs(leftExpr).stream(); + Stream stream = flattenExprs(leftExpr).stream(); results = Stream.concat(results.stream(), stream).toList(); } else { - Stream stream = Stream.of(leftExpr); + Stream stream = Stream.of(leftExpr); results = Stream.concat(results.stream(), stream).toList(); } } - if (expr.getRight() != null && expr.getRight().getPartType() == EXPR) { - Expr rightExpr = (Expr) expr.getRight(); + if (expr.getRight() != null && expr.getRight().getPartType() == EXPRESSION_CONTAINER) { + ExpressionContainer rightExpr = (ExpressionContainer) expr.getRight(); if (rightExpr.getOperationType() == AND || rightExpr.getOperationType() == OR) { - Stream stream = flattenExprs(rightExpr).stream(); + Stream stream = flattenExprs(rightExpr).stream(); results = Stream.concat(results.stream(), stream).toList(); } else { - Stream stream = Stream.of(rightExpr); + Stream stream = Stream.of(rightExpr); results = Stream.concat(results.stream(), stream).toList(); } } @@ -854,7 +867,7 @@ private static List flattenExprs(Expr expr) { return results; } - private static FilterOperationType getFilterOperation(Expr.ExprPartsOperation exprPartsOperation) { + private static FilterOperationType getFilterOperation(ExpressionContainer.ExprPartsOperation exprPartsOperation) { return switch (exprPartsOperation) { case GT -> FilterOperationType.GT; case GTEQ -> FilterOperationType.GTEQ; @@ -866,7 +879,7 @@ private static FilterOperationType getFilterOperation(Expr.ExprPartsOperation ex }; } - private static BinaryOperator getExpOperator(Expr.ExprPartsOperation exprPartsOperation) { + private static BinaryOperator getExpOperator(ExpressionContainer.ExprPartsOperation exprPartsOperation) { return switch (exprPartsOperation) { case ADD -> Exp::add; case SUB -> Exp::sub; @@ -890,7 +903,7 @@ private static BinaryOperator getExpOperator(Expr.ExprPartsOperation exprPa }; } - private static UnaryOperator getUnaryExpOperator(Expr.ExprPartsOperation exprPartsOperation) { + private static UnaryOperator getUnaryExpOperator(ExpressionContainer.ExprPartsOperation exprPartsOperation) { return switch (exprPartsOperation) { case INT_NOT -> Exp::intNot; case NOT -> Exp::not; diff --git a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java index 368b803..826f63b 100644 --- a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java @@ -4,120 +4,120 @@ import com.aerospike.dsl.exception.AerospikeDSLException; import org.junit.jupiter.api.Test; -import static com.aerospike.dsl.util.TestUtils.parseFilterExp; -import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseExp; +import static com.aerospike.dsl.util.TestUtils.parseExpAndCompare; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class ArithmeticExpressionsTests { @Test void add() { - parseFilterExpAndCompare("($.apples + $.bananas) > 10", + parseExpAndCompare("($.apples + $.bananas) > 10", Exp.gt(Exp.add(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseFilterExpAndCompare("($.apples + 5) > 10", + parseExpAndCompare("($.apples + 5) > 10", Exp.gt(Exp.add(Exp.intBin("apples"), Exp.val(5)), Exp.val(10))); - parseFilterExpAndCompare("(5 + $.bananas) > 10", + parseExpAndCompare("(5 + $.bananas) > 10", Exp.gt(Exp.add(Exp.val(5), Exp.intBin("bananas")), Exp.val(10))); - parseFilterExpAndCompare("(5.2 + $.bananas) > 10.2", + parseExpAndCompare("(5.2 + $.bananas) > 10.2", Exp.gt(Exp.add(Exp.val(5.2), Exp.floatBin("bananas")), Exp.val(10.2))); } @Test void sub() { - parseFilterExpAndCompare("($.apples - $.bananas) == 10", + parseExpAndCompare("($.apples - $.bananas) == 10", Exp.eq(Exp.sub(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseFilterExpAndCompare("($.apples - 5) == 10", + parseExpAndCompare("($.apples - 5) == 10", Exp.eq(Exp.sub(Exp.intBin("apples"), Exp.val(5)), Exp.val(10))); - parseFilterExpAndCompare("(15 - $.bananas) == 10", + parseExpAndCompare("(15 - $.bananas) == 10", Exp.eq(Exp.sub(Exp.val(15), Exp.intBin("bananas")), Exp.val(10))); } @Test void mul() { - parseFilterExpAndCompare("($.apples * $.bananas) != 10", + parseExpAndCompare("($.apples * $.bananas) != 10", Exp.ne(Exp.mul(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseFilterExpAndCompare("($.apples * 7) != 10", + parseExpAndCompare("($.apples * 7) != 10", Exp.ne(Exp.mul(Exp.intBin("apples"), Exp.val(7)), Exp.val(10))); - parseFilterExpAndCompare("(3 * $.bananas) != 10", + parseExpAndCompare("(3 * $.bananas) != 10", Exp.ne(Exp.mul(Exp.val(3), Exp.intBin("bananas")), Exp.val(10))); } @Test void div() { - parseFilterExpAndCompare("($.apples / $.bananas) <= 10", + parseExpAndCompare("($.apples / $.bananas) <= 10", Exp.le(Exp.div(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseFilterExpAndCompare("($.apples / 5) <= 10", + parseExpAndCompare("($.apples / 5) <= 10", Exp.le(Exp.div(Exp.intBin("apples"), Exp.val(5)), Exp.val(10))); - parseFilterExpAndCompare("(33 / $.bananas) <= 10", + parseExpAndCompare("(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 - parseFilterExpAndCompare("($.apples / 0) <= 10", + parseExpAndCompare("($.apples / 0) <= 10", Exp.le(Exp.div(Exp.intBin("apples"), Exp.val(0)), Exp.val(10))); } @Test void mod() { - parseFilterExpAndCompare("($.apples % $.bananas) != 10", + parseExpAndCompare("($.apples % $.bananas) != 10", Exp.ne(Exp.mod(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseFilterExpAndCompare("($.apples % 7) != 10", + parseExpAndCompare("($.apples % 7) != 10", Exp.ne(Exp.mod(Exp.intBin("apples"), Exp.val(7)), Exp.val(10))); - parseFilterExpAndCompare("(3 % $.bananas) != 10", + parseExpAndCompare("(3 % $.bananas) != 10", Exp.ne(Exp.mod(Exp.val(3), Exp.intBin("bananas")), Exp.val(10))); } @Test void intAnd() { - parseFilterExpAndCompare("($.apples & $.bananas) != 10", - Exp.ne(Exp.intAnd(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseFilterExpAndCompare("($.apples & 7) != 10", +// parseExpAndCompare("($.apples & $.bananas) != 10", +// Exp.ne(Exp.intAnd(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); + parseExpAndCompare("($.apples & 7) != 10", Exp.ne(Exp.intAnd(Exp.intBin("apples"), Exp.val(7)), Exp.val(10))); - parseFilterExpAndCompare("(3 & $.bananas) != 10", + parseExpAndCompare("(3 & $.bananas) != 10", Exp.ne(Exp.intAnd(Exp.val(3), Exp.intBin("bananas")), Exp.val(10))); } @Test void intOr() { - parseFilterExpAndCompare("($.apples | $.bananas) != 10", + parseExpAndCompare("($.apples | $.bananas) != 10", Exp.ne(Exp.intOr(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseFilterExpAndCompare("($.apples | 7) != 10", + parseExpAndCompare("($.apples | 7) != 10", Exp.ne(Exp.intOr(Exp.intBin("apples"), Exp.val(7)), Exp.val(10))); - parseFilterExpAndCompare("(3 | $.bananas) != 10", + parseExpAndCompare("(3 | $.bananas) != 10", Exp.ne(Exp.intOr(Exp.val(3), Exp.intBin("bananas")), Exp.val(10))); } @Test void intXor() { - parseFilterExpAndCompare("($.apples ^ $.bananas) != 10", + parseExpAndCompare("($.apples ^ $.bananas) != 10", Exp.ne(Exp.intXor(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10))); - parseFilterExpAndCompare("($.apples ^ 7) != 10", + parseExpAndCompare("($.apples ^ 7) != 10", Exp.ne(Exp.intXor(Exp.intBin("apples"), Exp.val(7)), Exp.val(10))); - parseFilterExpAndCompare("(3 ^ $.bananas) != 10", + parseExpAndCompare("(3 ^ $.bananas) != 10", Exp.ne(Exp.intXor(Exp.val(3), Exp.intBin("bananas")), Exp.val(10))); } @Test void intNot() { - parseFilterExpAndCompare("(~$.apples) != 10", + parseExpAndCompare("(~$.apples) != 10", Exp.ne(Exp.intNot(Exp.intBin("apples")), Exp.val(10))); } @Test void intLShift() { - parseFilterExpAndCompare("$.visits << 1", + parseExpAndCompare("$.visits << 1", Exp.lshift(Exp.intBin("visits"), Exp.val(1))); } @Test void intRShift() { - parseFilterExpAndCompare("(($.flags >> 6) & 1) == 1", + parseExpAndCompare("(($.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(() -> parseFilterExp("($.apples.get(type: STRING) + 5) > 10")) + assertThatThrownBy(() -> parseExp("($.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 index f497ddb..39033ab 100644 --- a/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java @@ -4,61 +4,61 @@ import com.aerospike.dsl.exception.AerospikeDSLException; import org.junit.jupiter.api.Test; -import static com.aerospike.dsl.util.TestUtils.parseFilterExp; -import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseExp; +import static com.aerospike.dsl.util.TestUtils.parseExpAndCompare; import static org.assertj.core.api.Assertions.assertThatThrownBy; class BinExpressionsTests { @Test void binGT() { - parseFilterExpAndCompare("$.intBin1 > 100", Exp.gt(Exp.intBin("intBin1"), Exp.val(100))); - parseFilterExpAndCompare("$.stringBin1 > 'text'", Exp.gt(Exp.stringBin("stringBin1"), Exp.val("text"))); - parseFilterExpAndCompare("$.stringBin1 > \"text\"", Exp.gt(Exp.stringBin("stringBin1"), Exp.val("text"))); + parseExpAndCompare("$.intBin1 > 100", Exp.gt(Exp.intBin("intBin1"), Exp.val(100))); + parseExpAndCompare("$.stringBin1 > 'text'", Exp.gt(Exp.stringBin("stringBin1"), Exp.val("text"))); + parseExpAndCompare("$.stringBin1 > \"text\"", Exp.gt(Exp.stringBin("stringBin1"), Exp.val("text"))); - parseFilterExpAndCompare("100 < $.intBin1", Exp.lt(Exp.val(100), Exp.intBin("intBin1"))); - parseFilterExpAndCompare("'text' < $.stringBin1", Exp.lt(Exp.val("text"), Exp.stringBin("stringBin1"))); - parseFilterExpAndCompare("\"text\" < $.stringBin1", Exp.lt(Exp.val("text"), Exp.stringBin("stringBin1"))); + parseExpAndCompare("100 < $.intBin1", Exp.lt(Exp.val(100), Exp.intBin("intBin1"))); + parseExpAndCompare("'text' < $.stringBin1", Exp.lt(Exp.val("text"), Exp.stringBin("stringBin1"))); + parseExpAndCompare("\"text\" < $.stringBin1", Exp.lt(Exp.val("text"), Exp.stringBin("stringBin1"))); } @Test void binGE() { - parseFilterExpAndCompare("$.intBin1 >= 100", Exp.ge(Exp.intBin("intBin1"), Exp.val(100))); - parseFilterExpAndCompare("$.stringBin1 >= 'text'", Exp.ge(Exp.stringBin("stringBin1"), Exp.val("text"))); - parseFilterExpAndCompare("$.stringBin1 >= \"text\"", Exp.ge(Exp.stringBin("stringBin1"), Exp.val("text"))); + parseExpAndCompare("$.intBin1 >= 100", Exp.ge(Exp.intBin("intBin1"), Exp.val(100))); + parseExpAndCompare("$.stringBin1 >= 'text'", Exp.ge(Exp.stringBin("stringBin1"), Exp.val("text"))); + parseExpAndCompare("$.stringBin1 >= \"text\"", Exp.ge(Exp.stringBin("stringBin1"), Exp.val("text"))); } @Test void binLT() { - parseFilterExpAndCompare("$.intBin1 < 100", Exp.lt(Exp.intBin("intBin1"), Exp.val(100))); - parseFilterExpAndCompare("$.stringBin1 < 'text'", Exp.lt(Exp.stringBin("stringBin1"), Exp.val("text"))); - parseFilterExpAndCompare("$.stringBin1 < \"text\"", Exp.lt(Exp.stringBin("stringBin1"), Exp.val("text"))); + parseExpAndCompare("$.intBin1 < 100", Exp.lt(Exp.intBin("intBin1"), Exp.val(100))); + parseExpAndCompare("$.stringBin1 < 'text'", Exp.lt(Exp.stringBin("stringBin1"), Exp.val("text"))); + parseExpAndCompare("$.stringBin1 < \"text\"", Exp.lt(Exp.stringBin("stringBin1"), Exp.val("text"))); } @Test void binLE() { - parseFilterExpAndCompare("$.intBin1 <= 100", Exp.le(Exp.intBin("intBin1"), Exp.val(100))); - parseFilterExpAndCompare("$.stringBin1 <= 'text'", Exp.le(Exp.stringBin("stringBin1"), Exp.val("text"))); - parseFilterExpAndCompare("$.stringBin1 <= \"text\"", Exp.le(Exp.stringBin("stringBin1"), Exp.val("text"))); + parseExpAndCompare("$.intBin1 <= 100", Exp.le(Exp.intBin("intBin1"), Exp.val(100))); + parseExpAndCompare("$.stringBin1 <= 'text'", Exp.le(Exp.stringBin("stringBin1"), Exp.val("text"))); + parseExpAndCompare("$.stringBin1 <= \"text\"", Exp.le(Exp.stringBin("stringBin1"), Exp.val("text"))); } @Test void binEquals() { - parseFilterExpAndCompare("$.intBin1 == 100", Exp.eq(Exp.intBin("intBin1"), Exp.val(100))); - parseFilterExpAndCompare("$.strBin == \"yes\"", Exp.eq(Exp.stringBin("strBin"), Exp.val("yes"))); - parseFilterExpAndCompare("$.strBin == 'yes'", Exp.eq(Exp.stringBin("strBin"), Exp.val("yes"))); + parseExpAndCompare("$.intBin1 == 100", Exp.eq(Exp.intBin("intBin1"), Exp.val(100))); + parseExpAndCompare("$.strBin == \"yes\"", Exp.eq(Exp.stringBin("strBin"), Exp.val("yes"))); + parseExpAndCompare("$.strBin == 'yes'", Exp.eq(Exp.stringBin("strBin"), Exp.val("yes"))); } @Test void binNotEquals() { - parseFilterExpAndCompare("$.intBin1 != 100", Exp.ne(Exp.intBin("intBin1"), Exp.val(100))); - parseFilterExpAndCompare("$.strBin != \"yes\"", Exp.ne(Exp.stringBin("strBin"), Exp.val("yes"))); - parseFilterExpAndCompare("$.strBin != 'yes'", Exp.ne(Exp.stringBin("strBin"), Exp.val("yes"))); + parseExpAndCompare("$.intBin1 != 100", Exp.ne(Exp.intBin("intBin1"), Exp.val(100))); + parseExpAndCompare("$.strBin != \"yes\"", Exp.ne(Exp.stringBin("strBin"), Exp.val("yes"))); + parseExpAndCompare("$.strBin != 'yes'", Exp.ne(Exp.stringBin("strBin"), Exp.val("yes"))); } @Test void negativeStringBinEquals() { - assertThatThrownBy(() -> parseFilterExp("$.strBin == yes")) + assertThatThrownBy(() -> parseExp("$.strBin == yes")) .isInstanceOf(AerospikeDSLException.class) .hasMessage("Unable to parse right operand"); } diff --git a/src/test/java/com/aerospike/dsl/expression/CastingTests.java b/src/test/java/com/aerospike/dsl/expression/CastingTests.java index 97cb5d3..75a1848 100644 --- a/src/test/java/com/aerospike/dsl/expression/CastingTests.java +++ b/src/test/java/com/aerospike/dsl/expression/CastingTests.java @@ -4,8 +4,8 @@ import com.aerospike.dsl.exception.AerospikeDSLException; import org.junit.jupiter.api.Test; -import static com.aerospike.dsl.util.TestUtils.parseFilterExp; -import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseExp; +import static com.aerospike.dsl.util.TestUtils.parseExpAndCompare; 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 - parseFilterExpAndCompare("$.intBin1 > $.floatBin1.asInt()", expectedExp); - parseFilterExpAndCompare("$.intBin1.get(type: INT) > $.floatBin1.asInt()", expectedExp); + parseExpAndCompare("$.intBin1 > $.floatBin1.asInt()", expectedExp); + parseExpAndCompare("$.intBin1.get(type: INT) > $.floatBin1.asInt()", expectedExp); } @Test void intToFloatComparison() { - parseFilterExpAndCompare("$.intBin1.get(type: INT) > $.intBin2.asFloat()", + parseExpAndCompare("$.intBin1.get(type: INT) > $.intBin2.asFloat()", Exp.gt(Exp.intBin("intBin1"), Exp.floatBin("intBin2"))); } @Test void negativeInvalidTypesComparison() { - assertThatThrownBy(() -> parseFilterExp("$.stringBin1.get(type: STRING) > $.intBin2.asFloat()")) + assertThatThrownBy(() -> parseExp("$.stringBin1.get(type: STRING) > $.intBin2.asFloat()")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Cannot compare STRING to FLOAT"); } diff --git a/src/test/java/com/aerospike/dsl/expression/ControlStructuresTests.java b/src/test/java/com/aerospike/dsl/expression/ControlStructuresTests.java index a178140..5f89e1b 100644 --- a/src/test/java/com/aerospike/dsl/expression/ControlStructuresTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ControlStructuresTests.java @@ -3,7 +3,7 @@ import com.aerospike.client.exp.Exp; import org.junit.jupiter.api.Test; -import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseExpAndCompare; public class ControlStructuresTests { @@ -17,10 +17,10 @@ void whenWithASingleDeclaration() { Exp.val("other") ); - parseFilterExpAndCompare("when ($.who == 1 => \"bob\", default => \"other\")", + parseExpAndCompare("when ($.who == 1 => \"bob\", default => \"other\")", expected); // different spacing style - parseFilterExpAndCompare("when($.who == 1 => \"bob\", default => \"other\")", + parseExpAndCompare("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); - parseFilterExpAndCompare("$.stringBin1.get(type: STRING) == (when ($.who == 1 => \"bob\", default => \"other\"))", + parseExpAndCompare("$.stringBin1.get(type: STRING) == (when ($.who == 1 => \"bob\", default => \"other\"))", expected); } @@ -58,7 +58,7 @@ void whenWithMultipleDeclarations() { Exp.val("other") ); - parseFilterExpAndCompare("when ($.who == 1 => \"bob\", $.who == 2 => \"fred\", default => \"other\")", + parseExpAndCompare("when ($.who == 1 => \"bob\", $.who == 2 => \"fred\", default => \"other\")", expected); } @@ -74,10 +74,10 @@ void withMultipleVariablesDefinitionAndUsage() { Exp.add(Exp.var("x"), Exp.var("y")) ); - parseFilterExpAndCompare("with (x = 1, y = ${x} + 1) do (${x} + ${y})", + parseExpAndCompare("with (x = 1, y = ${x} + 1) do (${x} + ${y})", expected); // different spacing style - parseFilterExpAndCompare("with(x = 1, y = ${x}+1) do(${x}+${y})", + parseExpAndCompare("with(x = 1, y = ${x}+1) do(${x}+${y})", expected); } } diff --git a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java index ee7d2a8..ffdcbfe 100644 --- a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java @@ -8,8 +8,8 @@ import java.util.List; import java.util.TreeMap; -import static com.aerospike.dsl.util.TestUtils.parseFilterExp; -import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseExp; +import static com.aerospike.dsl.util.TestUtils.parseExpAndCompare; 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() { - parseFilterExpAndCompare("$.intBin1.get(type: INT) > 5", + parseExpAndCompare("$.intBin1.get(type: INT) > 5", Exp.gt(Exp.intBin("intBin1"), Exp.val(5))); - parseFilterExpAndCompare("5 < $.intBin1.get(type: INT)", + parseExpAndCompare("5 < $.intBin1.get(type: INT)", Exp.lt(Exp.val(5), Exp.intBin("intBin1"))); } @Test void stringComparison() { // A String constant must contain quoted Strings - parseFilterExpAndCompare("$.stringBin1.get(type: STRING) == \"yes\"", + parseExpAndCompare("$.stringBin1.get(type: STRING) == \"yes\"", Exp.eq(Exp.stringBin("stringBin1"), Exp.val("yes"))); - parseFilterExpAndCompare("$.stringBin1.get(type: STRING) == 'yes'", + parseExpAndCompare("$.stringBin1.get(type: STRING) == 'yes'", Exp.eq(Exp.stringBin("stringBin1"), Exp.val("yes"))); - parseFilterExpAndCompare("\"yes\" == $.stringBin1.get(type: STRING)", + parseExpAndCompare("\"yes\" == $.stringBin1.get(type: STRING)", Exp.eq(Exp.val("yes"), Exp.stringBin("stringBin1"))); - parseFilterExpAndCompare("'yes' == $.stringBin1.get(type: STRING)", + parseExpAndCompare("'yes' == $.stringBin1.get(type: STRING)", Exp.eq(Exp.val("yes"), Exp.stringBin("stringBin1"))); } @Test void stringComparisonNegativeTest() { // A String constant must be quoted - assertThatThrownBy(() -> parseFilterExpAndCompare("$.stringBin1.get(type: STRING) == yes", + assertThatThrownBy(() -> parseExpAndCompare("$.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); - parseFilterExpAndCompare("$.blobBin1.get(type: BLOB) == \"" + encodedString + "\"", + parseExpAndCompare("$.blobBin1.get(type: BLOB) == \"" + encodedString + "\"", Exp.eq(Exp.blobBin("blobBin1"), Exp.val(data))); // Reverse - parseFilterExpAndCompare("\"" + encodedString + "\"" + " == $.blobBin1.get(type: BLOB)", + parseExpAndCompare("\"" + encodedString + "\"" + " == $.blobBin1.get(type: BLOB)", Exp.eq(Exp.val(data), Exp.blobBin("blobBin1"))); } @Test void floatComparison() { - parseFilterExpAndCompare("$.floatBin1.get(type: FLOAT) == 1.5", + parseExpAndCompare("$.floatBin1.get(type: FLOAT) == 1.5", Exp.eq(Exp.floatBin("floatBin1"), Exp.val(1.5))); - parseFilterExpAndCompare("1.5 == $.floatBin1.get(type: FLOAT)", + parseExpAndCompare("1.5 == $.floatBin1.get(type: FLOAT)", Exp.eq(Exp.val(1.5), Exp.floatBin("floatBin1"))); } @Test void booleanComparison() { - parseFilterExpAndCompare("$.boolBin1.get(type: BOOL) == true", + parseExpAndCompare("$.boolBin1.get(type: BOOL) == true", Exp.eq(Exp.boolBin("boolBin1"), Exp.val(true))); - parseFilterExpAndCompare("true == $.boolBin1.get(type: BOOL)", + parseExpAndCompare("true == $.boolBin1.get(type: BOOL)", Exp.eq(Exp.val(true), Exp.boolBin("boolBin1"))); } @Test void negativeBooleanComparison() { - assertThatThrownBy(() -> parseFilterExp("$.boolBin1.get(type: BOOL) == 5")) + assertThatThrownBy(() -> parseExp("$.boolBin1.get(type: BOOL) == 5")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Cannot compare BOOL to INT"); } @Test void listComparison_constantOnRightSide() { - parseFilterExpAndCompare("$.listBin1.get(type: LIST) == [100]", + parseExpAndCompare("$.listBin1.get(type: LIST) == [100]", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of(100)))); - parseFilterExpAndCompare("$.listBin1.[] == [100]", + parseExpAndCompare("$.listBin1.[] == [100]", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of(100)))); // integer values are read as long - parseFilterExpAndCompare("$.listBin1.get(type: LIST) == [100, 200, 300, 400]", + parseExpAndCompare("$.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 - parseFilterExpAndCompare("$.listBin1.get(type: LIST) == [100, 200, 300, 400]", + parseExpAndCompare("$.listBin1.get(type: LIST) == [100, 200, 300, 400]", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of(100L, 200L, 300L, 400L)))); - parseFilterExpAndCompare("$.listBin1.get(type: LIST) == ['yes']", + parseExpAndCompare("$.listBin1.get(type: LIST) == ['yes']", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of("yes")))); - parseFilterExpAndCompare("$.listBin1.get(type: LIST) == ['yes', 'of course']", + parseExpAndCompare("$.listBin1.get(type: LIST) == ['yes', 'of course']", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of("yes", "of course")))); - parseFilterExpAndCompare("$.listBin1.get(type: LIST) == [\"yes\"]", + parseExpAndCompare("$.listBin1.get(type: LIST) == [\"yes\"]", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of("yes")))); - parseFilterExpAndCompare("$.listBin1.get(type: LIST) == [\"yes\", \"of course\"]", + parseExpAndCompare("$.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(() -> - parseFilterExpAndCompare("$.listBin1.get(type: LIST) == [yes, of course]", + parseExpAndCompare("$.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() { - parseFilterExpAndCompare("[100] == $.listBin1.get(type: LIST)", + parseExpAndCompare("[100] == $.listBin1.get(type: LIST)", Exp.eq(Exp.val(List.of(100)), Exp.listBin("listBin1"))); - parseFilterExpAndCompare("[100] == $.listBin1.[]", + parseExpAndCompare("[100] == $.listBin1.[]", Exp.eq(Exp.val(List.of(100)), Exp.listBin("listBin1"))); // integer values are read as long - parseFilterExpAndCompare("[100, 200, 300, 400] == $.listBin1.get(type: LIST)", + parseExpAndCompare("[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 - parseFilterExpAndCompare("[100, 200, 300, 400] == $.listBin1.get(type: LIST)", + parseExpAndCompare("[100, 200, 300, 400] == $.listBin1.get(type: LIST)", Exp.eq(Exp.val(List.of(100L, 200L, 300L, 400L)), Exp.listBin("listBin1"))); - parseFilterExpAndCompare("['yes'] == $.listBin1.get(type: LIST)", + parseExpAndCompare("['yes'] == $.listBin1.get(type: LIST)", Exp.eq(Exp.val(List.of("yes")), Exp.listBin("listBin1"))); - parseFilterExpAndCompare("['yes', 'of course'] == $.listBin1.get(type: LIST)", + parseExpAndCompare("['yes', 'of course'] == $.listBin1.get(type: LIST)", Exp.eq(Exp.val(List.of("yes", "of course")), Exp.listBin("listBin1"))); - parseFilterExpAndCompare("[\"yes\"] == $.listBin1.get(type: LIST)", + parseExpAndCompare("[\"yes\"] == $.listBin1.get(type: LIST)", Exp.eq(Exp.val(List.of("yes")), Exp.listBin("listBin1"))); - parseFilterExpAndCompare("[\"yes\", \"of course\"] == $.listBin1.get(type: LIST)", + parseExpAndCompare("[\"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(() -> - parseFilterExpAndCompare("[yes, of course] == $.listBin1.get(type: LIST)", + parseExpAndCompare("[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 - parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {100:100}", + parseExpAndCompare("$.mapBin1.get(type: MAP) == {100:100}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(100, 100)))); - parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {100 : 100}", + parseExpAndCompare("$.mapBin1.get(type: MAP) == {100 : 100}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(100, 100)))); - parseFilterExpAndCompare("$.mapBin1.{} == {100:100}", + parseExpAndCompare("$.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 - parseFilterExpAndCompare("$.mapBin1.{} == {'" + encodedBlobKey + "':100}", + parseExpAndCompare("$.mapBin1.{} == {'" + encodedBlobKey + "':100}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(encodedBlobKey, 100)))); // integer values are read as long - parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {100:200, 300:400}", + parseExpAndCompare("$.mapBin1.get(type: MAP) == {100:200, 300:400}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(100L, 200L, 300L, 400L)))); - parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {100:200, 300:400}", + parseExpAndCompare("$.mapBin1.get(type: MAP) == {100:200, 300:400}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(100, 200, 300, 400)))); - parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {'yes?':'yes!'}", + parseExpAndCompare("$.mapBin1.get(type: MAP) == {'yes?':'yes!'}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("yes?", "yes!")))); - parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {\"yes\" : \"yes\"}", + parseExpAndCompare("$.mapBin1.get(type: MAP) == {\"yes\" : \"yes\"}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("yes", "yes")))); - parseFilterExpAndCompare( + parseExpAndCompare( "$.mapBin1.get(type: MAP) == {\"yes of course\" : \"yes of course\"}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("yes of course", "yes of course")))); - parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {\"yes\" : [\"yes\", \"of course\"]}", + parseExpAndCompare("$.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(() -> - parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {yes, of course}", + parseExpAndCompare("$.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(() -> - parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == ['yes', 'of course']", + parseExpAndCompare("$.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(() -> - parseFilterExpAndCompare("$.mapBin1.get(type: MAP) == {[100]:[100]}", + parseExpAndCompare("$.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 - parseFilterExpAndCompare("{100:100} == $.mapBin1.get(type: MAP)", + parseExpAndCompare("{100:100} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf(100, 100)), Exp.mapBin("mapBin1"))); - parseFilterExpAndCompare("{100 : 100} == $.mapBin1.get(type: MAP)", + parseExpAndCompare("{100 : 100} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf(100, 100)), Exp.mapBin("mapBin1"))); - parseFilterExpAndCompare("{100:100} == $.mapBin1.{}", + parseExpAndCompare("{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 - parseFilterExpAndCompare("{'" + encodedBlobKey + "':100} == $.mapBin1.{}", + parseExpAndCompare("{'" + encodedBlobKey + "':100} == $.mapBin1.{}", Exp.eq(Exp.val(treeMapOf(encodedBlobKey, 100)), Exp.mapBin("mapBin1"))); // integer values are read as long - parseFilterExpAndCompare("{100:200, 300:400} == $.mapBin1.get(type: MAP)", + parseExpAndCompare("{100:200, 300:400} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf(100L, 200L, 300L, 400L)), Exp.mapBin("mapBin1"))); - parseFilterExpAndCompare("{100:200, 300:400} == $.mapBin1.get(type: MAP)", + parseExpAndCompare("{100:200, 300:400} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf(100, 200, 300, 400)), Exp.mapBin("mapBin1"))); - parseFilterExpAndCompare("{'yes?':'yes!'} == $.mapBin1.get(type: MAP)", + parseExpAndCompare("{'yes?':'yes!'} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf("yes?", "yes!")), Exp.mapBin("mapBin1"))); - parseFilterExpAndCompare("{\"yes\" : \"yes\"} == $.mapBin1.get(type: MAP)", + parseExpAndCompare("{\"yes\" : \"yes\"} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf("yes", "yes")), Exp.mapBin("mapBin1"))); - parseFilterExpAndCompare( + parseExpAndCompare( "{\"yes of course\" : \"yes of course\"} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(treeMapOf("yes of course", "yes of course")), Exp.mapBin("mapBin1"))); - parseFilterExpAndCompare("{\"yes\" : [\"yes\", \"of course\"]} == $.mapBin1.get(type: MAP)", + parseExpAndCompare("{\"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(() -> - parseFilterExpAndCompare("{yes, of course} == $.mapBin1.get(type: MAP)", + parseExpAndCompare("{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(() -> - parseFilterExpAndCompare("['yes', 'of course'] == $.mapBin1.get(type: MAP)", // incorrect: must be {} + parseExpAndCompare("['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(() -> - parseFilterExpAndCompare("{[100]:[100]} == $.mapBin1.get(type: MAP)", + parseExpAndCompare("{[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() { - parseFilterExpAndCompare("$.stringBin1.get(type: STRING) == $.stringBin2.get(type: STRING)", + parseExpAndCompare("$.stringBin1.get(type: STRING) == $.stringBin2.get(type: STRING)", Exp.eq(Exp.stringBin("stringBin1"), Exp.stringBin("stringBin2"))); } @Test void twoIntegerBinsComparison() { - parseFilterExpAndCompare("$.intBin1.get(type: INT) == $.intBin2.get(type: INT)", + parseExpAndCompare("$.intBin1.get(type: INT) == $.intBin2.get(type: INT)", Exp.eq(Exp.intBin("intBin1"), Exp.intBin("intBin2"))); } @Test void twoFloatBinsComparison() { - parseFilterExpAndCompare("$.floatBin1.get(type: FLOAT) == $.floatBin2.get(type: FLOAT)", + parseExpAndCompare("$.floatBin1.get(type: FLOAT) == $.floatBin2.get(type: FLOAT)", Exp.eq(Exp.floatBin("floatBin1"), Exp.floatBin("floatBin2"))); } @Test void twoBlobBinsComparison() { - parseFilterExpAndCompare("$.blobBin1.get(type: BLOB) == $.blobBin2.get(type: BLOB)", + parseExpAndCompare("$.blobBin1.get(type: BLOB) == $.blobBin2.get(type: BLOB)", Exp.eq(Exp.blobBin("blobBin1"), Exp.blobBin("blobBin2"))); } @Test void negativeTwoDifferentBinTypesComparison() { - assertThatThrownBy(() -> parseFilterExp("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")) + assertThatThrownBy(() -> parseExp("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Cannot compare STRING to FLOAT"); } @Test void secondDegreeExplicitFloat() { - parseFilterExpAndCompare("($.apples.get(type: FLOAT) + $.bananas.get(type: FLOAT)) > 10.5", + parseExpAndCompare("($.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() { - parseFilterExpAndCompare("(($.apples.get(type: FLOAT) + $.bananas.get(type: FLOAT))" + + parseExpAndCompare("(($.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() { ) ); - parseFilterExpAndCompare("$.a.get(type: INT) == " + + parseExpAndCompare("$.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() { ) ); - parseFilterExpAndCompare("$.a.get(type: STRING) == " + + parseExpAndCompare("$.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/expression/ImplicitTypesTests.java b/src/test/java/com/aerospike/dsl/expression/ImplicitTypesTests.java index 2765fff..2d657bb 100644 --- a/src/test/java/com/aerospike/dsl/expression/ImplicitTypesTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ImplicitTypesTests.java @@ -3,23 +3,23 @@ import com.aerospike.client.exp.Exp; import org.junit.jupiter.api.Test; -import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseExpAndCompare; public class ImplicitTypesTests { @Test void floatComparison() { - parseFilterExpAndCompare("$.floatBin1 >= 100.25", + parseExpAndCompare("$.floatBin1 >= 100.25", Exp.ge(Exp.floatBin("floatBin1"), Exp.val(100.25))); } @Test void booleanComparison() { - parseFilterExpAndCompare("$.boolBin1 == true", + parseExpAndCompare("$.boolBin1 == true", Exp.eq(Exp.boolBin("boolBin1"), Exp.val(true))); - parseFilterExpAndCompare("false == $.boolBin1", + parseExpAndCompare("false == $.boolBin1", Exp.eq(Exp.val(false), Exp.boolBin("boolBin1"))); - parseFilterExpAndCompare("$.boolBin1 != false", + parseExpAndCompare("$.boolBin1 != false", Exp.ne(Exp.boolBin("boolBin1"), Exp.val(false))); } @@ -31,7 +31,7 @@ void binBooleanImplicitLogicalComparison() { // Exp.and(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2"))); // parseFilterExpAndCompare("$.boolBin1 or $.boolBin2", // Exp.or(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2"))); - parseFilterExpAndCompare("not($.boolBin1)", + parseExpAndCompare("not($.boolBin1)", Exp.not(Exp.boolBin("boolBin1"))); // parseFilterExpAndCompare("exclusive($.boolBin1, $.boolBin2)", // Exp.exclusive(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2"))); @@ -39,19 +39,19 @@ void binBooleanImplicitLogicalComparison() { @Test void implicitDefaultIntComparison() { - parseFilterExpAndCompare("$.intBin1 < $.intBin2", + parseExpAndCompare("$.intBin1 < $.intBin2", Exp.lt(Exp.intBin("intBin1"), Exp.intBin("intBin2"))); } @Test void secondDegreeImplicitCastingFloat() { - parseFilterExpAndCompare("($.apples + $.bananas) > 10.5", + parseExpAndCompare("($.apples + $.bananas) > 10.5", Exp.gt(Exp.add(Exp.floatBin("apples"), Exp.floatBin("bananas")), Exp.val(10.5))); } @Test void secondDegreeComplicatedFloatFirstImplicitCastingFloat() { - parseFilterExpAndCompare("($.apples + $.bananas) > 10.5 and ($.oranges + $.grapes) <= 5", + parseExpAndCompare("($.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() { - parseFilterExpAndCompare("($.apples + $.bananas) > 5 and ($.oranges + $.grapes) <= 10.5", + parseExpAndCompare("($.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() { - parseFilterExpAndCompare("(($.apples + $.bananas) + $.oranges) > 10", + parseExpAndCompare("(($.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() { - parseFilterExpAndCompare("(($.apples + $.bananas) + $.oranges) > 10.5", + parseExpAndCompare("(($.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() { - parseFilterExpAndCompare("(($.apples + $.bananas) + ($.oranges + $.acai)) > 10", + parseExpAndCompare("(($.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() { - parseFilterExpAndCompare("(($.apples + $.bananas) + ($.oranges + $.acai)) > 10.5", + parseExpAndCompare("(($.apples + $.bananas) + ($.oranges + $.acai)) > 10.5", Exp.gt( Exp.add( Exp.add(Exp.floatBin("apples"), Exp.floatBin("bananas")), @@ -128,7 +128,7 @@ void complicatedWhenImplicitTypeInt() { ) ); - parseFilterExpAndCompare("$.a == (when($.b == 1 => $.a1, $.b == 2 => $.a2, $.b == 3 => $.a3, default => $.a4+1))", + parseExpAndCompare("$.a == (when($.b == 1 => $.a1, $.b == 2 => $.a2, $.b == 3 => $.a3, default => $.a4+1))", expected); } @@ -154,7 +154,7 @@ void complicatedWhenImplicitTypeString() { ) ); - parseFilterExpAndCompare("$.a == (when($.b == 1 => $.a1, $.b == 2 => $.a2, $.b == 3 => $.a3, default => \"hello\"))", + parseExpAndCompare("$.a == (when($.b == 1 => $.a1, $.b == 2 => $.a2, $.b == 3 => $.a3, default => \"hello\"))", expected); } } diff --git a/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java index bc1bb71..06ef10e 100644 --- a/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java @@ -9,8 +9,8 @@ import java.util.List; -import static com.aerospike.dsl.util.TestUtils.parseFilterExp; -import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseExp; +import static com.aerospike.dsl.util.TestUtils.parseExpAndCompare; import static org.assertj.core.api.Assertions.assertThatThrownBy; class ListExpressionsTests { @@ -26,10 +26,10 @@ void listByIndexInteger() { ), Exp.val(100)); // Implicit detect as Int - parseFilterExpAndCompare("$.listBin1.[0] == 100", expected); - parseFilterExpAndCompare("$.listBin1.[0].get(type: INT) == 100", expected); - parseFilterExpAndCompare("$.listBin1.[0].get(type: INT, return: VALUE) == 100", expected); - parseFilterExpAndCompare("$.listBin1.[0].asInt() == 100", expected); + parseExpAndCompare("$.listBin1.[0] == 100", expected); + parseExpAndCompare("$.listBin1.[0].get(type: INT) == 100", expected); + parseExpAndCompare("$.listBin1.[0].get(type: INT, return: VALUE) == 100", expected); + parseExpAndCompare("$.listBin1.[0].asInt() == 100", expected); } @Test @@ -43,9 +43,9 @@ void listByIndexOtherTypes() { ), Exp.val("stringVal")); // Implicit detect as string - parseFilterExpAndCompare("$.listBin1.[0] == \"stringVal\"", expected); - parseFilterExpAndCompare("$.listBin1.[0].get(type: STRING) == \"stringVal\"", expected); - parseFilterExpAndCompare("$.listBin1.[0].get(type: STRING, return: VALUE) == \"stringVal\"", expected); + parseExpAndCompare("$.listBin1.[0] == \"stringVal\"", expected); + parseExpAndCompare("$.listBin1.[0].get(type: STRING) == \"stringVal\"", expected); + parseExpAndCompare("$.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 - parseFilterExpAndCompare("$.listBin1.[0] == true", expected); - parseFilterExpAndCompare("$.listBin1.[0].get(type: BOOL) == true", expected); - parseFilterExpAndCompare("$.listBin1.[0].get(type: BOOL, return: VALUE) == true", expected); + parseExpAndCompare("$.listBin1.[0] == true", expected); + parseExpAndCompare("$.listBin1.[0].get(type: BOOL) == true", expected); + parseExpAndCompare("$.listBin1.[0].get(type: BOOL, return: VALUE) == true", expected); } @Test @@ -70,10 +70,10 @@ void listByValue() { Exp.listBin("listBin1") ), Exp.val(100)); - parseFilterExpAndCompare("$.listBin1.[=100] == 100", expected); - parseFilterExpAndCompare("$.listBin1.[=100].get(type: INT) == 100", expected); - parseFilterExpAndCompare("$.listBin1.[=100].get(type: INT, return: VALUE) == 100", expected); - parseFilterExpAndCompare("$.listBin1.[=100].asInt() == 100", expected); + parseExpAndCompare("$.listBin1.[=100] == 100", expected); + parseExpAndCompare("$.listBin1.[=100].get(type: INT) == 100", expected); + parseExpAndCompare("$.listBin1.[=100].get(type: INT, return: VALUE) == 100", expected); + parseExpAndCompare("$.listBin1.[=100].asInt() == 100", expected); } @Test @@ -84,8 +84,8 @@ void listByValueCount() { Exp.listBin("listBin1")), Exp.val(0) ); - parseFilterExpAndCompare("$.listBin1.[=100].count() > 0", expected); - parseFilterExpAndCompare("$.listBin1.[=100].[].count() > 0", expected); + parseExpAndCompare("$.listBin1.[=100].count() > 0", expected); + parseExpAndCompare("$.listBin1.[=100].[].count() > 0", expected); } @Test @@ -98,10 +98,10 @@ void listByRank() { Exp.listBin("listBin1") ), Exp.val(100)); - parseFilterExpAndCompare("$.listBin1.[#-1] == 100", expected); - parseFilterExpAndCompare("$.listBin1.[#-1].get(type: INT) == 100", expected); - parseFilterExpAndCompare("$.listBin1.[#-1].get(type: INT, return: VALUE) == 100", expected); - parseFilterExpAndCompare("$.listBin1.[#-1].asInt() == 100", expected); + parseExpAndCompare("$.listBin1.[#-1] == 100", expected); + parseExpAndCompare("$.listBin1.[#-1].get(type: INT) == 100", expected); + parseExpAndCompare("$.listBin1.[#-1].get(type: INT, return: VALUE) == 100", expected); + parseExpAndCompare("$.listBin1.[#-1].asInt() == 100", expected); } @Test @@ -116,9 +116,9 @@ void listBinElementEquals_Nested() { CTX.listIndex(0) ), Exp.val(100)); - parseFilterExpAndCompare("$.listBin1.[0].[0].[0] == 100", expected); - parseFilterExpAndCompare("$.listBin1.[0].[0].[0].get(type: INT) == 100", expected); - parseFilterExpAndCompare("$.listBin1.[0].[0].[0].get(type: INT, return: VALUE) == 100", expected); + parseExpAndCompare("$.listBin1.[0].[0].[0] == 100", expected); + parseExpAndCompare("$.listBin1.[0].[0].[0].get(type: INT) == 100", expected); + parseExpAndCompare("$.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)); - parseFilterExpAndCompare("$.listBin1.[].count() == 1", expected); + parseExpAndCompare("$.listBin1.[].count() == 1", expected); // the default behaviour for count() without List '[]' or Map '{}' designators is List - parseFilterExpAndCompare("$.listBin1.count() == 1", expected); + parseExpAndCompare("$.listBin1.count() == 1", expected); } @Test @@ -143,10 +143,10 @@ void nestedListSize() { Exp.listBin("listBin1")) ), Exp.val(100)); - parseFilterExpAndCompare("$.listBin1.[1].[].count() == 100", expected); + parseExpAndCompare("$.listBin1.[1].[].count() == 100", expected); // the default behaviour for count() without List '[]' or Map '{}' designators is List - parseFilterExpAndCompare("$.listBin1.[1].count() == 100", expected); + parseExpAndCompare("$.listBin1.[1].count() == 100", expected); } @@ -162,10 +162,10 @@ void nestedListSizeWithContext() { CTX.listIndex(1)) ), Exp.val(100)); - parseFilterExpAndCompare("$.listBin1.[1].[2].[].count() == 100", expected); + parseExpAndCompare("$.listBin1.[1].[2].[].count() == 100", expected); // the default behaviour for count() without List '[]' or Map '{}' designators is List - parseFilterExpAndCompare("$.listBin1.[1].[2].count() == 100", expected); + parseExpAndCompare("$.listBin1.[1].[2].count() == 100", expected); } @Test @@ -179,7 +179,7 @@ void nestedLists() { CTX.listIndex(5) ), Exp.val("stringVal")); - parseFilterExpAndCompare("$.listBin1.[5].[1].get(type: STRING) == \"stringVal\"", expected); + parseExpAndCompare("$.listBin1.[5].[1].get(type: STRING) == \"stringVal\"", expected); } @Test @@ -195,8 +195,8 @@ void nestedListsWithDifferentContextTypes() { ), Exp.val("stringVal")); // Implicit detect as String - parseFilterExpAndCompare("$.listBin1.[5].[#-1] == \"stringVal\"", expected); - parseFilterExpAndCompare("$.listBin1.[5].[#-1].get(type: STRING) == \"stringVal\"", expected); + parseExpAndCompare("$.listBin1.[5].[#-1] == \"stringVal\"", expected); + parseExpAndCompare("$.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 - parseFilterExpAndCompare("$.listBin1.[5].[#-1].[=100] == 200", expected); + parseExpAndCompare("$.listBin1.[5].[#-1].[=100] == 200", expected); } @Test @@ -223,21 +223,21 @@ void listBinElementCount() { ), Exp.val(100) ); - parseFilterExpAndCompare("$.listBin1.[0].count() == 100", expected); - parseFilterExpAndCompare("$.listBin1.[0].[].count() == 100", expected); + parseExpAndCompare("$.listBin1.[0].count() == 100", expected); + parseExpAndCompare("$.listBin1.[0].[].count() == 100", expected); } @Test void negativeSyntaxList() { // TODO: throw meaningful exception (by ANTLR?) - assertThatThrownBy(() -> parseFilterExp("$.listBin1.[stringValue] == 100")) + assertThatThrownBy(() -> parseExp("$.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(() -> parseFilterExp("$.listBin1.[#-1].get(type: INT) == \"stringValue\"")) + assertThatThrownBy(() -> parseExp("$.listBin1.[#-1].get(type: INT) == \"stringValue\"")) .isInstanceOf(NullPointerException.class); } @@ -248,7 +248,7 @@ void listIndexRange() { Exp.val(1), Exp.val(2), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[1:3]", expected); + parseExpAndCompare("$.listBin1.[1:3]", expected); // Negative expected = ListExp.getByIndexRange( @@ -256,7 +256,7 @@ void listIndexRange() { Exp.val(-3), Exp.val(4), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[-3:1]", expected); + parseExpAndCompare("$.listBin1.[-3:1]", expected); // Inverted expected = ListExp.getByIndexRange( @@ -264,14 +264,14 @@ void listIndexRange() { Exp.val(2), Exp.val(2), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[!2:4]", expected); + parseExpAndCompare("$.listBin1.[!2:4]", expected); // From start till the end expected = ListExp.getByIndexRange( ListReturnType.VALUE, Exp.val(1), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[1:]", expected); + parseExpAndCompare("$.listBin1.[1:]", expected); } @Test @@ -280,23 +280,23 @@ void listValueList() { ListReturnType.VALUE, Exp.val(List.of("a", "b", "c")), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[=a,b,c]", expected); - parseFilterExpAndCompare("$.listBin1.[=\"a\",\"b\",\"c\"]", expected); + parseExpAndCompare("$.listBin1.[=a,b,c]", expected); + parseExpAndCompare("$.listBin1.[=\"a\",\"b\",\"c\"]", expected); // Integer expected = ListExp.getByValueList( ListReturnType.VALUE, Exp.val(List.of(1, 2, 3)), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[=1,2,3]", expected); + parseExpAndCompare("$.listBin1.[=1,2,3]", expected); // Inverted expected = ListExp.getByValueList( ListReturnType.VALUE | ListReturnType.INVERTED, Exp.val(List.of("a", "b", "c")), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[!=a,b,c]", expected); - parseFilterExpAndCompare("$.listBin1.[!=\"a\",\"b\",\"c\"]", expected); + parseExpAndCompare("$.listBin1.[!=a,b,c]", expected); + parseExpAndCompare("$.listBin1.[!=\"a\",\"b\",\"c\"]", expected); } @Test @@ -307,7 +307,7 @@ void listValueRange() { Exp.val(111), Exp.val(334), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[=111:334]", expected); + parseExpAndCompare("$.listBin1.[=111:334]", expected); // Inverted expected = ListExp.getByValueRange( @@ -315,7 +315,7 @@ void listValueRange() { Exp.val(10), Exp.val(20), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[!=10:20]", expected); + parseExpAndCompare("$.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")); - parseFilterExpAndCompare("$.listBin1.[=111:]", expected); + parseExpAndCompare("$.listBin1.[=111:]", expected); } @Test @@ -333,7 +333,7 @@ void listRankRange() { Exp.val(0), Exp.val(3), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[#0:3]", expected); + parseExpAndCompare("$.listBin1.[#0:3]", expected); // Inverted expected = ListExp.getByRankRange( @@ -341,14 +341,14 @@ void listRankRange() { Exp.val(0), Exp.val(3), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[!#0:3]", expected); + parseExpAndCompare("$.listBin1.[!#0:3]", expected); // From start till the end expected = ListExp.getByRankRange( ListReturnType.VALUE, Exp.val(-3), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[#-3:]", expected); + parseExpAndCompare("$.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)); - parseFilterExpAndCompare("$.listBin1.[5].[#-3:]", expected); + parseExpAndCompare("$.listBin1.[5].[#-3:]", expected); } @Test @@ -367,7 +367,7 @@ void listRankRangeRelative() { Exp.val("b"), Exp.val(2), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[#-3:-1~b]", expected); + parseExpAndCompare("$.listBin1.[#-3:-1~b]", expected); // Inverted expected = ListExp.getByValueRelativeRankRange( @@ -376,7 +376,7 @@ void listRankRangeRelative() { Exp.val("b"), Exp.val(2), Exp.listBin("listBin1")); - parseFilterExpAndCompare("$.listBin1.[!#-3:-1~b]", expected); + parseExpAndCompare("$.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")); - parseFilterExpAndCompare("$.listBin1.[#-3:~b]", expected); + parseExpAndCompare("$.listBin1.[#-3:~b]", expected); } @Test @@ -398,7 +398,7 @@ void listReturnTypes() { ), Exp.val(5)); // Implicit detect as Int - parseFilterExpAndCompare("$.listBin1.[0].get(return: COUNT) == 5", expected); + parseExpAndCompare("$.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 - parseFilterExpAndCompare("$.listBin1.[0].get(return: EXISTS) == true", expected); + parseExpAndCompare("$.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 - parseFilterExpAndCompare("$.listBin1.[0].get(return: INDEX) == 1", expected); + parseExpAndCompare("$.listBin1.[0].get(return: INDEX) == 1", expected); } } diff --git a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java index 9329ce6..fe4bc97 100644 --- a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java @@ -5,8 +5,8 @@ import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; -import static com.aerospike.dsl.util.TestUtils.parseFilterExp; -import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseExp; +import static com.aerospike.dsl.util.TestUtils.parseExpAndCompare; 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))); - parseFilterExpAndCompare("$.intBin1 > 100 and $.intBin2 > 100", expected1); + parseExpAndCompare("$.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? - parseFilterExpAndCompare("$.intBin1 > 100 and $.intBin2 > 100 or $.intBin3 < 100", expected2); - parseFilterExpAndCompare("($.intBin1 > 100 and $.intBin2 > 100) or $.intBin3 < 100", expected2); + parseExpAndCompare("$.intBin1 > 100 and $.intBin2 > 100 or $.intBin3 < 100", expected2); + parseExpAndCompare("($.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)) ) ); - parseFilterExpAndCompare("($.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 < 100))", expected3); + parseExpAndCompare("($.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 < 100))", expected3); // check that parentheses make difference - assertThatThrownBy(() -> parseFilterExpAndCompare("($.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 < 100))", expected2)) + assertThatThrownBy(() -> parseExpAndCompare("($.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 < 100))", expected2)) .isInstanceOf(AssertionFailedError.class); } @Test void logicalNot() { - parseFilterExpAndCompare("not($.keyExists())", Exp.not(Exp.keyExists())); + parseExpAndCompare("not($.keyExists())", Exp.not(Exp.keyExists())); } @Test void binLogicalExclusive() { - parseFilterExpAndCompare("exclusive($.hand == \"hook\", $.leg == \"peg\")", + parseExpAndCompare("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 - parseFilterExpAndCompare("exclusive($.a == \"aVal\", $.b == \"bVal\", $.c == \"cVal\", $.d == 4)", + parseExpAndCompare("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() { - parseFilterExpAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 < 100", + parseExpAndCompare("$.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(() -> parseFilterExp("($.intBin1 > 100 and ($.intBin2 > 100) or")) + assertThatThrownBy(() -> parseExp("($.intBin1 > 100 and ($.intBin2 > 100) or")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Could not parse given input"); - assertThatThrownBy(() -> parseFilterExp("and ($.intBin1 > 100 and ($.intBin2 > 100)")) + assertThatThrownBy(() -> parseExp("and ($.intBin1 > 100 and ($.intBin2 > 100)")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Could not parse given input"); - assertThatThrownBy(() -> parseFilterExp("($.intBin1 > 100 and ($.intBin2 > 100) not")) + assertThatThrownBy(() -> parseExp("($.intBin1 > 100 and ($.intBin2 > 100) not")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Could not parse given input"); - assertThatThrownBy(() -> parseFilterExp("($.intBin1 > 100 and ($.intBin2 > 100) exclusive")) + assertThatThrownBy(() -> parseExp("($.intBin1 > 100 and ($.intBin2 > 100) exclusive")) .isInstanceOf(AerospikeDSLException.class) .hasMessageContaining("Could not parse given input"); } @Test void negativeBinLogicalExclusiveWithOneParam() { - assertThatThrownBy(() -> parseFilterExpAndCompare("exclusive($.hand == \"hook\")", + assertThatThrownBy(() -> parseExpAndCompare("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/expression/MapAndListExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/MapAndListExpressionsTests.java index bdea01b..0c2926d 100644 --- a/src/test/java/com/aerospike/dsl/expression/MapAndListExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/MapAndListExpressionsTests.java @@ -9,7 +9,7 @@ import com.aerospike.client.exp.MapExp; import org.junit.jupiter.api.Test; -import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseExpAndCompare; public class MapAndListExpressionsTests { @@ -24,7 +24,7 @@ void listInsideAMap() { CTX.mapKey(Value.get("a")) ), Exp.val(100)); - parseFilterExpAndCompare("$.mapBin1.a.[0] == 100", expected); + parseExpAndCompare("$.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)); - parseFilterExpAndCompare("$.mapBin1.a.cc.[2].get(type: INT) > 100", expected); + parseExpAndCompare("$.mapBin1.a.cc.[2].get(type: INT) > 100", expected); } @Test @@ -50,7 +50,7 @@ void mapListList() { CTX.listIndex(0) ), Exp.val(100)); - parseFilterExpAndCompare("$.mapBin1.a.[0].[0] == 100", expected); + parseExpAndCompare("$.mapBin1.a.[0].[0] == 100", expected); } @Test @@ -63,7 +63,7 @@ void mapInsideAList() { Exp.listBin("listBin1"), CTX.listIndex(2) ), Exp.val(100)); - parseFilterExpAndCompare("$.listBin1.[2].cc.get(type: INT) > 100", expected); + parseExpAndCompare("$.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)); - parseFilterExpAndCompare("$.listBin1.[2].aa.cc > 100", expected); - parseFilterExpAndCompare("$.listBin1.[2].aa.cc.get(type: INT) > 100", expected); + parseExpAndCompare("$.listBin1.[2].aa.cc > 100", expected); + parseExpAndCompare("$.listBin1.[2].aa.cc.get(type: INT) > 100", expected); } @Test @@ -93,7 +93,7 @@ void listMapList() { CTX.mapKey(Value.get("a")) ), Exp.val(100)); - parseFilterExpAndCompare("$.listBin1.[1].a.[0] == 100", expected); + parseExpAndCompare("$.listBin1.[1].a.[0] == 100", expected); } @Test @@ -110,8 +110,8 @@ void listMapListSize() { ) ), Exp.val(100)); - parseFilterExpAndCompare("$.listBin1.[1].a.[0].count() == 100", expected); - parseFilterExpAndCompare("$.listBin1.[1].a.[0].[].count() == 100", expected); + parseExpAndCompare("$.listBin1.[1].a.[0].count() == 100", expected); + parseExpAndCompare("$.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)); - parseFilterExpAndCompare("$.mapBin1.a.[0].cc > 100", expected); - parseFilterExpAndCompare("$.mapBin1.a.[0].cc.get(type: INT) > 100", expected); + parseExpAndCompare("$.mapBin1.a.[0].cc > 100", expected); + parseExpAndCompare("$.mapBin1.a.[0].cc.get(type: INT) > 100", expected); } //@Test diff --git a/src/test/java/com/aerospike/dsl/expression/MapExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/MapExpressionsTests.java index dff3a7f..806f5eb 100644 --- a/src/test/java/com/aerospike/dsl/expression/MapExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/MapExpressionsTests.java @@ -11,7 +11,7 @@ import java.util.List; -import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseExpAndCompare; public class MapExpressionsTests { @@ -27,10 +27,10 @@ void mapOneLevelExpressions() { ), Exp.val(200)); // Implicit detect as Int - parseFilterExpAndCompare("$.mapBin1.a == 200", expected); - parseFilterExpAndCompare("$.mapBin1.a.get(type: INT) == 200", expected); - parseFilterExpAndCompare("$.mapBin1.a.get(type: INT, return: VALUE) == 200", expected); - parseFilterExpAndCompare("$.mapBin1.a.asInt() == 200", expected); + parseExpAndCompare("$.mapBin1.a == 200", expected); + parseExpAndCompare("$.mapBin1.a.get(type: INT) == 200", expected); + parseExpAndCompare("$.mapBin1.a.get(type: INT, return: VALUE) == 200", expected); + parseExpAndCompare("$.mapBin1.a.asInt() == 200", expected); // String expected = Exp.eq( @@ -42,9 +42,9 @@ void mapOneLevelExpressions() { ), Exp.val("stringVal")); // Implicit detect as String - parseFilterExpAndCompare("$.mapBin1.a == \"stringVal\"", expected); - parseFilterExpAndCompare("$.mapBin1.a.get(type: STRING) == \"stringVal\"", expected); - parseFilterExpAndCompare("$.mapBin1.a.get(type: STRING, return: VALUE) == \"stringVal\"", expected); + parseExpAndCompare("$.mapBin1.a == \"stringVal\"", expected); + parseExpAndCompare("$.mapBin1.a.get(type: STRING) == \"stringVal\"", expected); + parseExpAndCompare("$.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)); - parseFilterExpAndCompare("$.mapBin1.a.bb.bcc > 200", expected); - parseFilterExpAndCompare("$.mapBin1.a.bb.bcc.get(type: INT) > 200", expected); - parseFilterExpAndCompare("$.mapBin1.a.bb.bcc.get(type: INT, return: VALUE) > 200", expected); + parseExpAndCompare("$.mapBin1.a.bb.bcc > 200", expected); + parseExpAndCompare("$.mapBin1.a.bb.bcc.get(type: INT) > 200", expected); + parseExpAndCompare("$.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 - parseFilterExpAndCompare("$.mapBin1.a.bb.bcc == \"stringVal\"", expected); - parseFilterExpAndCompare("$.mapBin1.a.bb.bcc.get(type: STRING) == \"stringVal\"", expected); - parseFilterExpAndCompare("$.mapBin1.a.bb.bcc.get(type: STRING, return: VALUE) == \"stringVal\"", expected); + parseExpAndCompare("$.mapBin1.a.bb.bcc == \"stringVal\"", expected); + parseExpAndCompare("$.mapBin1.a.bb.bcc.get(type: STRING) == \"stringVal\"", expected); + parseExpAndCompare("$.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)); - parseFilterExpAndCompare("$.mapBin1.a.bb.bcc.get(type: INT) > 200", expected); - parseFilterExpAndCompare("$.mapBin1.a.\"bb\".bcc.get(type: INT) > 200", expected); - parseFilterExpAndCompare("$.mapBin1.a.'bb'.bcc.get(type: INT) > 200", expected); + parseExpAndCompare("$.mapBin1.a.bb.bcc.get(type: INT) > 200", expected); + parseExpAndCompare("$.mapBin1.a.\"bb\".bcc.get(type: INT) > 200", expected); + parseExpAndCompare("$.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)); - parseFilterExpAndCompare("$.mapBin1.\"127.0.0.1\".bcc.get(type: INT) > 200", expected); - parseFilterExpAndCompare("$.mapBin1.'127.0.0.1'.bcc.get(type: INT) > 200", expected); + parseExpAndCompare("$.mapBin1.\"127.0.0.1\".bcc.get(type: INT) > 200", expected); + parseExpAndCompare("$.mapBin1.'127.0.0.1'.bcc.get(type: INT) > 200", expected); } @Test @@ -113,7 +113,7 @@ void mapSize() { Exp.mapBin("mapBin1") ), Exp.val(200)); - parseFilterExpAndCompare("$.mapBin1.{}.count() > 200", expected); + parseExpAndCompare("$.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)); - parseFilterExpAndCompare("$.mapBin1.count() > 200", expected2); + parseExpAndCompare("$.mapBin1.count() > 200", expected2); } @Test @@ -135,7 +135,7 @@ void nestedMapSize() { Exp.mapBin("mapBin1")) ), Exp.val(200)); - parseFilterExpAndCompare("$.mapBin1.a.{}.count() == 200", expected); + parseExpAndCompare("$.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)); - parseFilterExpAndCompare("$.mapBin1.a.count() == 200", expected2); + parseExpAndCompare("$.mapBin1.a.count() == 200", expected2); } @Test @@ -161,7 +161,7 @@ void nestedMapSizeWithContext() { CTX.mapKey(Value.get("a"))) ), Exp.val(200)); - parseFilterExpAndCompare("$.mapBin1.a.b.{}.count() == 200", expected); + parseExpAndCompare("$.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)); - parseFilterExpAndCompare("$.mapBin1.a.b.count() == 200", expected2); + parseExpAndCompare("$.mapBin1.a.b.count() == 200", expected2); } @Test @@ -186,10 +186,10 @@ void mapByIndex() { Exp.mapBin("mapBin1") ), Exp.val(100)); - parseFilterExpAndCompare("$.mapBin1.{0} == 100", expected); - parseFilterExpAndCompare("$.mapBin1.{0}.get(type: INT) == 100", expected); - parseFilterExpAndCompare("$.mapBin1.{0}.get(type: INT, return: VALUE) == 100", expected); - parseFilterExpAndCompare("$.mapBin1.{0}.asInt() == 100", expected); + parseExpAndCompare("$.mapBin1.{0} == 100", expected); + parseExpAndCompare("$.mapBin1.{0}.get(type: INT) == 100", expected); + parseExpAndCompare("$.mapBin1.{0}.get(type: INT, return: VALUE) == 100", expected); + parseExpAndCompare("$.mapBin1.{0}.asInt() == 100", expected); } @Test @@ -201,10 +201,10 @@ void mapByValue() { Exp.mapBin("mapBin1") ), Exp.val(100)); - parseFilterExpAndCompare("$.mapBin1.{=100} == 100", expected); - parseFilterExpAndCompare("$.mapBin1.{=100}.get(type: INT) == 100", expected); - parseFilterExpAndCompare("$.mapBin1.{=100}.get(type: INT, return: VALUE) == 100", expected); - parseFilterExpAndCompare("$.mapBin1.{=100}.asInt() == 100", expected); + parseExpAndCompare("$.mapBin1.{=100} == 100", expected); + parseExpAndCompare("$.mapBin1.{=100}.get(type: INT) == 100", expected); + parseExpAndCompare("$.mapBin1.{=100}.get(type: INT, return: VALUE) == 100", expected); + parseExpAndCompare("$.mapBin1.{=100}.asInt() == 100", expected); } @Test @@ -215,8 +215,8 @@ void mapByValueCount() { Exp.mapBin("mapBin1")), Exp.val(0) ); - parseFilterExpAndCompare("$.mapBin1.{=100}.count() > 0", expected); - parseFilterExpAndCompare("$.mapBin1.{=100}.{}.count() > 0", expected); + parseExpAndCompare("$.mapBin1.{=100}.count() > 0", expected); + parseExpAndCompare("$.mapBin1.{=100}.{}.count() > 0", expected); } @Test @@ -229,10 +229,10 @@ void mapByRank() { Exp.mapBin("mapBin1") ), Exp.val(100)); - parseFilterExpAndCompare("$.mapBin1.{#-1} == 100", expected); - parseFilterExpAndCompare("$.mapBin1.{#-1}.get(type: INT) == 100", expected); - parseFilterExpAndCompare("$.mapBin1.{#-1}.get(type: INT, return: VALUE) == 100", expected); - parseFilterExpAndCompare("$.mapBin1.{#-1}.asInt() == 100", expected); + parseExpAndCompare("$.mapBin1.{#-1} == 100", expected); + parseExpAndCompare("$.mapBin1.{#-1}.get(type: INT) == 100", expected); + parseExpAndCompare("$.mapBin1.{#-1}.get(type: INT, return: VALUE) == 100", expected); + parseExpAndCompare("$.mapBin1.{#-1}.asInt() == 100", expected); } @Test @@ -246,10 +246,10 @@ void mapByRankWithNesting() { CTX.mapKey(Value.get("a")) ), Exp.val(100)); - parseFilterExpAndCompare("$.mapBin1.a.{#-1} == 100", expected); - parseFilterExpAndCompare("$.mapBin1.a.{#-1}.get(type: INT) == 100", expected); - parseFilterExpAndCompare("$.mapBin1.a.{#-1}.get(type: INT, return: VALUE) == 100", expected); - parseFilterExpAndCompare("$.mapBin1.a.{#-1}.asInt() == 100", expected); + parseExpAndCompare("$.mapBin1.a.{#-1} == 100", expected); + parseExpAndCompare("$.mapBin1.a.{#-1}.get(type: INT) == 100", expected); + parseExpAndCompare("$.mapBin1.a.{#-1}.get(type: INT, return: VALUE) == 100", expected); + parseExpAndCompare("$.mapBin1.a.{#-1}.asInt() == 100", expected); } @Test @@ -265,8 +265,8 @@ void nestedListsWithDifferentContextTypes() { ), Exp.val("stringVal")); // Implicit detect as String - parseFilterExpAndCompare("$.mapBin1.{5}.{#-1} == \"stringVal\"", expected); - parseFilterExpAndCompare("$.mapBin1.{5}.{#-1}.get(type: STRING) == \"stringVal\"", expected); + parseExpAndCompare("$.mapBin1.{5}.{#-1} == \"stringVal\"", expected); + parseExpAndCompare("$.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)); - parseFilterExpAndCompare("$.mapBin1.{5}.{#-1}.{=100} == 200", expected); + parseExpAndCompare("$.mapBin1.{5}.{#-1}.{=100} == 200", expected); } @Test @@ -288,8 +288,8 @@ void mapKeyRange() { Exp.val("a"), Exp.val("c"), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{a-c}", expected); - parseFilterExpAndCompare("$.mapBin1.{\"a\"-\"c\"}", expected); + parseExpAndCompare("$.mapBin1.{a-c}", expected); + parseExpAndCompare("$.mapBin1.{\"a\"-\"c\"}", expected); // Inverted expected = MapExp.getByKeyRange( @@ -297,8 +297,8 @@ void mapKeyRange() { Exp.val("a"), Exp.val("c"), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{!a-c}", expected); - parseFilterExpAndCompare("$.mapBin1.{!\"a\"-\"c\"}", expected); + parseExpAndCompare("$.mapBin1.{!a-c}", expected); + parseExpAndCompare("$.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")); - parseFilterExpAndCompare("$.mapBin1.{a-}", expected); - parseFilterExpAndCompare("$.mapBin1.{\"a\"-}", expected); + parseExpAndCompare("$.mapBin1.{a-}", expected); + parseExpAndCompare("$.mapBin1.{\"a\"-}", expected); } @Test @@ -316,16 +316,16 @@ void mapKeyList() { MapReturnType.VALUE, Exp.val(List.of("a", "b", "c")), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{a,b,c}", expected); - parseFilterExpAndCompare("$.mapBin1.{\"a\",\"b\",\"c\"}", expected); + parseExpAndCompare("$.mapBin1.{a,b,c}", expected); + parseExpAndCompare("$.mapBin1.{\"a\",\"b\",\"c\"}", expected); // Inverted expected = MapExp.getByKeyList( MapReturnType.VALUE | MapReturnType.INVERTED, Exp.val(List.of("a", "b", "c")), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{!a,b,c}", expected); - parseFilterExpAndCompare("$.mapBin1.{!\"a\",\"b\",\"c\"}", expected); + parseExpAndCompare("$.mapBin1.{!a,b,c}", expected); + parseExpAndCompare("$.mapBin1.{!\"a\",\"b\",\"c\"}", expected); } @Test @@ -335,7 +335,7 @@ void mapIndexRange() { Exp.val(1), Exp.val(2), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{1:3}", expected); + parseExpAndCompare("$.mapBin1.{1:3}", expected); // Negative expected = MapExp.getByIndexRange( @@ -343,7 +343,7 @@ void mapIndexRange() { Exp.val(-3), Exp.val(4), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{-3:1}", expected); + parseExpAndCompare("$.mapBin1.{-3:1}", expected); // Inverted expected = MapExp.getByIndexRange( @@ -351,14 +351,14 @@ void mapIndexRange() { Exp.val(2), Exp.val(2), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{!2:4}", expected); + parseExpAndCompare("$.mapBin1.{!2:4}", expected); // From start till the end expected = MapExp.getByIndexRange( MapReturnType.VALUE, Exp.val(1), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{1:}", expected); + parseExpAndCompare("$.mapBin1.{1:}", expected); } @Test @@ -367,23 +367,23 @@ void mapValueList() { MapReturnType.VALUE, Exp.val(List.of("a", "b", "c")), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{=a,b,c}", expected); - parseFilterExpAndCompare("$.mapBin1.{=\"a\",\"b\",\"c\"}", expected); + parseExpAndCompare("$.mapBin1.{=a,b,c}", expected); + parseExpAndCompare("$.mapBin1.{=\"a\",\"b\",\"c\"}", expected); // Integer expected = MapExp.getByValueList( MapReturnType.VALUE, Exp.val(List.of(1, 2, 3)), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{=1,2,3}", expected); + parseExpAndCompare("$.mapBin1.{=1,2,3}", expected); // Inverted expected = MapExp.getByValueList( MapReturnType.VALUE | MapReturnType.INVERTED, Exp.val(List.of("a", "b", "c")), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{!=a,b,c}", expected); - parseFilterExpAndCompare("$.mapBin1.{!=\"a\",\"b\",\"c\"}", expected); + parseExpAndCompare("$.mapBin1.{!=a,b,c}", expected); + parseExpAndCompare("$.mapBin1.{!=\"a\",\"b\",\"c\"}", expected); } @Test @@ -393,7 +393,7 @@ void mapValueRange() { Exp.val(111), Exp.val(334), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{=111:334}", expected); + parseExpAndCompare("$.mapBin1.{=111:334}", expected); // Inverted expected = MapExp.getByValueRange( @@ -401,7 +401,7 @@ void mapValueRange() { Exp.val(10), Exp.val(20), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{!=10:20}", expected); + parseExpAndCompare("$.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")); - parseFilterExpAndCompare("$.mapBin1.{=111:}", expected); + parseExpAndCompare("$.mapBin1.{=111:}", expected); } @Test @@ -419,7 +419,7 @@ void mapRankRange() { Exp.val(0), Exp.val(3), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{#0:3}", expected); + parseExpAndCompare("$.mapBin1.{#0:3}", expected); // Inverted expected = MapExp.getByRankRange( @@ -427,14 +427,14 @@ void mapRankRange() { Exp.val(0), Exp.val(3), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{!#0:3}", expected); + parseExpAndCompare("$.mapBin1.{!#0:3}", expected); // From start till the end expected = MapExp.getByRankRange( MapReturnType.VALUE, Exp.val(-3), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{#-3:}", expected); + parseExpAndCompare("$.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)); - parseFilterExpAndCompare("$.mapBin1.{5}.{#-3:}", expected); + parseExpAndCompare("$.mapBin1.{5}.{#-3:}", expected); } @Test @@ -453,7 +453,7 @@ void mapRankRangeRelative() { Exp.val(10), Exp.val(2), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{#-1:1~10}", expected); + parseExpAndCompare("$.mapBin1.{#-1:1~10}", expected); // Inverted expected = MapExp.getByValueRelativeRankRange( @@ -462,7 +462,7 @@ void mapRankRangeRelative() { Exp.val(10), Exp.val(2), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{!#-1:1~10}", expected); + parseExpAndCompare("$.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")); - parseFilterExpAndCompare("$.mapBin1.{#-2:~10}", expected); + parseExpAndCompare("$.mapBin1.{#-2:~10}", expected); } @Test @@ -481,7 +481,7 @@ void mapIndexRangeRelative() { Exp.val(0), Exp.val(1), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{0:1~a}", expected); + parseExpAndCompare("$.mapBin1.{0:1~a}", expected); // Inverted expected = MapExp.getByKeyRelativeIndexRange( @@ -490,7 +490,7 @@ void mapIndexRangeRelative() { Exp.val(0), Exp.val(1), Exp.mapBin("mapBin1")); - parseFilterExpAndCompare("$.mapBin1.{!0:1~a}", expected); + parseExpAndCompare("$.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")); - parseFilterExpAndCompare("$.mapBin1.{0:~a}", expected); + parseExpAndCompare("$.mapBin1.{0:~a}", expected); } @Test @@ -512,7 +512,7 @@ void mapReturnTypes() { ), Exp.val(5)); // Implicit detect as Int - parseFilterExpAndCompare("$.mapBin1.a.get(type: INT, return: COUNT) == 5", expected); + parseExpAndCompare("$.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 - parseFilterExpAndCompare("$.mapBin1.a.get(return: ORDERED_MAP)", expected); + parseExpAndCompare("$.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 - parseFilterExpAndCompare("$.mapBin1.a.get(type: INT, return: RANK) == 5", expected); + parseExpAndCompare("$.mapBin1.a.get(type: INT, return: RANK) == 5", expected); } } diff --git a/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java index 107f2bc..9c99f09 100644 --- a/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java +++ b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java @@ -4,8 +4,8 @@ import com.aerospike.dsl.exception.AerospikeDSLException; import org.junit.jupiter.api.Test; -import static com.aerospike.dsl.util.TestUtils.parseFilterExp; -import static com.aerospike.dsl.util.TestUtils.parseFilterExpAndCompare; +import static com.aerospike.dsl.util.TestUtils.parseExp; +import static com.aerospike.dsl.util.TestUtils.parseExpAndCompare; 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)); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(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)); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(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)); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(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)); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(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")); - parseFilterExpAndCompare(input2, expected2); + parseExpAndCompare(input2, expected2); } @Test @@ -52,7 +52,7 @@ void isTombstone() { // Expression to find records that are tombstones String input = "$.isTombstone()"; Exp expected = Exp.isTombstone(); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(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(); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(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")); - parseFilterExpAndCompare(inputMetadataLeft, expectedLeft); + parseExpAndCompare(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()); - parseFilterExpAndCompare(inputMetadataRight, expectedRight); + parseExpAndCompare(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)); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(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")); - parseFilterExpAndCompare(input2, expected2); + parseExpAndCompare(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")); - parseFilterExpAndCompare(input3, expected3); + parseExpAndCompare(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()); - parseFilterExpAndCompare(input4, expected4); + parseExpAndCompare(input4, expected4); } @Test @@ -108,12 +108,12 @@ void setName() { Exp.eq(Exp.setName(), Exp.val("groupA")), Exp.eq(Exp.setName(), Exp.val("groupB")) ); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(input, expected); // set name compared with String Bin input = "$.mySetBin == $.setName()"; expected = Exp.eq(Exp.stringBin("mySetBin"), Exp.setName()); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(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)); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(input, expected); } //@Test void negativeTtlAsDifferentType() { // TODO: should be supported when adding operator + metadata validations (requires a refactor) - assertThatThrownBy(() -> parseFilterExp("$.ttl() == true")) + assertThatThrownBy(() -> parseExp("$.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)); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(input, expected); } @Test @@ -148,7 +148,7 @@ void metadataWithLogicalOperatorsExpressions() { Exp.gt(Exp.deviceSize(), Exp.val(1024)), Exp.lt(Exp.ttl(), Exp.val(300)) ); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(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)) ); - parseFilterExpAndCompare(input2, expected2); + parseExpAndCompare(input2, expected2); } @Test @@ -166,13 +166,13 @@ void metadataAsExpressionWithLogicalOperator() { Exp.isTombstone(), Exp.lt(Exp.ttl(), Exp.val(300)) ); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(input, expected); input = "$.ttl() < 300 or $.keyExists()"; expected = Exp.or( Exp.lt(Exp.ttl(), Exp.val(300)), Exp.keyExists() ); - parseFilterExpAndCompare(input, expected); + parseExpAndCompare(input, expected); } } diff --git a/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java index 07ab76d..b94da89 100644 --- a/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java @@ -2,7 +2,7 @@ import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; -import com.aerospike.dsl.index.Index; +import com.aerospike.dsl.Index; import org.junit.jupiter.api.Test; import java.util.List; diff --git a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java index a75f6a4..427d042 100644 --- a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java @@ -148,7 +148,9 @@ void twoBlobBinsComparison() { } @Test - void differentBinTypes_nullResult() { - assertThat(parseFilter("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")).isNull(); + void negativeTwoDifferentBinTypesComparison() { + assertThatThrownBy(() -> parseFilter("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")) + .isInstanceOf(AerospikeDSLException.class) + .hasMessage("Cannot compare STRING to FLOAT"); } } diff --git a/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java b/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java index 7985a41..c1e810d 100644 --- a/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java +++ b/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java @@ -3,8 +3,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; -import com.aerospike.dsl.ParsedExpression; -import com.aerospike.dsl.index.Index; +import com.aerospike.dsl.Index; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -19,8 +18,7 @@ void binLogical_AND_2_no_indexes() { Filter filter = null; Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", expected); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp); } @Test @@ -33,8 +31,7 @@ void binLogical_AND_2_all_indexes() { Filter filter = Filter.range("intBin2", 101, Long.MAX_VALUE); Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", namespace, indexes, expected); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, namespace, indexes); } @Test @@ -48,8 +45,7 @@ void binLogical_AND_2_all_indexes_no_cardinality() { Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", namespace, indexes, expected); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, namespace, indexes); } @Test @@ -60,8 +56,7 @@ void binLogical_AND_2_one_index() { Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", namespace, indexes, expected); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, namespace, indexes); } @Test @@ -79,8 +74,8 @@ void binLogical_AND_3_all_indexes() { Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", namespace, indexes, expected); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, + namespace, indexes); } @Test @@ -91,6 +86,7 @@ void binLogical_AND_3_all_indexes_same_cardinality() { Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(100).build() ); String namespace = "test1"; + // Filter is chosen alphabetically because the same cardinality is given Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); Exp exp = Exp.and( Exp.and( @@ -98,8 +94,8 @@ void binLogical_AND_3_all_indexes_same_cardinality() { Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", namespace, indexes, expected); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, + namespace, indexes); } @Test @@ -110,6 +106,7 @@ void binLogical_AND_3_all_indexes_no_cardinality() { Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).build() ); String namespace = "test1"; + // Filter is chosen alphabetically because no cardinality is given Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); Exp exp = Exp.and( Exp.and( @@ -117,8 +114,8 @@ void binLogical_AND_3_all_indexes_no_cardinality() { Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", namespace, indexes, expected); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, + namespace, indexes); } @Test @@ -139,8 +136,8 @@ void binLogical_AND_3_all_indexes_partial_data() { Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", namespace, indexes, expected); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, + namespace, indexes); } @Test @@ -157,8 +154,8 @@ void binLogical_AND_3_two_indexes() { Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", namespace, indexes, expected); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, + namespace, indexes); } @Test @@ -166,8 +163,7 @@ void binLogical_OR_2_no_indexes() { Filter filter = null; Exp exp = Exp.or(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", expected); + parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", filter, exp); } @Test @@ -177,10 +173,12 @@ void binLogical_OR_2_all_indexes() { Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(1).build() ); String namespace = "test1"; - Filter filter = Filter.range("intBin2", 101, Long.MAX_VALUE); - Exp exp = null; - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", namespace, indexes, expected); + Filter filter = null; + Exp exp = Exp.or( + Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100)) + ); + parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", filter, exp, namespace, indexes); } @Test @@ -189,10 +187,12 @@ void binLogical_OR_2_one_index() { Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build() ); String namespace = "test1"; - Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); - Exp exp = null; - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", namespace, indexes, expected); + Filter filter = null; + Exp exp = Exp.or( + Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100)) + ); + parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", filter, exp, namespace, indexes); } @Test @@ -203,69 +203,58 @@ void binLogical_OR_3_all_indexes() { Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).binValuesRatio(0).build() ); String namespace = "test1"; - Filter filter = Filter.range("intBin2", 101, Long.MAX_VALUE); - Exp exp = null; - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100 or $.intBin3 > 100", namespace, indexes, expected); - } - - @Test - void binLogical_OR_3_all_indexes_no_cardinality() { - List indexes = List.of( - Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).build(), - Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).build(), - Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).build() - ); - String namespace = "test1"; - Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); - Exp exp = null; - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100 or $.intBin3 > 100", namespace, indexes, expected); - } - - @Test - void binLogical_OR_3_all_indexes_same_cardinality() { - List indexes = List.of( - Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(100).build(), - Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(100).build(), - Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).binValuesRatio(100).build() + Filter filter = null; + Exp exp = Exp.or( + Exp.or( + Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100)) + ), + Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); - String namespace = "test1"; - Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); - Exp exp = null; - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100 or $.intBin3 > 100", namespace, indexes, expected); + parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100 or $.intBin3 > 100", filter, exp, + namespace, indexes); } @Test - void binLogical_AND_OR_indexed() { + void binLogical_prioritizedAND_OR_indexed() { List indexes = List.of( Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).binValuesRatio(1).build() ); String namespace = "test1"; - Filter filter = Filter.range("intBin3", 101, Long.MAX_VALUE); - Exp exp = null; - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 or $.intBin3 > 100", namespace, indexes, expected); - parseExpressionAndCompare("($.intBin1 > 100 and $.intBin2 > 100) or $.intBin3 > 100", namespace, indexes, expected); + Filter filter = null; + Exp exp = Exp.or( + Exp.and( + Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100)) + ), + Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) + ); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 or $.intBin3 > 100", filter, exp, + namespace, indexes); + parseExpressionAndCompare("($.intBin1 > 100 and $.intBin2 > 100) or $.intBin3 > 100", filter, exp, + namespace, indexes); } - @Disabled // TODO: complex logical structures + @Disabled // TODO: complex logical structures, different grouping @Test - void binLogical_AND_indexed_OR() { + void binLogical_AND_prioritizedOR_indexed() { List indexes = List.of( Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), - Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(1).build(), + Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), Index.builder().namespace("test1").bin("intBin3").indexType(IndexType.NUMERIC).binValuesRatio(0).build() ); String namespace = "test1"; - Filter filter = Filter.range("intBin3", 101, Long.MAX_VALUE); - Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), - Exp.gt(Exp.intBin("intBin2"), Exp.val(100)));; - ParsedExpression expected = new ParsedExpression(exp, filter); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 or $.intBin3 > 100", namespace, indexes, expected); - parseExpressionAndCompare("($.intBin1 > 100 and $.intBin2 > 100) or $.intBin3 > 100", namespace, indexes, expected); + Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); + Exp exp = Exp.or( + Exp.and( + Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100)) + ), + Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) + ); + parseExpressionAndCompare("$.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 > 100)", filter, exp, + namespace, indexes); } } diff --git a/src/test/java/com/aerospike/dsl/util/TestUtils.java b/src/test/java/com/aerospike/dsl/util/TestUtils.java index e34a739..69a3471 100644 --- a/src/test/java/com/aerospike/dsl/util/TestUtils.java +++ b/src/test/java/com/aerospike/dsl/util/TestUtils.java @@ -4,8 +4,8 @@ import com.aerospike.client.exp.Expression; import com.aerospike.client.query.Filter; import com.aerospike.dsl.DSLParserImpl; +import com.aerospike.dsl.Index; import com.aerospike.dsl.ParsedExpression; -import com.aerospike.dsl.index.Index; import lombok.experimental.UtilityClass; import java.util.List; @@ -16,41 +16,46 @@ public class TestUtils { private final DSLParserImpl parser = new DSLParserImpl(); - - public static Expression parseFilterExp(String input) { - return parser.parseFilterExpression(input); + public static Expression parseExp(String input) { + return Exp.build(parser.parseExpression(input).getResultPair().getExp()); } - public static void parseFilterExpAndCompare(String input, Exp expected) { - Expression actualExpression = parser.parseFilterExpression(input); + public static void parseExpAndCompare(String input, Exp expected) { + Expression actualExpression = Exp.build(parser.parseExpression(input).getResultPair().getExp()); Expression expectedExpression = Exp.build(expected); assertEquals(actualExpression, expectedExpression); } public static Filter parseFilter(String input) { - return parser.parseFilter(input, null, null); + return parser.parseExpression(input).getResultPair().getFilter(); + } + + public static Filter parseFilter(String input, String namespace, List indexes) { + return parser.parseExpression(input, namespace, indexes).getResultPair().getFilter(); } public static void parseFilterAndCompare(String input, Filter expected) { - Filter actualFilter = parser.parseFilter(input, null, null); + Filter actualFilter = parseFilter(input); assertEquals(actualFilter, expected); } public static void parseFilterAndCompare(String input, String namespace, List indexes, Filter expected) { - Filter actualFilter = parser.parseFilter(input, namespace, indexes); + Filter actualFilter = parseFilter(input, namespace, indexes); assertEquals(actualFilter, expected); } - public static void parseExpressionAndCompare(String input, ParsedExpression expected) { - ParsedExpression actualExpression = parser.parseDslExpression(input, null, null); - assertEquals(actualExpression.getFilterExpression(), expected.getFilterExpression()); - assertEquals(actualExpression.getSIFilter(), expected.getSIFilter()); + public static void parseExpressionAndCompare(String input, Filter filter, Exp exp) { + ParsedExpression actualExpression = parser.parseExpression(input); + assertEquals(actualExpression.getResultPair().getFilter(), filter); + Exp actualExp = actualExpression.getResultPair().getExp(); + assertEquals(actualExp == null ? null : Exp.build(actualExp), exp == null ? null : Exp.build(exp)); } - public static void parseExpressionAndCompare(String input, String namespace, List indexes, - ParsedExpression expected) { - ParsedExpression actualExpression = parser.parseDslExpression(input, namespace, indexes); - assertEquals(actualExpression.getFilterExpression(), expected.getFilterExpression()); - assertEquals(actualExpression.getSIFilter(), expected.getSIFilter()); + public static void parseExpressionAndCompare(String input, Filter filter, Exp exp, + String namespace, List indexes) { + ParsedExpression actualExpression = parser.parseExpression(input, namespace, indexes); + assertEquals(actualExpression.getResultPair().getFilter(), filter); + Exp actualExp = actualExpression.getResultPair().getExp(); + assertEquals(actualExp == null ? null : Exp.build(actualExp), exp == null ? null : Exp.build(exp)); } } From 207180211f0cc994ace30b1ce49899f278ee7c82 Mon Sep 17 00:00:00 2001 From: agrgr Date: Mon, 28 Apr 2025 13:22:51 +0300 Subject: [PATCH 08/20] code format --- src/main/java/com/aerospike/dsl/ParsedExpression.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/aerospike/dsl/ParsedExpression.java b/src/main/java/com/aerospike/dsl/ParsedExpression.java index 582c102..ed72201 100644 --- a/src/main/java/com/aerospike/dsl/ParsedExpression.java +++ b/src/main/java/com/aerospike/dsl/ParsedExpression.java @@ -32,10 +32,13 @@ public ParsedExpression(AbstractPart resultingPart, String namespace, Map getResultPair() { - return DSLParserImpl.getResultPair(resultingPart, namespace, indexesMap); + if (resultPair == null) { + resultPair = DSLParserImpl.getResultPair(resultingPart, namespace, indexesMap); + } + return resultPair; } } From f9c7f0f705a54e26a2cd05cb88e6c1c59a57fc83 Mon Sep 17 00:00:00 2001 From: agrgr Date: Mon, 28 Apr 2025 22:42:39 +0300 Subject: [PATCH 09/20] change packages structure, update API to group namespace and indexes, rename Pair, add javadoc, update tests --- .../java/com/aerospike/dsl/DSLParser.java | 19 +- .../java/com/aerospike/dsl/DSLParserImpl.java | 37 +-- .../com/aerospike/dsl/IndexFilterInput.java | 26 ++ src/main/java/com/aerospike/dsl/Pair.java | 12 - .../com/aerospike/dsl/ParsedExpression.java | 38 ++- src/main/java/com/aerospike/dsl/Result.java | 24 ++ .../aerospike/dsl/model/ParsedOperand.java | 5 - .../dsl/model/simple/VariableOperand.java | 20 -- .../dsl/{model => part}/AbstractPart.java | 2 +- .../{model => part}/ExpressionContainer.java | 2 +- .../{model/cdt_part => part/cdt}/CdtPart.java | 8 +- .../cdt_part => part/cdt}/list/ListIndex.java | 4 +- .../cdt}/list/ListIndexRange.java | 4 +- .../cdt_part => part/cdt}/list/ListPart.java | 6 +- .../cdt_part => part/cdt}/list/ListRank.java | 4 +- .../cdt}/list/ListRankRange.java | 4 +- .../cdt}/list/ListRankRangeRelative.java | 4 +- .../cdt}/list/ListTypeDesignator.java | 8 +- .../cdt_part => part/cdt}/list/ListValue.java | 4 +- .../cdt}/list/ListValueList.java | 4 +- .../cdt}/list/ListValueRange.java | 4 +- .../cdt_part => part/cdt}/map/MapIndex.java | 4 +- .../cdt}/map/MapIndexRange.java | 4 +- .../cdt}/map/MapIndexRangeRelative.java | 4 +- .../cdt_part => part/cdt}/map/MapKey.java | 4 +- .../cdt_part => part/cdt}/map/MapKeyList.java | 4 +- .../cdt}/map/MapKeyRange.java | 4 +- .../cdt_part => part/cdt}/map/MapPart.java | 6 +- .../cdt_part => part/cdt}/map/MapRank.java | 4 +- .../cdt}/map/MapRankRange.java | 4 +- .../cdt}/map/MapRankRangeRelative.java | 4 +- .../cdt}/map/MapTypeDesignator.java | 6 +- .../cdt_part => part/cdt}/map/MapValue.java | 4 +- .../cdt}/map/MapValueList.java | 4 +- .../cdt}/map/MapValueRange.java | 4 +- .../controlstructure}/ExclusiveStructure.java | 6 +- .../controlstructure}/WhenStructure.java | 4 +- .../controlstructure}/WithStructure.java | 5 +- .../operand}/BooleanOperand.java | 7 +- .../simple => part/operand}/FloatOperand.java | 7 +- .../simple => part/operand}/IntOperand.java | 7 +- .../cdt => part/operand}/ListOperand.java | 7 +- .../cdt => part/operand}/MapOperand.java | 7 +- .../operand}/MetadataOperand.java | 3 +- .../dsl/part/operand/ParsedValueOperand.java | 9 + .../operand}/StringOperand.java | 7 +- .../dsl/part/operand/VariableOperand.java | 20 ++ .../operand}/WithOperand.java | 4 +- .../dsl/{model => part}/path/BasePath.java | 4 +- .../dsl/{model => part}/path/BinPart.java | 4 +- .../dsl/{model => part}/path/Path.java | 6 +- .../{model => part}/path/PathFunction.java | 4 +- .../aerospike/dsl/util/PathOperandUtils.java | 28 +- .../com/aerospike/dsl/util/TypeUtils.java | 6 +- .../visitor/ExpressionConditionVisitor.java | 56 ++-- .../aerospike/dsl/visitor/VisitorUtils.java | 63 +++-- .../dsl/filter/ArithmeticFiltersTests.java | 260 +++++++++--------- .../aerospike/dsl/filter/BinFiltersTests.java | 56 ++-- .../dsl/filter/ExplicitTypesFiltersTests.java | 31 ++- .../LogicalParsedExpressionTests.java | 34 ++- .../com/aerospike/dsl/util/TestUtils.java | 29 +- 61 files changed, 527 insertions(+), 446 deletions(-) create mode 100644 src/main/java/com/aerospike/dsl/IndexFilterInput.java delete mode 100644 src/main/java/com/aerospike/dsl/Pair.java create mode 100644 src/main/java/com/aerospike/dsl/Result.java delete mode 100644 src/main/java/com/aerospike/dsl/model/ParsedOperand.java delete mode 100644 src/main/java/com/aerospike/dsl/model/simple/VariableOperand.java rename src/main/java/com/aerospike/dsl/{model => part}/AbstractPart.java (96%) rename src/main/java/com/aerospike/dsl/{model => part}/ExpressionContainer.java (97%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/CdtPart.java (78%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/list/ListIndex.java (90%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/list/ListIndexRange.java (96%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/list/ListPart.java (89%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/list/ListRank.java (90%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/list/ListRankRange.java (96%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/list/ListRankRangeRelative.java (97%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/list/ListTypeDesignator.java (86%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/list/ListValue.java (94%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/list/ListValueList.java (96%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/list/ListValueRange.java (95%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapIndex.java (90%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapIndexRange.java (96%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapIndexRangeRelative.java (97%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapKey.java (93%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapKeyList.java (95%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapKeyRange.java (96%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapPart.java (90%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapRank.java (90%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapRankRange.java (96%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapRankRangeRelative.java (97%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapTypeDesignator.java (88%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapValue.java (94%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapValueList.java (96%) rename src/main/java/com/aerospike/dsl/{model/cdt_part => part/cdt}/map/MapValueRange.java (96%) rename src/main/java/com/aerospike/dsl/{model/ctrl_structure => part/controlstructure}/ExclusiveStructure.java (68%) rename src/main/java/com/aerospike/dsl/{model/ctrl_structure => part/controlstructure}/WhenStructure.java (75%) rename src/main/java/com/aerospike/dsl/{model/ctrl_structure => part/controlstructure}/WithStructure.java (66%) rename src/main/java/com/aerospike/dsl/{model/simple => part/operand}/BooleanOperand.java (70%) rename src/main/java/com/aerospike/dsl/{model/simple => part/operand}/FloatOperand.java (71%) rename src/main/java/com/aerospike/dsl/{model/simple => part/operand}/IntOperand.java (58%) rename src/main/java/com/aerospike/dsl/{model/cdt => part/operand}/ListOperand.java (60%) rename src/main/java/com/aerospike/dsl/{model/cdt => part/operand}/MapOperand.java (62%) rename src/main/java/com/aerospike/dsl/{model => part/operand}/MetadataOperand.java (96%) create mode 100644 src/main/java/com/aerospike/dsl/part/operand/ParsedValueOperand.java rename src/main/java/com/aerospike/dsl/{model/simple => part/operand}/StringOperand.java (80%) create mode 100644 src/main/java/com/aerospike/dsl/part/operand/VariableOperand.java rename src/main/java/com/aerospike/dsl/{model/ctrl_structure => part/operand}/WithOperand.java (86%) rename src/main/java/com/aerospike/dsl/{model => part}/path/BasePath.java (90%) rename src/main/java/com/aerospike/dsl/{model => part}/path/BinPart.java (84%) rename src/main/java/com/aerospike/dsl/{model => part}/path/Path.java (93%) rename src/main/java/com/aerospike/dsl/{model => part}/path/PathFunction.java (93%) diff --git a/src/main/java/com/aerospike/dsl/DSLParser.java b/src/main/java/com/aerospike/dsl/DSLParser.java index f1b28cd..06ecfb1 100644 --- a/src/main/java/com/aerospike/dsl/DSLParser.java +++ b/src/main/java/com/aerospike/dsl/DSLParser.java @@ -1,9 +1,8 @@ package com.aerospike.dsl; +import com.aerospike.client.query.Filter; import com.aerospike.dsl.exception.AerospikeDSLException; -import java.util.Collection; - /** * Contains API to convert dot separated String path into an Aerospike filter - * a functional language for applying predicates to bin data and record metadata. @@ -84,11 +83,11 @@ public interface DSLParser { * * * - * @param input String consisting of dot separated elements, typically bin name and optional context - * @return ParsedExpression object + * @param dslString String consisting of dot separated elements, typically bin name and optional context + * @return {@link ParsedExpression} object * @throws AerospikeDSLException in case of invalid syntax */ - ParsedExpression parseExpression(String input); + ParsedExpression parseExpression(String dslString); /** * Parse String DSL path into Aerospike filter Expression. @@ -156,11 +155,11 @@ public interface DSLParser { * * * - * @param input String consisting of dot separated elements, typically bin name and optional context - * @param namespace Namespace to use - * @param indexes Collection of {@link Index} objects that represent created secondary indexes - * @return ParsedExpression object + * @param dslString String consisting of dot separated elements, typically bin name and optional context + * @param indexFilterInput Class containing namespace and collection of {@link Index} objects that represent + * created secondary indexes. Required for creating {@link Filter}. Can be null + * @return {@link ParsedExpression} object * @throws AerospikeDSLException in case of or invalid syntax */ - ParsedExpression parseExpression(String input, String namespace, Collection indexes); + ParsedExpression parseExpression(String dslString, IndexFilterInput indexFilterInput); } diff --git a/src/main/java/com/aerospike/dsl/DSLParserImpl.java b/src/main/java/com/aerospike/dsl/DSLParserImpl.java index 4a796f5..2e7cbed 100644 --- a/src/main/java/com/aerospike/dsl/DSLParserImpl.java +++ b/src/main/java/com/aerospike/dsl/DSLParserImpl.java @@ -1,12 +1,9 @@ package com.aerospike.dsl; -import com.aerospike.client.exp.Exp; -import com.aerospike.client.query.Filter; import com.aerospike.dsl.annotation.Beta; import com.aerospike.dsl.exception.AerospikeDSLException; import com.aerospike.dsl.exception.NoApplicableFilterException; -import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.ExpressionContainer; +import com.aerospike.dsl.part.AbstractPart; import com.aerospike.dsl.visitor.ExpressionConditionVisitor; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; @@ -16,21 +13,20 @@ import java.util.HashMap; import java.util.Map; -import static com.aerospike.dsl.model.AbstractPart.PartType.EXPRESSION_CONTAINER; import static com.aerospike.dsl.visitor.VisitorUtils.*; public class DSLParserImpl implements DSLParser { @Beta - public ParsedExpression parseExpression(String input) { - ParseTree parseTree = getParseTree(input); - return getParsedExpression(parseTree, null, null); + public ParsedExpression parseExpression(String dslString) { + ParseTree parseTree = getParseTree(dslString); + return getParsedExpression(parseTree, null); } @Beta - public ParsedExpression parseExpression(String input, String namespace, Collection indexes) { + public ParsedExpression parseExpression(String input, IndexFilterInput indexFilterInput) { ParseTree parseTree = getParseTree(input); - return getParsedExpression(parseTree, namespace, indexes); + return getParsedExpression(parseTree, indexFilterInput); } private ParseTree getParseTree(String input) { @@ -39,10 +35,13 @@ private ParseTree getParseTree(String input) { return parser.parse(); } - private ParsedExpression getParsedExpression(ParseTree parseTree, String namespace, Collection indexes) { + private ParsedExpression getParsedExpression(ParseTree parseTree, IndexFilterInput indexFilterInput) { boolean hasFilterParsingError = false; AbstractPart resultingPart = null; Map indexesMap = new HashMap<>(); + String namespace = indexFilterInput == null ? null : indexFilterInput.getNamespace(); + Collection indexes = indexFilterInput == null ? null : indexFilterInput.getIndexes(); + if (indexes != null && !indexes.isEmpty()) { indexes.forEach(idx -> indexesMap.put(idx.getNamespace() + INDEX_NAME_SEPARATOR + idx.getBin(), idx)); } @@ -60,20 +59,4 @@ private ParsedExpression getParsedExpression(ParseTree parseTree, String namespa // Transfer the parsed tree along with namespace and indexes Map return new ParsedExpression(resultingPart, namespace, indexesMap); } - - public static Pair getResultPair(AbstractPart resultingPart, String namespace, - Map indexesMap) { - if (resultingPart != null) { - if (resultingPart.getPartType() == EXPRESSION_CONTAINER) { - AbstractPart result = - buildExpr((ExpressionContainer) resultingPart, namespace, indexesMap); - return new Pair<>(result.getFilter(), result.getExp()); - } else { - Filter filter = resultingPart.getFilter(); - Exp exp = resultingPart.getExp(); - return new Pair<>(filter, exp); - } - } - return new Pair<>(null, null); - } } diff --git a/src/main/java/com/aerospike/dsl/IndexFilterInput.java b/src/main/java/com/aerospike/dsl/IndexFilterInput.java new file mode 100644 index 0000000..bba7a63 --- /dev/null +++ b/src/main/java/com/aerospike/dsl/IndexFilterInput.java @@ -0,0 +1,26 @@ +package com.aerospike.dsl; + +import com.aerospike.client.query.Filter; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Collection; + +/** + * This class stores namespace and indexes required to build secondary index {@link Filter}. + */ +@AllArgsConstructor(staticName = "of") +@Getter +public class IndexFilterInput { + + /** + * Namespace to be used for creating {@link Filter}. Is matched with namespace of indexes + */ + private String namespace; + /** + * Collection of {@link Index} objects to be used for creating {@link Filter}. + * Namespace of indexes is matched with the given {@link #namespace}, bin name and index type are matched + * with bins in DSL String + */ + private Collection indexes; +} diff --git a/src/main/java/com/aerospike/dsl/Pair.java b/src/main/java/com/aerospike/dsl/Pair.java deleted file mode 100644 index 86b6748..0000000 --- a/src/main/java/com/aerospike/dsl/Pair.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.aerospike.dsl; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -@Getter -public class Pair { - - A filter; - B exp; -} diff --git a/src/main/java/com/aerospike/dsl/ParsedExpression.java b/src/main/java/com/aerospike/dsl/ParsedExpression.java index ed72201..d9487bb 100644 --- a/src/main/java/com/aerospike/dsl/ParsedExpression.java +++ b/src/main/java/com/aerospike/dsl/ParsedExpression.java @@ -5,11 +5,15 @@ 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 com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.part.ExpressionContainer; import lombok.Getter; import java.util.Map; +import static com.aerospike.dsl.part.AbstractPart.PartType.EXPRESSION_CONTAINER; +import static com.aerospike.dsl.visitor.VisitorUtils.*; + /** * A class to build and store the results of DSL expression parsing: secondary index {@link Filter} @@ -19,26 +23,40 @@ @Getter public class ParsedExpression { - private final AbstractPart resultingPart; + private final AbstractPart expressionTree; private final String namespace; private final Map indexesMap; - private Pair resultPair; + private Result result; - public ParsedExpression(AbstractPart resultingPart, String namespace, Map indexesMap) { - this.resultingPart = resultingPart; + public ParsedExpression(AbstractPart expressionTree, String namespace, Map indexesMap) { + this.expressionTree = expressionTree; this.namespace = namespace; this.indexesMap = indexesMap; } /** - * @return Pair of secondary index {@link Filter} and filter {@link Exp}. Each can be null in case of an invalid or + * @return Pair of secondary index {@link Filter} and filter {@link Exp}. Each can be null in case of invalid or * unsupported DSL string * @throws AerospikeDSLException If there was an error */ - public Pair getResultPair() { - if (resultPair == null) { - resultPair = DSLParserImpl.getResultPair(resultingPart, namespace, indexesMap); + public Result getResult() { + if (result == null) { + result = getResultPair(); + } + return result; + } + + public Result getResultPair() { + if (expressionTree != null) { + if (expressionTree.getPartType() == EXPRESSION_CONTAINER) { + AbstractPart result = buildExpr((ExpressionContainer) expressionTree, namespace, indexesMap); + return new Result(result.getFilter(), result.getExp()); + } else { + Filter filter = expressionTree.getFilter(); + Exp exp = expressionTree.getExp(); + return new Result(filter, exp); + } } - return resultPair; + return new Result(null, null); } } diff --git a/src/main/java/com/aerospike/dsl/Result.java b/src/main/java/com/aerospike/dsl/Result.java new file mode 100644 index 0000000..97a46c1 --- /dev/null +++ b/src/main/java/com/aerospike/dsl/Result.java @@ -0,0 +1,24 @@ +package com.aerospike.dsl; + +import com.aerospike.client.exp.Exp; +import com.aerospike.client.query.Filter; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * This class stores result of parsing DSL expression using {@link DSLParserImpl#parseExpression} + * in form of Java client's secondary index {@link Filter} and filter {@link Exp}. + */ +@AllArgsConstructor +@Getter +public class Result { + + /** + * Secondary index {@link Filter}. Can be null in case of invalid or unsupported DSL string + */ + Filter filter; + /** + * Filter {@link Exp}. Can be null in case of invalid or unsupported DSL string + */ + Exp exp; +} diff --git a/src/main/java/com/aerospike/dsl/model/ParsedOperand.java b/src/main/java/com/aerospike/dsl/model/ParsedOperand.java deleted file mode 100644 index 1b17960..0000000 --- a/src/main/java/com/aerospike/dsl/model/ParsedOperand.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.aerospike.dsl.model; - -public interface ParsedOperand { - Object getValue(); -} diff --git a/src/main/java/com/aerospike/dsl/model/simple/VariableOperand.java b/src/main/java/com/aerospike/dsl/model/simple/VariableOperand.java deleted file mode 100644 index f842f0f..0000000 --- a/src/main/java/com/aerospike/dsl/model/simple/VariableOperand.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.aerospike.dsl.model.simple; - -import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.AbstractPart; -import lombok.Getter; - -@Getter -public class VariableOperand extends AbstractPart { - - private final String name; - - public VariableOperand(String name) { - super(PartType.VARIABLE_OPERAND); - this.name = name; - } - - public Exp getExp() { - return Exp.var(name); - } -} diff --git a/src/main/java/com/aerospike/dsl/model/AbstractPart.java b/src/main/java/com/aerospike/dsl/part/AbstractPart.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/AbstractPart.java rename to src/main/java/com/aerospike/dsl/part/AbstractPart.java index fad7d71..37a0cd1 100644 --- a/src/main/java/com/aerospike/dsl/model/AbstractPart.java +++ b/src/main/java/com/aerospike/dsl/part/AbstractPart.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.part; import com.aerospike.client.exp.Exp; import com.aerospike.client.query.Filter; diff --git a/src/main/java/com/aerospike/dsl/model/ExpressionContainer.java b/src/main/java/com/aerospike/dsl/part/ExpressionContainer.java similarity index 97% rename from src/main/java/com/aerospike/dsl/model/ExpressionContainer.java rename to src/main/java/com/aerospike/dsl/part/ExpressionContainer.java index c0772d4..ce9e508 100644 --- a/src/main/java/com/aerospike/dsl/model/ExpressionContainer.java +++ b/src/main/java/com/aerospike/dsl/part/ExpressionContainer.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.part; import lombok.Getter; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/CdtPart.java b/src/main/java/com/aerospike/dsl/part/cdt/CdtPart.java similarity index 78% rename from src/main/java/com/aerospike/dsl/model/cdt_part/CdtPart.java rename to src/main/java/com/aerospike/dsl/part/cdt/CdtPart.java index a25f6fd..56373e1 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/CdtPart.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/CdtPart.java @@ -1,11 +1,11 @@ -package com.aerospike.dsl.model.cdt_part; +package com.aerospike.dsl.part.cdt; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.path.BasePath; -import com.aerospike.dsl.model.path.PathFunction; +import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.part.path.PathFunction; public abstract class CdtPart extends AbstractPart { diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListIndex.java b/src/main/java/com/aerospike/dsl/part/cdt/list/ListIndex.java similarity index 90% rename from src/main/java/com/aerospike/dsl/model/cdt_part/list/ListIndex.java rename to src/main/java/com/aerospike/dsl/part/cdt/list/ListIndex.java index c6d0e3a..c08431d 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListIndex.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/list/ListIndex.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.model.cdt_part.list; +package com.aerospike.dsl.part.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; public class ListIndex extends ListPart { private final int index; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListIndexRange.java b/src/main/java/com/aerospike/dsl/part/cdt/list/ListIndexRange.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt_part/list/ListIndexRange.java rename to src/main/java/com/aerospike/dsl/part/cdt/list/ListIndexRange.java index 2f9cc90..89216b7 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListIndexRange.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/list/ListIndexRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.list; +package com.aerospike.dsl.part.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListPart.java b/src/main/java/com/aerospike/dsl/part/cdt/list/ListPart.java similarity index 89% rename from src/main/java/com/aerospike/dsl/model/cdt_part/list/ListPart.java rename to src/main/java/com/aerospike/dsl/part/cdt/list/ListPart.java index bf342de..111c5d5 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListPart.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/list/ListPart.java @@ -1,9 +1,9 @@ -package com.aerospike.dsl.model.cdt_part.list; +package com.aerospike.dsl.part.cdt.list; import com.aerospike.client.cdt.ListReturnType; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.PathFunction; -import com.aerospike.dsl.model.cdt_part.CdtPart; +import com.aerospike.dsl.part.path.PathFunction; +import com.aerospike.dsl.part.cdt.CdtPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRank.java b/src/main/java/com/aerospike/dsl/part/cdt/list/ListRank.java similarity index 90% rename from src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRank.java rename to src/main/java/com/aerospike/dsl/part/cdt/list/ListRank.java index 6459fa5..dd5e7d3 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRank.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/list/ListRank.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.model.cdt_part.list; +package com.aerospike.dsl.part.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; public class ListRank extends ListPart { private final int rank; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRankRange.java b/src/main/java/com/aerospike/dsl/part/cdt/list/ListRankRange.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRankRange.java rename to src/main/java/com/aerospike/dsl/part/cdt/list/ListRankRange.java index 2e35909..60c0a19 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRankRange.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/list/ListRankRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.list; +package com.aerospike.dsl.part.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRankRangeRelative.java b/src/main/java/com/aerospike/dsl/part/cdt/list/ListRankRangeRelative.java similarity index 97% rename from src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRankRangeRelative.java rename to src/main/java/com/aerospike/dsl/part/cdt/list/ListRankRangeRelative.java index ddb3881..04b2508 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListRankRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/list/ListRankRangeRelative.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.list; +package com.aerospike.dsl.part.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListTypeDesignator.java b/src/main/java/com/aerospike/dsl/part/cdt/list/ListTypeDesignator.java similarity index 86% rename from src/main/java/com/aerospike/dsl/model/cdt_part/list/ListTypeDesignator.java rename to src/main/java/com/aerospike/dsl/part/cdt/list/ListTypeDesignator.java index 57562ab..8abfdfb 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListTypeDesignator.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/list/ListTypeDesignator.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.model.cdt_part.list; +package com.aerospike.dsl.part.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.path.BasePath; -import com.aerospike.dsl.model.cdt_part.CdtPart; +import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.part.cdt.CdtPart; import java.util.Collections; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValue.java b/src/main/java/com/aerospike/dsl/part/cdt/list/ListValue.java similarity index 94% rename from src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValue.java rename to src/main/java/com/aerospike/dsl/part/cdt/list/ListValue.java index c3d6434..7a4e43f 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValue.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/list/ListValue.java @@ -1,11 +1,11 @@ -package com.aerospike.dsl.model.cdt_part.list; +package com.aerospike.dsl.part.cdt.list; import com.aerospike.client.Value; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValueList.java b/src/main/java/com/aerospike/dsl/part/cdt/list/ListValueList.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValueList.java rename to src/main/java/com/aerospike/dsl/part/cdt/list/ListValueList.java index 702024e..8d57075 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValueList.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/list/ListValueList.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.list; +package com.aerospike.dsl.part.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValueRange.java b/src/main/java/com/aerospike/dsl/part/cdt/list/ListValueRange.java similarity index 95% rename from src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValueRange.java rename to src/main/java/com/aerospike/dsl/part/cdt/list/ListValueRange.java index 2ac5a7a..22eb93e 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/list/ListValueRange.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/list/ListValueRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.list; +package com.aerospike.dsl.part.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; public class ListValueRange extends ListPart { private final boolean inverted; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndex.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapIndex.java similarity index 90% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndex.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapIndex.java index 7ca6bf6..01f774f 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndex.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapIndex.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; public class MapIndex extends MapPart { private final int index; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndexRange.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapIndexRange.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndexRange.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapIndexRange.java index fc92829..e9d42db 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndexRange.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapIndexRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndexRangeRelative.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapIndexRangeRelative.java similarity index 97% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndexRangeRelative.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapIndexRangeRelative.java index 1dfc787..3337130 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapIndexRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapIndexRangeRelative.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKey.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapKey.java similarity index 93% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKey.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapKey.java index 53c379a..3a57f6f 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKey.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapKey.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.Value; import com.aerospike.client.cdt.CTX; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKeyList.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapKeyList.java similarity index 95% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKeyList.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapKeyList.java index 1072bcd..f6bf98e 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKeyList.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapKeyList.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKeyRange.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapKeyRange.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKeyRange.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapKeyRange.java index fe91368..f2e9fbe 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapKeyRange.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapKeyRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import java.util.Optional; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapPart.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapPart.java similarity index 90% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapPart.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapPart.java index 4fc1fba..f969800 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapPart.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapPart.java @@ -1,8 +1,8 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.cdt.MapReturnType; -import com.aerospike.dsl.model.path.PathFunction; -import com.aerospike.dsl.model.cdt_part.CdtPart; +import com.aerospike.dsl.part.path.PathFunction; +import com.aerospike.dsl.part.cdt.CdtPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRank.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapRank.java similarity index 90% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRank.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapRank.java index 4da997b..1e75c2d 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRank.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapRank.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; public class MapRank extends MapPart { private final int rank; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRankRange.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapRankRange.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRankRange.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapRankRange.java index e2a1c44..93d43a9 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRankRange.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapRankRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRankRangeRelative.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapRankRangeRelative.java similarity index 97% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRankRangeRelative.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapRankRangeRelative.java index c2d866e..7d4cea6 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapRankRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapRankRangeRelative.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapTypeDesignator.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapTypeDesignator.java similarity index 88% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapTypeDesignator.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapTypeDesignator.java index 4507c16..70c94d7 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapTypeDesignator.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapTypeDesignator.java @@ -1,9 +1,9 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.path.BasePath; -import com.aerospike.dsl.model.cdt_part.CdtPart; +import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.part.cdt.CdtPart; /** * Designates that the element to the left is a Map. diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValue.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapValue.java similarity index 94% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValue.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapValue.java index 3655291..26f1762 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValue.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapValue.java @@ -1,11 +1,11 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.Value; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValueList.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapValueList.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValueList.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapValueList.java index f061155..c7ce146 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValueList.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapValueList.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValueRange.java b/src/main/java/com/aerospike/dsl/part/cdt/map/MapValueRange.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValueRange.java rename to src/main/java/com/aerospike/dsl/part/cdt/map/MapValueRange.java index 38eac4b..1348b5d 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt_part/map/MapValueRange.java +++ b/src/main/java/com/aerospike/dsl/part/cdt/map/MapValueRange.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.model.cdt_part.map; +package com.aerospike.dsl.part.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; @@ -6,7 +6,7 @@ import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.model.path.BasePath; +import com.aerospike.dsl.part.path.BasePath; public class MapValueRange extends MapPart { private final boolean inverted; diff --git a/src/main/java/com/aerospike/dsl/model/ctrl_structure/ExclusiveStructure.java b/src/main/java/com/aerospike/dsl/part/controlstructure/ExclusiveStructure.java similarity index 68% rename from src/main/java/com/aerospike/dsl/model/ctrl_structure/ExclusiveStructure.java rename to src/main/java/com/aerospike/dsl/part/controlstructure/ExclusiveStructure.java index f030a45..95cdabe 100644 --- a/src/main/java/com/aerospike/dsl/model/ctrl_structure/ExclusiveStructure.java +++ b/src/main/java/com/aerospike/dsl/part/controlstructure/ExclusiveStructure.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.model.ctrl_structure; +package com.aerospike.dsl.part.controlstructure; -import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.ExpressionContainer; +import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.part.ExpressionContainer; import lombok.Getter; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/ctrl_structure/WhenStructure.java b/src/main/java/com/aerospike/dsl/part/controlstructure/WhenStructure.java similarity index 75% rename from src/main/java/com/aerospike/dsl/model/ctrl_structure/WhenStructure.java rename to src/main/java/com/aerospike/dsl/part/controlstructure/WhenStructure.java index 7ca507e..1e971d9 100644 --- a/src/main/java/com/aerospike/dsl/model/ctrl_structure/WhenStructure.java +++ b/src/main/java/com/aerospike/dsl/part/controlstructure/WhenStructure.java @@ -1,6 +1,6 @@ -package com.aerospike.dsl.model.ctrl_structure; +package com.aerospike.dsl.part.controlstructure; -import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.part.AbstractPart; import lombok.Getter; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/ctrl_structure/WithStructure.java b/src/main/java/com/aerospike/dsl/part/controlstructure/WithStructure.java similarity index 66% rename from src/main/java/com/aerospike/dsl/model/ctrl_structure/WithStructure.java rename to src/main/java/com/aerospike/dsl/part/controlstructure/WithStructure.java index 89d6fdb..892ef8a 100644 --- a/src/main/java/com/aerospike/dsl/model/ctrl_structure/WithStructure.java +++ b/src/main/java/com/aerospike/dsl/part/controlstructure/WithStructure.java @@ -1,6 +1,7 @@ -package com.aerospike.dsl.model.ctrl_structure; +package com.aerospike.dsl.part.controlstructure; -import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.part.operand.WithOperand; import lombok.Getter; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/simple/BooleanOperand.java b/src/main/java/com/aerospike/dsl/part/operand/BooleanOperand.java similarity index 70% rename from src/main/java/com/aerospike/dsl/model/simple/BooleanOperand.java rename to src/main/java/com/aerospike/dsl/part/operand/BooleanOperand.java index a629e36..0151aac 100644 --- a/src/main/java/com/aerospike/dsl/model/simple/BooleanOperand.java +++ b/src/main/java/com/aerospike/dsl/part/operand/BooleanOperand.java @@ -1,12 +1,11 @@ -package com.aerospike.dsl.model.simple; +package com.aerospike.dsl.part.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.ParsedOperand; +import com.aerospike.dsl.part.AbstractPart; import lombok.Getter; @Getter -public class BooleanOperand extends AbstractPart implements ParsedOperand { +public class BooleanOperand extends AbstractPart implements ParsedValueOperand { private final Boolean value; diff --git a/src/main/java/com/aerospike/dsl/model/simple/FloatOperand.java b/src/main/java/com/aerospike/dsl/part/operand/FloatOperand.java similarity index 71% rename from src/main/java/com/aerospike/dsl/model/simple/FloatOperand.java rename to src/main/java/com/aerospike/dsl/part/operand/FloatOperand.java index 0ad19cb..11b4e47 100644 --- a/src/main/java/com/aerospike/dsl/model/simple/FloatOperand.java +++ b/src/main/java/com/aerospike/dsl/part/operand/FloatOperand.java @@ -1,12 +1,11 @@ -package com.aerospike.dsl.model.simple; +package com.aerospike.dsl.part.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.ParsedOperand; +import com.aerospike.dsl.part.AbstractPart; import lombok.Getter; @Getter -public class FloatOperand extends AbstractPart implements ParsedOperand { +public class FloatOperand extends AbstractPart implements ParsedValueOperand { private final Double value; diff --git a/src/main/java/com/aerospike/dsl/model/simple/IntOperand.java b/src/main/java/com/aerospike/dsl/part/operand/IntOperand.java similarity index 58% rename from src/main/java/com/aerospike/dsl/model/simple/IntOperand.java rename to src/main/java/com/aerospike/dsl/part/operand/IntOperand.java index 1916d2a..5a9e654 100644 --- a/src/main/java/com/aerospike/dsl/model/simple/IntOperand.java +++ b/src/main/java/com/aerospike/dsl/part/operand/IntOperand.java @@ -1,12 +1,11 @@ -package com.aerospike.dsl.model.simple; +package com.aerospike.dsl.part.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.ParsedOperand; +import com.aerospike.dsl.part.AbstractPart; import lombok.Getter; @Getter -public class IntOperand extends AbstractPart implements ParsedOperand { +public class IntOperand extends AbstractPart implements ParsedValueOperand { private final Long value; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/ListOperand.java b/src/main/java/com/aerospike/dsl/part/operand/ListOperand.java similarity index 60% rename from src/main/java/com/aerospike/dsl/model/cdt/ListOperand.java rename to src/main/java/com/aerospike/dsl/part/operand/ListOperand.java index c86b38a..a6b89ed 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/ListOperand.java +++ b/src/main/java/com/aerospike/dsl/part/operand/ListOperand.java @@ -1,14 +1,13 @@ -package com.aerospike.dsl.model.cdt; +package com.aerospike.dsl.part.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.ParsedOperand; +import com.aerospike.dsl.part.AbstractPart; import lombok.Getter; import java.util.List; @Getter -public class ListOperand extends AbstractPart implements ParsedOperand { +public class ListOperand extends AbstractPart implements ParsedValueOperand { private final List value; diff --git a/src/main/java/com/aerospike/dsl/model/cdt/MapOperand.java b/src/main/java/com/aerospike/dsl/part/operand/MapOperand.java similarity index 62% rename from src/main/java/com/aerospike/dsl/model/cdt/MapOperand.java rename to src/main/java/com/aerospike/dsl/part/operand/MapOperand.java index 0b8b0f3..2304a74 100644 --- a/src/main/java/com/aerospike/dsl/model/cdt/MapOperand.java +++ b/src/main/java/com/aerospike/dsl/part/operand/MapOperand.java @@ -1,14 +1,13 @@ -package com.aerospike.dsl.model.cdt; +package com.aerospike.dsl.part.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.ParsedOperand; +import com.aerospike.dsl.part.AbstractPart; import lombok.Getter; import java.util.TreeMap; @Getter -public class MapOperand extends AbstractPart implements ParsedOperand { +public class MapOperand extends AbstractPart implements ParsedValueOperand { private final TreeMap value; diff --git a/src/main/java/com/aerospike/dsl/model/MetadataOperand.java b/src/main/java/com/aerospike/dsl/part/operand/MetadataOperand.java similarity index 96% rename from src/main/java/com/aerospike/dsl/model/MetadataOperand.java rename to src/main/java/com/aerospike/dsl/part/operand/MetadataOperand.java index adfe3f4..ada28ed 100644 --- a/src/main/java/com/aerospike/dsl/model/MetadataOperand.java +++ b/src/main/java/com/aerospike/dsl/part/operand/MetadataOperand.java @@ -1,6 +1,7 @@ -package com.aerospike.dsl.model; +package com.aerospike.dsl.part.operand; import com.aerospike.client.exp.Exp; +import com.aerospike.dsl.part.ExpressionContainer; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/part/operand/ParsedValueOperand.java b/src/main/java/com/aerospike/dsl/part/operand/ParsedValueOperand.java new file mode 100644 index 0000000..89b405f --- /dev/null +++ b/src/main/java/com/aerospike/dsl/part/operand/ParsedValueOperand.java @@ -0,0 +1,9 @@ +package com.aerospike.dsl.part.operand; + +/** + * This interface provides an abstraction for an operand that returns a single value to be used for constructing + * the resulting filter (e.g., a String for StringOperand or a list of objects for ListOperand) + */ +public interface ParsedValueOperand { + Object getValue(); +} diff --git a/src/main/java/com/aerospike/dsl/model/simple/StringOperand.java b/src/main/java/com/aerospike/dsl/part/operand/StringOperand.java similarity index 80% rename from src/main/java/com/aerospike/dsl/model/simple/StringOperand.java rename to src/main/java/com/aerospike/dsl/part/operand/StringOperand.java index bbea02f..aa6eb76 100644 --- a/src/main/java/com/aerospike/dsl/model/simple/StringOperand.java +++ b/src/main/java/com/aerospike/dsl/part/operand/StringOperand.java @@ -1,15 +1,14 @@ -package com.aerospike.dsl.model.simple; +package com.aerospike.dsl.part.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.ParsedOperand; +import com.aerospike.dsl.part.AbstractPart; import lombok.Getter; import lombok.Setter; import java.util.Base64; @Getter -public class StringOperand extends AbstractPart implements ParsedOperand { +public class StringOperand extends AbstractPart implements ParsedValueOperand { private final String value; @Setter diff --git a/src/main/java/com/aerospike/dsl/part/operand/VariableOperand.java b/src/main/java/com/aerospike/dsl/part/operand/VariableOperand.java new file mode 100644 index 0000000..f046b3f --- /dev/null +++ b/src/main/java/com/aerospike/dsl/part/operand/VariableOperand.java @@ -0,0 +1,20 @@ +package com.aerospike.dsl.part.operand; + +import com.aerospike.client.exp.Exp; +import com.aerospike.dsl.part.AbstractPart; +import lombok.Getter; + +@Getter +public class VariableOperand extends AbstractPart implements ParsedValueOperand { + + private final String value; + + public VariableOperand(String name) { + super(PartType.VARIABLE_OPERAND); + this.value = name; + } + + public Exp getExp() { + return Exp.var(value); + } +} diff --git a/src/main/java/com/aerospike/dsl/model/ctrl_structure/WithOperand.java b/src/main/java/com/aerospike/dsl/part/operand/WithOperand.java similarity index 86% rename from src/main/java/com/aerospike/dsl/model/ctrl_structure/WithOperand.java rename to src/main/java/com/aerospike/dsl/part/operand/WithOperand.java index ef06fba..44b05ef 100644 --- a/src/main/java/com/aerospike/dsl/model/ctrl_structure/WithOperand.java +++ b/src/main/java/com/aerospike/dsl/part/operand/WithOperand.java @@ -1,6 +1,6 @@ -package com.aerospike.dsl.model.ctrl_structure; +package com.aerospike.dsl.part.operand; -import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.part.AbstractPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/model/path/BasePath.java b/src/main/java/com/aerospike/dsl/part/path/BasePath.java similarity index 90% rename from src/main/java/com/aerospike/dsl/model/path/BasePath.java rename to src/main/java/com/aerospike/dsl/part/path/BasePath.java index 45894a2..13250f9 100644 --- a/src/main/java/com/aerospike/dsl/model/path/BasePath.java +++ b/src/main/java/com/aerospike/dsl/part/path/BasePath.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.model.path; +package com.aerospike.dsl.part.path; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.part.AbstractPart; import lombok.Getter; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/path/BinPart.java b/src/main/java/com/aerospike/dsl/part/path/BinPart.java similarity index 84% rename from src/main/java/com/aerospike/dsl/model/path/BinPart.java rename to src/main/java/com/aerospike/dsl/part/path/BinPart.java index 2a442f9..48d2dae 100644 --- a/src/main/java/com/aerospike/dsl/model/path/BinPart.java +++ b/src/main/java/com/aerospike/dsl/part/path/BinPart.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.model.path; +package com.aerospike.dsl.part.path; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.ExpressionContainer; +import com.aerospike.dsl.part.ExpressionContainer; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/model/path/Path.java b/src/main/java/com/aerospike/dsl/part/path/Path.java similarity index 93% rename from src/main/java/com/aerospike/dsl/model/path/Path.java rename to src/main/java/com/aerospike/dsl/part/path/Path.java index 9bd819a..50be659 100644 --- a/src/main/java/com/aerospike/dsl/model/path/Path.java +++ b/src/main/java/com/aerospike/dsl/part/path/Path.java @@ -1,8 +1,8 @@ -package com.aerospike.dsl.model.path; +package com.aerospike.dsl.part.path; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.cdt_part.CdtPart; +import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.part.cdt.CdtPart; import lombok.Getter; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/model/path/PathFunction.java b/src/main/java/com/aerospike/dsl/part/path/PathFunction.java similarity index 93% rename from src/main/java/com/aerospike/dsl/model/path/PathFunction.java rename to src/main/java/com/aerospike/dsl/part/path/PathFunction.java index 263d29b..f0d8260 100644 --- a/src/main/java/com/aerospike/dsl/model/path/PathFunction.java +++ b/src/main/java/com/aerospike/dsl/part/path/PathFunction.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.model.path; +package com.aerospike.dsl.part.path; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.AbstractPart; +import com.aerospike.dsl.part.AbstractPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/util/PathOperandUtils.java b/src/main/java/com/aerospike/dsl/util/PathOperandUtils.java index 07a2913..d0290d0 100644 --- a/src/main/java/com/aerospike/dsl/util/PathOperandUtils.java +++ b/src/main/java/com/aerospike/dsl/util/PathOperandUtils.java @@ -4,26 +4,26 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.client.exp.MapExp; -import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.path.BasePath; -import com.aerospike.dsl.model.path.BinPart; -import com.aerospike.dsl.model.path.PathFunction; -import com.aerospike.dsl.model.cdt_part.CdtPart; -import com.aerospike.dsl.model.cdt_part.list.ListPart; -import com.aerospike.dsl.model.cdt_part.list.ListTypeDesignator; -import com.aerospike.dsl.model.cdt_part.map.MapPart; -import com.aerospike.dsl.model.cdt_part.map.MapTypeDesignator; +import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.part.path.BinPart; +import com.aerospike.dsl.part.path.PathFunction; +import com.aerospike.dsl.part.cdt.CdtPart; +import com.aerospike.dsl.part.cdt.list.ListPart; +import com.aerospike.dsl.part.cdt.list.ListTypeDesignator; +import com.aerospike.dsl.part.cdt.map.MapPart; +import com.aerospike.dsl.part.cdt.map.MapTypeDesignator; import lombok.experimental.UtilityClass; import java.util.ArrayList; import java.util.List; import java.util.function.UnaryOperator; -import static com.aerospike.dsl.model.AbstractPart.PartType.LIST_PART; -import static com.aerospike.dsl.model.AbstractPart.PartType.MAP_PART; -import static com.aerospike.dsl.model.path.PathFunction.PathFunctionType.*; -import static com.aerospike.dsl.model.cdt_part.list.ListPart.ListPartType.*; -import static com.aerospike.dsl.model.cdt_part.map.MapPart.MapPartType.MAP_TYPE_DESIGNATOR; +import static com.aerospike.dsl.part.AbstractPart.PartType.LIST_PART; +import static com.aerospike.dsl.part.AbstractPart.PartType.MAP_PART; +import static com.aerospike.dsl.part.path.PathFunction.PathFunctionType.*; +import static com.aerospike.dsl.part.cdt.list.ListPart.ListPartType.*; +import static com.aerospike.dsl.part.cdt.map.MapPart.MapPartType.MAP_TYPE_DESIGNATOR; @UtilityClass public class PathOperandUtils { diff --git a/src/main/java/com/aerospike/dsl/util/TypeUtils.java b/src/main/java/com/aerospike/dsl/util/TypeUtils.java index f66c18c..32a2c38 100644 --- a/src/main/java/com/aerospike/dsl/util/TypeUtils.java +++ b/src/main/java/com/aerospike/dsl/util/TypeUtils.java @@ -1,9 +1,9 @@ package com.aerospike.dsl.util; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.model.AbstractPart; -import com.aerospike.dsl.model.cdt_part.map.MapPart; -import com.aerospike.dsl.model.cdt_part.map.MapTypeDesignator; +import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.part.cdt.map.MapPart; +import com.aerospike.dsl.part.cdt.map.MapTypeDesignator; import lombok.experimental.UtilityClass; @UtilityClass diff --git a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java index 6d84eb1..c6850a8 100644 --- a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java +++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java @@ -4,33 +4,25 @@ 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_part.list.ListIndex; -import com.aerospike.dsl.model.cdt_part.list.ListIndexRange; -import com.aerospike.dsl.model.cdt_part.list.ListRank; -import com.aerospike.dsl.model.cdt_part.list.ListRankRange; -import com.aerospike.dsl.model.cdt_part.list.ListRankRangeRelative; -import com.aerospike.dsl.model.cdt_part.list.ListTypeDesignator; -import com.aerospike.dsl.model.cdt_part.list.ListValue; -import com.aerospike.dsl.model.cdt_part.list.ListValueList; -import com.aerospike.dsl.model.cdt_part.list.ListValueRange; -import com.aerospike.dsl.model.cdt_part.map.*; -import com.aerospike.dsl.model.cdt.ListOperand; -import com.aerospike.dsl.model.cdt.MapOperand; -import com.aerospike.dsl.model.ctrl_structure.ExclusiveStructure; -import com.aerospike.dsl.model.ctrl_structure.WhenStructure; -import com.aerospike.dsl.model.ctrl_structure.WithOperand; -import com.aerospike.dsl.model.ctrl_structure.WithStructure; -import com.aerospike.dsl.model.path.BasePath; -import com.aerospike.dsl.model.path.BinPart; -import com.aerospike.dsl.model.MetadataOperand; -import com.aerospike.dsl.model.path.Path; -import com.aerospike.dsl.model.path.PathFunction; -import com.aerospike.dsl.model.simple.BooleanOperand; -import com.aerospike.dsl.model.simple.FloatOperand; -import com.aerospike.dsl.model.simple.IntOperand; -import com.aerospike.dsl.model.simple.StringOperand; -import com.aerospike.dsl.model.simple.VariableOperand; +import com.aerospike.dsl.part.*; +import com.aerospike.dsl.part.cdt.list.ListIndex; +import com.aerospike.dsl.part.cdt.list.ListIndexRange; +import com.aerospike.dsl.part.cdt.list.ListRank; +import com.aerospike.dsl.part.cdt.list.ListRankRange; +import com.aerospike.dsl.part.cdt.list.ListRankRangeRelative; +import com.aerospike.dsl.part.cdt.list.ListTypeDesignator; +import com.aerospike.dsl.part.cdt.list.ListValue; +import com.aerospike.dsl.part.cdt.list.ListValueList; +import com.aerospike.dsl.part.cdt.list.ListValueRange; +import com.aerospike.dsl.part.cdt.map.*; +import com.aerospike.dsl.part.operand.*; +import com.aerospike.dsl.part.controlstructure.ExclusiveStructure; +import com.aerospike.dsl.part.controlstructure.WhenStructure; +import com.aerospike.dsl.part.controlstructure.WithStructure; +import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.part.path.BinPart; +import com.aerospike.dsl.part.path.Path; +import com.aerospike.dsl.part.path.PathFunction; import com.aerospike.dsl.util.TypeUtils; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.RuleNode; @@ -312,7 +304,7 @@ public AbstractPart visitListConstant(ConditionParser.ListConstantContext ctx) { public ListOperand readChildrenIntoListOperand(RuleNode listNode) { int size = listNode.getChildCount(); - List list = new ArrayList<>(); + List values = new ArrayList<>(); for (int i = 0; i < size; i++) { ParseTree child = listNode.getChild(i); if (!shouldVisitListElement(i, size, child)) { @@ -325,13 +317,13 @@ public ListOperand readChildrenIntoListOperand(RuleNode listNode) { } try { - list.add(((ParsedOperand) operand).getValue()); + values.add(((ParsedValueOperand) operand).getValue()); } catch (ClassCastException e) { throw new AerospikeDSLException("List constant contains elements of different type"); } } - return new ListOperand(list); + return new ListOperand(values); } @Override @@ -343,8 +335,8 @@ public TreeMap getOrderedMapPair(ParseTree ctx) { if (ctx.getChild(0) == null || ctx.getChild(2) == null) { throw new AerospikeDSLException("Unable to parse map operand"); } - Object key = ((ParsedOperand) visit(ctx.getChild(0))).getValue(); - Object value = ((ParsedOperand) visit(ctx.getChild(2))).getValue(); + Object key = ((ParsedValueOperand) visit(ctx.getChild(0))).getValue(); + Object value = ((ParsedValueOperand) visit(ctx.getChild(2))).getValue(); TreeMap map = new TreeMap<>(); map.put(key, value); return map; diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index e94e9da..3f6b5d1 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -7,15 +7,15 @@ import com.aerospike.dsl.exception.AerospikeDSLException; import com.aerospike.dsl.exception.NoApplicableFilterException; import com.aerospike.dsl.Index; -import com.aerospike.dsl.model.*; -import com.aerospike.dsl.model.path.BinPart; -import com.aerospike.dsl.model.ctrl_structure.ExclusiveStructure; -import com.aerospike.dsl.model.simple.IntOperand; -import com.aerospike.dsl.model.MetadataOperand; -import com.aerospike.dsl.model.simple.StringOperand; -import com.aerospike.dsl.model.ctrl_structure.WhenStructure; -import com.aerospike.dsl.model.ctrl_structure.WithOperand; -import com.aerospike.dsl.model.ctrl_structure.WithStructure; +import com.aerospike.dsl.part.*; +import com.aerospike.dsl.part.path.BinPart; +import com.aerospike.dsl.part.controlstructure.ExclusiveStructure; +import com.aerospike.dsl.part.operand.IntOperand; +import com.aerospike.dsl.part.operand.MetadataOperand; +import com.aerospike.dsl.part.operand.StringOperand; +import com.aerospike.dsl.part.controlstructure.WhenStructure; +import com.aerospike.dsl.part.operand.WithOperand; +import com.aerospike.dsl.part.controlstructure.WithStructure; import lombok.experimental.UtilityClass; import org.antlr.v4.runtime.misc.Pair; import org.antlr.v4.runtime.tree.ParseTree; @@ -32,8 +32,8 @@ import java.util.function.UnaryOperator; import java.util.stream.Stream; -import static com.aerospike.dsl.model.AbstractPart.PartType.*; -import static com.aerospike.dsl.model.ExpressionContainer.ExprPartsOperation.*; +import static com.aerospike.dsl.part.AbstractPart.PartType.*; +import static com.aerospike.dsl.part.ExpressionContainer.ExprPartsOperation.*; import static com.aerospike.dsl.util.ValidationUtils.validateComparableTypes; import static com.aerospike.dsl.visitor.VisitorUtils.ArithmeticTermType.*; @@ -222,7 +222,8 @@ static Exp getExpLeftBinTypeComparison(BinPart left, AbstractPart right, BinaryO leftExp = Exp.bin(left.getBinName(), binType); yield operator.apply(leftExp, right.getExp()); } - case EXPRESSION_CONTAINER, PATH_OPERAND -> operator.apply(leftExp, right.getExp()); // Can't validate with Expr on one side + case EXPRESSION_CONTAINER, PATH_OPERAND -> + operator.apply(leftExp, right.getExp()); // Can't validate with Expr on one side case BIN_PART -> { // Left and right are both bin parts // Validate types if possible @@ -695,7 +696,7 @@ private FilterOperationType invertType(FilterOperationType type) { }; } - public AbstractPart buildExpr(ExpressionContainer expr, String namespace, Map indexes) { + public static AbstractPart buildExpr(ExpressionContainer expr, String namespace, Map indexes) { Exp exp; Filter sIndexFilter = null; try { @@ -774,24 +775,24 @@ private static Filter getSIFilter(ExpressionContainer expr, String namespace, Ma } private static ExpressionContainer chooseExprForFilter(List exprs, String namespace, Map indexes) { - if (exprs.size() == 1) return exprs.get(0); - if (exprs.size() > 1 && (indexes == null || indexes.isEmpty())) return null; + if (indexes == null || indexes.isEmpty()) return null; Map> exprsPerCardinality = new HashMap<>(); for (ExpressionContainer expr : exprs) { BinPart binPart = getBinPart(expr); - Index index = indexes.get(namespace + INDEX_NAME_SEPARATOR + binPart.getBinName()); - if (index == null) continue; - if (expTypeToIndexType.get(binPart.getExpType()) == index.getIndexType()) { - List exprsList = exprsPerCardinality.get(index.getBinValuesRatio()); - if (exprsList != null) { - exprsList.add(expr); - } else { - exprsList = new ArrayList<>(); - exprsList.add(expr); - } - exprsPerCardinality.put(index.getBinValuesRatio(), exprsList); + if (binPart == null) return null; // no bin found + Index index = indexes.get(namespace + INDEX_NAME_SEPARATOR + binPart.getBinName()); + if (index == null) continue; + if (expTypeToIndexType.get(binPart.getExpType()) == index.getIndexType()) { + List exprsList = exprsPerCardinality.get(index.getBinValuesRatio()); + if (exprsList != null) { + exprsList.add(expr); + } else { + exprsList = new ArrayList<>(); + exprsList.add(expr); } + exprsPerCardinality.put(index.getBinValuesRatio(), exprsList); + } } // Find the entry with the largest key and put it in a new Map @@ -826,8 +827,14 @@ private static BinPart getBinPart(ExpressionContainer expr) { } } } else { - if (expr.getLeft() != null && expr.getLeft().getPartType() == BIN_PART) { - return (BinPart) expr.getLeft(); + if (expr.getLeft() != null) { + if (expr.getLeft().getPartType() == BIN_PART) { + return (BinPart) expr.getLeft(); + } + if (expr.getLeft().getPartType() == EXPRESSION_CONTAINER) { + result = getBinPart((ExpressionContainer) expr.getLeft()); + if (result != null) return result; + } } if (expr.getRight() != null && expr.getRight().getPartType() == BIN_PART) { diff --git a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java index 9082ae9..88ede8d 100644 --- a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java @@ -1,9 +1,15 @@ package com.aerospike.dsl.filter; import com.aerospike.client.query.Filter; +import com.aerospike.client.query.IndexType; +import com.aerospike.dsl.Index; +import com.aerospike.dsl.IndexFilterInput; import com.aerospike.dsl.exception.AerospikeDSLException; import org.junit.jupiter.api.Test; +import java.util.Collection; +import java.util.List; + import static com.aerospike.dsl.util.TestUtils.parseFilter; import static com.aerospike.dsl.util.TestUtils.parseFilterAndCompare; import static org.assertj.core.api.Assertions.assertThat; @@ -11,26 +17,34 @@ public class ArithmeticFiltersTests { + String NAMESPACE = "test1"; + Collection INDEXES = List.of( + Index.builder().namespace("test1").bin("apples").indexType(IndexType.NUMERIC).binValuesRatio(1).build(), + Index.builder().namespace("test1").bin("bananas").indexType(IndexType.NUMERIC).binValuesRatio(1).build() + ); + IndexFilterInput INDEX_FILTER_INPUT = IndexFilterInput.of(NAMESPACE, INDEXES); + @Test void add() { - assertThat(parseFilter("($.apples + $.bananas) > 10")).isNull(); // not supported by secondary index filter + // not supported by secondary index filter + assertThat(parseFilter("($.apples + $.bananas) > 10", INDEX_FILTER_INPUT)).isNull(); - parseFilterAndCompare("($.apples + 5) > 10", + parseFilterAndCompare("($.apples + 5) > 10", INDEX_FILTER_INPUT, Filter.range("apples", 10 - 5 + 1, Long.MAX_VALUE)); - parseFilterAndCompare("($.apples + 5) >= 10", + parseFilterAndCompare("($.apples + 5) >= 10", INDEX_FILTER_INPUT, Filter.range("apples", 10 - 5, Long.MAX_VALUE)); - parseFilterAndCompare("($.apples + 5) < 10", + parseFilterAndCompare("($.apples + 5) < 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 10 - 5 - 1)); - parseFilterAndCompare("($.apples + 5) <= 10", + parseFilterAndCompare("($.apples + 5) <= 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 10 - 5)); - parseFilterAndCompare("(9 + $.bananas) > 10", + parseFilterAndCompare("(9 + $.bananas) > 10", INDEX_FILTER_INPUT, Filter.range("bananas", 10 - 9 + 1, Long.MAX_VALUE)); - parseFilterAndCompare("(9 + $.bananas) >= 10", + parseFilterAndCompare("(9 + $.bananas) >= 10", INDEX_FILTER_INPUT, Filter.range("bananas", 10 - 9, Long.MAX_VALUE)); - parseFilterAndCompare("(9 + $.bananas) < 10", + parseFilterAndCompare("(9 + $.bananas) < 10", INDEX_FILTER_INPUT, Filter.range("bananas", Long.MIN_VALUE, 10 - 9 - 1)); - parseFilterAndCompare("(9 + $.bananas) <= 10", + parseFilterAndCompare("(9 + $.bananas) <= 10", INDEX_FILTER_INPUT, Filter.range("bananas", Long.MIN_VALUE, 10 - 9)); assertThat(parseFilter("(5.2 + $.bananas) > 10.2")).isNull(); // not supported by secondary index filter @@ -41,33 +55,33 @@ void add() { @Test void sub() { - assertThat(parseFilter("($.apples - $.bananas) > 10")).isNull(); // not supported by secondary index filter + assertThat(parseFilter("($.apples - $.bananas) > 10", INDEX_FILTER_INPUT)).isNull(); // not supported by secondary index filter - parseFilterAndCompare("($.apples - 5) > 10", + parseFilterAndCompare("($.apples - 5) > 10", INDEX_FILTER_INPUT, Filter.range("apples", 10 + 5 + 1, Long.MAX_VALUE)); - parseFilterAndCompare("($.apples - 5) >= 10", + parseFilterAndCompare("($.apples - 5) >= 10", INDEX_FILTER_INPUT, Filter.range("apples", 10 + 5, Long.MAX_VALUE)); - parseFilterAndCompare("($.apples - 5) < 10", + parseFilterAndCompare("($.apples - 5) < 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 10 + 5 - 1)); - parseFilterAndCompare("($.apples - 5) <= 10", + parseFilterAndCompare("($.apples - 5) <= 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 10 + 5)); - parseFilterAndCompare("($.apples - 5) > -10", + parseFilterAndCompare("($.apples - 5) > -10", INDEX_FILTER_INPUT, Filter.range("apples", -10 + 5 + 1, Long.MAX_VALUE)); - parseFilterAndCompare("($.apples - 5) >= -10", + parseFilterAndCompare("($.apples - 5) >= -10", INDEX_FILTER_INPUT, Filter.range("apples", -10 + 5, Long.MAX_VALUE)); - parseFilterAndCompare("($.apples - 5) < -10", + parseFilterAndCompare("($.apples - 5) < -10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, -10 + 5 - 1)); - parseFilterAndCompare("($.apples - 5) <= -10", + parseFilterAndCompare("($.apples - 5) <= -10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, -10 + 5)); - parseFilterAndCompare("(9 - $.bananas) > 10", + parseFilterAndCompare("(9 - $.bananas) > 10", INDEX_FILTER_INPUT, Filter.range("bananas", Long.MIN_VALUE, 9 - 10 - 1)); - parseFilterAndCompare("(9 - $.bananas) >= 10", + parseFilterAndCompare("(9 - $.bananas) >= 10", INDEX_FILTER_INPUT, Filter.range("bananas", Long.MIN_VALUE, 9 - 10)); - parseFilterAndCompare("(9 - $.bananas) < 10", + parseFilterAndCompare("(9 - $.bananas) < 10", INDEX_FILTER_INPUT, Filter.range("bananas", 9 - 10 + 1, Long.MAX_VALUE)); - parseFilterAndCompare("(9 - $.bananas) <= 10", + parseFilterAndCompare("(9 - $.bananas) <= 10", INDEX_FILTER_INPUT, Filter.range("bananas", 9 - 10, Long.MAX_VALUE)); assertThat(parseFilter("($.apples - $.bananas) > 10")).isNull(); // not supported by secondary index filter @@ -78,38 +92,38 @@ void sub() { @Test void mul() { - assertThat(parseFilter("($.apples * $.bananas) > 10")).isNull(); // not supported by secondary index filter + assertThat(parseFilter("($.apples * $.bananas) > 10", INDEX_FILTER_INPUT)).isNull(); // not supported by secondary index filter - parseFilterAndCompare("($.apples * 5) > 10", + parseFilterAndCompare("($.apples * 5) > 10", INDEX_FILTER_INPUT, Filter.range("apples", 10 / 5 + 1, Long.MAX_VALUE)); - parseFilterAndCompare("($.apples * 5) >= 10", + parseFilterAndCompare("($.apples * 5) >= 10", INDEX_FILTER_INPUT, Filter.range("apples", 10 / 5, Long.MAX_VALUE)); - parseFilterAndCompare("($.apples * 5) < 10", + parseFilterAndCompare("($.apples * 5) < 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 10 / 5 - 1)); - parseFilterAndCompare("($.apples * 5) <= 10", + parseFilterAndCompare("($.apples * 5) <= 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 10 / 5)); - parseFilterAndCompare("(9 * $.bananas) > 10", + parseFilterAndCompare("(9 * $.bananas) > 10", INDEX_FILTER_INPUT, Filter.range("bananas", 10 / 9 + 1, Long.MAX_VALUE)); - parseFilterAndCompare("(9 * $.bananas) >= 10", + parseFilterAndCompare("(9 * $.bananas) >= 10", INDEX_FILTER_INPUT, Filter.range("bananas", 10 / 9, Long.MAX_VALUE)); - parseFilterAndCompare("(9 * $.bananas) < 10", + parseFilterAndCompare("(9 * $.bananas) < 10", INDEX_FILTER_INPUT, Filter.range("bananas", Long.MIN_VALUE, 10 / 9)); - parseFilterAndCompare("(9 * $.bananas) <= 10", + parseFilterAndCompare("(9 * $.bananas) <= 10", INDEX_FILTER_INPUT, Filter.range("bananas", Long.MIN_VALUE, 10 / 9)); - parseFilterAndCompare("($.apples * -5) > 10", + parseFilterAndCompare("($.apples * -5) > 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 10 / -5 - 1)); - parseFilterAndCompare("($.apples * -5) >= 10", + parseFilterAndCompare("($.apples * -5) >= 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 10 / -5)); - parseFilterAndCompare("($.apples * -5) < 10", + parseFilterAndCompare("($.apples * -5) < 10", INDEX_FILTER_INPUT, Filter.range("apples", 10 / -5 + 1, Long.MAX_VALUE)); - parseFilterAndCompare("($.apples * -5) <= 10", + parseFilterAndCompare("($.apples * -5) <= 10", INDEX_FILTER_INPUT, Filter.range("apples", 10 / -5, Long.MAX_VALUE)); - assertThat(parseFilter("(0 * $.bananas) > 10")).isNull(); // Cannot divide by zero + assertThat(parseFilter("(0 * $.bananas) > 10", INDEX_FILTER_INPUT)).isNull(); // Cannot divide by zero - parseFilterAndCompare("(9 * $.bananas) > 0", + parseFilterAndCompare("(9 * $.bananas) > 0", INDEX_FILTER_INPUT, Filter.range("bananas", 0 / 9 + 1, Long.MAX_VALUE)); assertThatThrownBy(() -> parseFilter("($.apples * $.bananas - 5) > 10")) @@ -119,187 +133,187 @@ void mul() { @Test void div_twoBins() { - assertThat(parseFilter("($.apples / $.bananas) <= 10")).isNull(); // not supported by secondary index filter + assertThat(parseFilter("($.apples / $.bananas) <= 10", INDEX_FILTER_INPUT)).isNull(); // not supported by secondary index filter } @Test void div_binIsDivided_leftNumberIsLarger() { - parseFilterAndCompare("($.apples / 50) > 10", + parseFilterAndCompare("($.apples / 50) > 10", INDEX_FILTER_INPUT, Filter.range("apples", 50 * 10 + 1, Long.MAX_VALUE)); // [501, 2^63 - 1] - parseFilterAndCompare("($.apples / 50) >= 10", + parseFilterAndCompare("($.apples / 50) >= 10", INDEX_FILTER_INPUT, Filter.range("apples", 50 * 10, Long.MAX_VALUE)); // [500, 2^63 - 1] - parseFilterAndCompare("($.apples / 50) < 10", + parseFilterAndCompare("($.apples / 50) < 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 50 * 10 - 1)); // [-2^63, 499] - parseFilterAndCompare("($.apples / 50) <= 10", + parseFilterAndCompare("($.apples / 50) <= 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 50 * 10)); // [-2^63, 500] - parseFilterAndCompare("($.apples / -50) > 10", + parseFilterAndCompare("($.apples / -50) > 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, -50 * 10 - 1)); // [-2^63, -501] - parseFilterAndCompare("($.apples / -50) >= 10", + parseFilterAndCompare("($.apples / -50) >= 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, -50 * 10)); // [-2^63, -500] - parseFilterAndCompare("($.apples / -50) < 10", + parseFilterAndCompare("($.apples / -50) < 10", INDEX_FILTER_INPUT, Filter.range("apples", -50 * 10 + 1, Long.MAX_VALUE)); // [-499, 2^63 - 1] - parseFilterAndCompare("($.apples / -50) <= 10", + parseFilterAndCompare("($.apples / -50) <= 10", INDEX_FILTER_INPUT, Filter.range("apples", -50 * 10, Long.MAX_VALUE)); // [-500, 2^63 - 1] - parseFilterAndCompare("($.apples / 50) > -10", + parseFilterAndCompare("($.apples / 50) > -10", INDEX_FILTER_INPUT, Filter.range("apples", 50 * -10 + 1, Long.MAX_VALUE)); // [-499, 2^63 - 1] - parseFilterAndCompare("($.apples / 50) >= -10", + parseFilterAndCompare("($.apples / 50) >= -10", INDEX_FILTER_INPUT, Filter.range("apples", 50 * -10, Long.MAX_VALUE)); // [-500, 2^63 - 1] - parseFilterAndCompare("($.apples / 50) < -10", + parseFilterAndCompare("($.apples / 50) < -10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 50 * -10 - 1)); // [-2^63, -501] - parseFilterAndCompare("($.apples / 50) <= -10", + parseFilterAndCompare("($.apples / 50) <= -10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 50 * -10)); // [-2^63, -500] - parseFilterAndCompare("($.apples / -50) > -10", + parseFilterAndCompare("($.apples / -50) > -10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, -50 * -10 - 1)); // [-2^63, 499] - parseFilterAndCompare("($.apples / -50) >= -10", + parseFilterAndCompare("($.apples / -50) >= -10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, -10 * -50)); // [-2^63, 500] - parseFilterAndCompare("($.apples / -50) < -10", + parseFilterAndCompare("($.apples / -50) < -10", INDEX_FILTER_INPUT, Filter.range("apples", -10 * -50 + 1, Long.MAX_VALUE)); // [501, 2^63 - 1] - parseFilterAndCompare("($.apples / -50) <= -10", + parseFilterAndCompare("($.apples / -50) <= -10", INDEX_FILTER_INPUT, Filter.range("apples", -10 * -50, Long.MAX_VALUE)); // [500, 2^63 - 1] } @Test void div_binIsDivided_leftNumberIsSmaller() { - parseFilterAndCompare("($.apples / 5) > 10", + parseFilterAndCompare("($.apples / 5) > 10", INDEX_FILTER_INPUT, Filter.range("apples", 5 * 10 + 1, Long.MAX_VALUE)); // [51, 2^63 - 1] - parseFilterAndCompare("($.apples / 5) >= 10", + parseFilterAndCompare("($.apples / 5) >= 10", INDEX_FILTER_INPUT, Filter.range("apples", 5 * 10, Long.MAX_VALUE)); // [50, 2^63 - 1] - parseFilterAndCompare("($.apples / 5) < 10", + parseFilterAndCompare("($.apples / 5) < 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 5 * 10 - 1)); // [-2^63, 49] - parseFilterAndCompare("($.apples / 5) <= 10", + parseFilterAndCompare("($.apples / 5) <= 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 5 * 10)); // [-2^63, 50] - parseFilterAndCompare("($.apples / -5) > 10", + parseFilterAndCompare("($.apples / -5) > 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, -5 * 10 - 1)); // [-2^63, -51] - parseFilterAndCompare("($.apples / -5) >= 10", + parseFilterAndCompare("($.apples / -5) >= 10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, -5 * 10)); // [-2^63, -50] - parseFilterAndCompare("($.apples / -5) < 10", + parseFilterAndCompare("($.apples / -5) < 10", INDEX_FILTER_INPUT, Filter.range("apples", -5 * 10 + 1, Long.MAX_VALUE)); // [-49, 2^63 - 1] - parseFilterAndCompare("($.apples / -5) <= 10", + parseFilterAndCompare("($.apples / -5) <= 10", INDEX_FILTER_INPUT, Filter.range("apples", -5 * 10, Long.MAX_VALUE)); // [-50, 2^63 - 1] - parseFilterAndCompare("($.apples / 5) > -10", + parseFilterAndCompare("($.apples / 5) > -10", INDEX_FILTER_INPUT, Filter.range("apples", 5 * -10 + 1, Long.MAX_VALUE)); // [-49, 2^63 - 1] - parseFilterAndCompare("($.apples / 5) >= -10", + parseFilterAndCompare("($.apples / 5) >= -10", INDEX_FILTER_INPUT, Filter.range("apples", 5 * -10, Long.MAX_VALUE)); // [-50, 2^63 - 1] - parseFilterAndCompare("($.apples / 5) < -10", + parseFilterAndCompare("($.apples / 5) < -10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 5 * -10 - 1)); // [-2^63, -51] - parseFilterAndCompare("($.apples / 5) <= -10", + parseFilterAndCompare("($.apples / 5) <= -10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 5 * -10)); // [-2^63, -50] - parseFilterAndCompare("($.apples / -5) > -10", + parseFilterAndCompare("($.apples / -5) > -10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, -5 * -10 - 1)); // [-2^63, 49] - parseFilterAndCompare("($.apples / -5) >= -10", + parseFilterAndCompare("($.apples / -5) >= -10", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, -10 * -5)); // [-2^63, 50] - parseFilterAndCompare("($.apples / -5) < -10", + parseFilterAndCompare("($.apples / -5) < -10", INDEX_FILTER_INPUT, Filter.range("apples", -10 * -5 + 1, Long.MAX_VALUE)); // [51, 2^63 - 1] - parseFilterAndCompare("($.apples / -5) <= -10", + parseFilterAndCompare("($.apples / -5) <= -10", INDEX_FILTER_INPUT, Filter.range("apples", -10 * -5, Long.MAX_VALUE)); // [50, 2^63 - 1] } @Test void div_binIsDivided_leftNumberEqualsRight() { - parseFilterAndCompare("($.apples / 5) > 5", + parseFilterAndCompare("($.apples / 5) > 5", INDEX_FILTER_INPUT, Filter.range("apples", 5 * 5 + 1, Long.MAX_VALUE)); // [26, 2^63 - 1] - parseFilterAndCompare("($.apples / 5) >= 5", + parseFilterAndCompare("($.apples / 5) >= 5", INDEX_FILTER_INPUT, Filter.range("apples", 5 * 5, Long.MAX_VALUE)); // [25, 2^63 - 1] - parseFilterAndCompare("($.apples / 5) < 5", + parseFilterAndCompare("($.apples / 5) < 5", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 5 * 5 - 1)); // [-2^63, 24] - parseFilterAndCompare("($.apples / 5) <= 5", + parseFilterAndCompare("($.apples / 5) <= 5", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, 5 * 5)); // [-2^63, 25] - parseFilterAndCompare("($.apples / -5) > -5", + parseFilterAndCompare("($.apples / -5) > -5", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, -5 * -5 - 1)); // [-2^63, 24] - parseFilterAndCompare("($.apples / -5) >= -5", + parseFilterAndCompare("($.apples / -5) >= -5", INDEX_FILTER_INPUT, Filter.range("apples", Long.MIN_VALUE, -5 * -5)); // [-2^63, 25] - parseFilterAndCompare("($.apples / -5) < -5", + parseFilterAndCompare("($.apples / -5) < -5", INDEX_FILTER_INPUT, Filter.range("apples", -5 * -5 + 1, Long.MAX_VALUE)); // [26, 2^63 - 1] - parseFilterAndCompare("($.apples / -5) <= -5", + parseFilterAndCompare("($.apples / -5) <= -5", INDEX_FILTER_INPUT, Filter.range("apples", -5 * -5, Long.MAX_VALUE)); // [25, 2^63 - 1] } @Test void div_binIsDivisor_leftNumberIsLarger() { - parseFilterAndCompare("(90 / $.bananas) > 10", + parseFilterAndCompare("(90 / $.bananas) > 10", INDEX_FILTER_INPUT, Filter.range("bananas", 1, 90 / 10 - 1)); // [1,8] - parseFilterAndCompare("(90 / $.bananas) >= 10", + parseFilterAndCompare("(90 / $.bananas) >= 10", INDEX_FILTER_INPUT, Filter.range("bananas", 1, 90 / 10)); // [1,9] // Not supported by secondary index filter - assertThat(parseFilter("(90 / $.bananas) < 10")).isNull(); - assertThat(parseFilter("(90 / $.bananas) <= 10")).isNull(); + assertThat(parseFilter("(90 / $.bananas) < 10", INDEX_FILTER_INPUT)).isNull(); + assertThat(parseFilter("(90 / $.bananas) <= 10", INDEX_FILTER_INPUT)).isNull(); // Not supported by secondary index filter - assertThat(parseFilter("(90 / $.bananas) > -10")).isNull(); - assertThat(parseFilter("(90 / $.bananas) >= -10")).isNull(); - parseFilterAndCompare("(90 / $.bananas) < -10", + assertThat(parseFilter("(90 / $.bananas) > -10", INDEX_FILTER_INPUT)).isNull(); + assertThat(parseFilter("(90 / $.bananas) >= -10", INDEX_FILTER_INPUT)).isNull(); + parseFilterAndCompare("(90 / $.bananas) < -10", INDEX_FILTER_INPUT, Filter.range("bananas", 90 / -10 + 1, -1)); // [-8, -1] - parseFilterAndCompare("(90 / $.bananas) <= -10", + parseFilterAndCompare("(90 / $.bananas) <= -10", INDEX_FILTER_INPUT, Filter.range("bananas", 90 / -10, -1)); // [-8, -1] - parseFilterAndCompare("(-90 / $.bananas) > 10", + parseFilterAndCompare("(-90 / $.bananas) > 10", INDEX_FILTER_INPUT, Filter.range("bananas", -90 / 10 + 1, -1)); // [-8, -1] - parseFilterAndCompare("(90 / $.bananas) >= 10", + parseFilterAndCompare("(90 / $.bananas) >= 10", INDEX_FILTER_INPUT, Filter.range("bananas", 1, 90 / 10)); // [1,9] // Not supported by secondary index filter - assertThat(parseFilter("(-90 / $.bananas) < 10")).isNull(); - assertThat(parseFilter("(-90 / $.bananas) <= 10")).isNull(); + assertThat(parseFilter("(-90 / $.bananas) < 10", INDEX_FILTER_INPUT)).isNull(); + assertThat(parseFilter("(-90 / $.bananas) <= 10", INDEX_FILTER_INPUT)).isNull(); // Not supported by secondary index filter - assertThat(parseFilter("(-90 / $.bananas) > -10")).isNull(); - assertThat(parseFilter("(-90 / $.bananas) >= -10")).isNull(); - parseFilterAndCompare("(-90 / $.bananas) < -10", + assertThat(parseFilter("(-90 / $.bananas) > -10", INDEX_FILTER_INPUT)).isNull(); + assertThat(parseFilter("(-90 / $.bananas) >= -10", INDEX_FILTER_INPUT)).isNull(); + parseFilterAndCompare("(-90 / $.bananas) < -10", INDEX_FILTER_INPUT, Filter.range("bananas", 1L, -90 / -10 - 1)); // [1, 8] - parseFilterAndCompare("(-90 / $.bananas) <= -10", + parseFilterAndCompare("(-90 / $.bananas) <= -10", INDEX_FILTER_INPUT, Filter.range("bananas", 1L, -90 / -10)); // [1, 9] } @Test void div_binIsDivisor_leftNumberIsSmaller() { // Not supported by secondary index filter - assertThat(parseFilter("(9 / $.bananas) > 10")).isNull(); // no integer numbers - assertThat(parseFilter("(9 / $.bananas) >= 10")).isNull(); // no integer numbers - assertThat(parseFilter("(9 / $.bananas) < 10")).isNull(); // maximal range is all numbers - assertThat(parseFilter("(9 / $.bananas) <= 10")).isNull(); // maximal range is all numbers - - assertThat(parseFilter("(9 / $.bananas) > -10")).isNull(); // maximal range is all numbers - assertThat(parseFilter("(9 / $.bananas) >= -10")).isNull(); // maximal range is all numbers - assertThat(parseFilter("(9 / $.bananas) < -10")).isNull(); // no integer numbers - assertThat(parseFilter("(9 / $.bananas) <= -10")).isNull(); // no integer numbers - - assertThat(parseFilter("(-9 / $.bananas) > 10")).isNull(); // no integer numbers - assertThat(parseFilter("(-9 / $.bananas) >= 10")).isNull(); // no integer numbers - assertThat(parseFilter("(-9 / $.bananas) < 10")).isNull(); // maximal range is all numbers - assertThat(parseFilter("(-9 / $.bananas) <= 10")).isNull(); // maximal range is all numbers - - assertThat(parseFilter("(-9 / $.bananas) > -10")).isNull(); // maximal range is all numbers - assertThat(parseFilter("(-9 / $.bananas) >= -10")).isNull(); // maximal range is all numbers - assertThat(parseFilter("(-9 / $.bananas) < -10")).isNull(); // no integer numbers - assertThat(parseFilter("(-9 / $.bananas) <= -10")).isNull(); // no integer numbers + assertThat(parseFilter("(9 / $.bananas) > 10", INDEX_FILTER_INPUT)).isNull(); // no integer numbers + assertThat(parseFilter("(9 / $.bananas) >= 10", INDEX_FILTER_INPUT)).isNull(); // no integer numbers + assertThat(parseFilter("(9 / $.bananas) < 10", INDEX_FILTER_INPUT)).isNull(); // maximal range is all numbers + assertThat(parseFilter("(9 / $.bananas) <= 10", INDEX_FILTER_INPUT)).isNull(); // maximal range is all numbers + + assertThat(parseFilter("(9 / $.bananas) > -10", INDEX_FILTER_INPUT)).isNull(); // maximal range is all numbers + assertThat(parseFilter("(9 / $.bananas) >= -10", INDEX_FILTER_INPUT)).isNull(); // maximal range is all numbers + assertThat(parseFilter("(9 / $.bananas) < -10", INDEX_FILTER_INPUT)).isNull(); // no integer numbers + assertThat(parseFilter("(9 / $.bananas) <= -10", INDEX_FILTER_INPUT)).isNull(); // no integer numbers + + assertThat(parseFilter("(-9 / $.bananas) > 10", INDEX_FILTER_INPUT)).isNull(); // no integer numbers + assertThat(parseFilter("(-9 / $.bananas) >= 10", INDEX_FILTER_INPUT)).isNull(); // no integer numbers + assertThat(parseFilter("(-9 / $.bananas) < 10", INDEX_FILTER_INPUT)).isNull(); // maximal range is all numbers + assertThat(parseFilter("(-9 / $.bananas) <= 10", INDEX_FILTER_INPUT)).isNull(); // maximal range is all numbers + + assertThat(parseFilter("(-9 / $.bananas) > -10", INDEX_FILTER_INPUT)).isNull(); // maximal range is all numbers + assertThat(parseFilter("(-9 / $.bananas) >= -10", INDEX_FILTER_INPUT)).isNull(); // maximal range is all numbers + assertThat(parseFilter("(-9 / $.bananas) < -10", INDEX_FILTER_INPUT)).isNull(); // no integer numbers + assertThat(parseFilter("(-9 / $.bananas) <= -10", INDEX_FILTER_INPUT)).isNull(); // no integer numbers // Not supported by secondary index Filter - assertThat(parseFilter("(0 / $.bananas) > 10")).isNull(); // maximal range is all numbers + assertThat(parseFilter("(0 / $.bananas) > 10", INDEX_FILTER_INPUT)).isNull(); // maximal range is all numbers // Not supported by secondary index Filter, cannot divide by zero - assertThat(parseFilter("(9 / $.bananas) > 0")).isNull(); // no integer numbers + assertThat(parseFilter("(9 / $.bananas) > 0", INDEX_FILTER_INPUT)).isNull(); // no integer numbers } @Test void div_binIsDivisor_leftNumberEqualsRight() { // Not supported by secondary index filter - assertThat(parseFilter("(90 / $.bananas) > 90")).isNull(); // no integer numbers - parseFilterAndCompare("(90 / $.bananas) >= 90", + assertThat(parseFilter("(90 / $.bananas) > 90", INDEX_FILTER_INPUT)).isNull(); // no integer numbers + parseFilterAndCompare("(90 / $.bananas) >= 90", INDEX_FILTER_INPUT, Filter.range("bananas", 90 / 90, 90 / 90)); // [1, 1] - assertThat(parseFilter("(90 / $.bananas) < 90")).isNull(); // maximal range is all numbers - assertThat(parseFilter("(90 / $.bananas) <= 90")).isNull(); // maximal range is all numbers + assertThat(parseFilter("(90 / $.bananas) < 90", INDEX_FILTER_INPUT)).isNull(); // maximal range is all numbers + assertThat(parseFilter("(90 / $.bananas) <= 90", INDEX_FILTER_INPUT)).isNull(); // maximal range is all numbers - assertThat(parseFilter("(-90 / $.bananas) > -90")).isNull(); // maximal range is all numbers - assertThat(parseFilter("(-90 / $.bananas) >= -90")).isNull(); // maximal range is all numbers - assertThat(parseFilter("(-90 / $.bananas) < -90")).isNull(); // no integer numbers - parseFilterAndCompare("(-90 / $.bananas) <= -90", + assertThat(parseFilter("(-90 / $.bananas) > -90", INDEX_FILTER_INPUT)).isNull(); // maximal range is all numbers + assertThat(parseFilter("(-90 / $.bananas) >= -90", INDEX_FILTER_INPUT)).isNull(); // maximal range is all numbers + assertThat(parseFilter("(-90 / $.bananas) < -90", INDEX_FILTER_INPUT)).isNull(); // no integer numbers + parseFilterAndCompare("(-90 / $.bananas) <= -90", INDEX_FILTER_INPUT, 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 index b94da89..4108ecd 100644 --- a/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java @@ -3,6 +3,7 @@ import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.dsl.Index; +import com.aerospike.dsl.IndexFilterInput; import org.junit.jupiter.api.Test; import java.util.List; @@ -13,24 +14,31 @@ class BinFiltersTests { + String NAMESPACE = "test1"; + List INDEXES = List.of( + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(1).build(), + Index.builder().namespace("test1").bin("stringBin1").indexType(IndexType.STRING).binValuesRatio(1).build() + ); + IndexFilterInput INDEX_FILTER_INPUT = IndexFilterInput.of(NAMESPACE, INDEXES); + @Test void binGT() { - parseFilterAndCompare("$.intBin1 > 100", + parseFilterAndCompare("$.intBin1 > 100", INDEX_FILTER_INPUT, Filter.range("intBin1", 101, Long.MAX_VALUE)); - parseFilterAndCompare("$.intBin1 > -100", + parseFilterAndCompare("$.intBin1 > -100", INDEX_FILTER_INPUT, Filter.range("intBin1", -99, Long.MAX_VALUE)); // Comparing Strings is not supported by secondary index Filters - assertThat(parseFilter("$.stringBin1 > 'text'")).isNull(); - assertThat(parseFilter("$.stringBin1 > \"text\"")).isNull(); + assertThat(parseFilter("$.stringBin1 > 'text'", INDEX_FILTER_INPUT)).isNull(); + assertThat(parseFilter("$.stringBin1 > \"text\"", INDEX_FILTER_INPUT)).isNull(); // "$.intBin1 > 100" and "100 < $.intBin1" represent identical Filters - parseFilterAndCompare("100 < $.intBin1", + parseFilterAndCompare("100 < $.intBin1", INDEX_FILTER_INPUT, Filter.range("intBin1", 101, Long.MAX_VALUE)); // Comparing Strings is not supported by secondary index Filters - assertThat(parseFilter("'text' > $.stringBin1")).isNull(); - assertThat(parseFilter("\"text\" > $.stringBin1")).isNull(); + assertThat(parseFilter("'text' > $.stringBin1", INDEX_FILTER_INPUT)).isNull(); + assertThat(parseFilter("\"text\" > $.stringBin1", INDEX_FILTER_INPUT)).isNull(); } @Test @@ -39,7 +47,7 @@ void binGT_logical_combinations() { Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(1).build() ); - parseFilterAndCompare("$.intBin1 > 100 and $.intBin2 < 1000", "test1", indexes, + parseFilterAndCompare("$.intBin1 > 100 and $.intBin2 < 1000", IndexFilterInput.of(NAMESPACE, indexes), Filter.range("intBin2", Long.MIN_VALUE, 999)); parseFilterAndCompare("$.intBin1 > 100 and $.intBin2 < 1000", @@ -48,54 +56,54 @@ void binGT_logical_combinations() { @Test void binGE() { - parseFilterAndCompare("$.intBin1 >= 100", + parseFilterAndCompare("$.intBin1 >= 100", INDEX_FILTER_INPUT, Filter.range("intBin1", 100, Long.MAX_VALUE)); // "$.intBin1 >= 100" and "100 <= $.intBin1" represent identical Filters - parseFilterAndCompare("100 <= $.intBin1", + parseFilterAndCompare("100 <= $.intBin1", INDEX_FILTER_INPUT, Filter.range("intBin1", 100, Long.MAX_VALUE)); } @Test void binLT() { - parseFilterAndCompare("$.intBin1 < 100", + parseFilterAndCompare("$.intBin1 < 100", INDEX_FILTER_INPUT, Filter.range("intBin1", Long.MIN_VALUE, 99)); - parseFilterAndCompare("100 > $.intBin1", + parseFilterAndCompare("100 > $.intBin1", INDEX_FILTER_INPUT, Filter.range("intBin1", Long.MIN_VALUE, 99)); } @Test void binLE() { - parseFilterAndCompare("$.intBin1 <= 100", + parseFilterAndCompare("$.intBin1 <= 100", INDEX_FILTER_INPUT, Filter.range("intBin1", Long.MIN_VALUE, 100)); - parseFilterAndCompare("100 >= $.intBin1", + parseFilterAndCompare("100 >= $.intBin1", INDEX_FILTER_INPUT, Filter.range("intBin1", Long.MIN_VALUE, 100)); } @Test void binEQ() { - parseFilterAndCompare("$.intBin1 == 100", + parseFilterAndCompare("$.intBin1 == 100", INDEX_FILTER_INPUT, Filter.equal("intBin1", 100)); - parseFilterAndCompare("100 == $.intBin1", + parseFilterAndCompare("100 == $.intBin1", INDEX_FILTER_INPUT, Filter.equal("intBin1", 100)); - parseFilterAndCompare("$.stringBin1 == 'text'", + parseFilterAndCompare("$.stringBin1 == 'text'", INDEX_FILTER_INPUT, Filter.equal("stringBin1", "text")); - parseFilterAndCompare("$.stringBin1 == \"text\"", + parseFilterAndCompare("$.stringBin1 == \"text\"", INDEX_FILTER_INPUT, Filter.equal("stringBin1", "text")); } @Test void binNOTEQ() { // NOT EQUAL is not supported by secondary index filter - assertThat(parseFilter("$.intBin1 != 100")).isNull(); - assertThat(parseFilter("$.stringBin1 != 'text'")).isNull(); - assertThat(parseFilter("$.stringBin1 != \"text\"")).isNull(); + assertThat(parseFilter("$.intBin1 != 100", INDEX_FILTER_INPUT)).isNull(); + assertThat(parseFilter("$.stringBin1 != 'text'", INDEX_FILTER_INPUT)).isNull(); + assertThat(parseFilter("$.stringBin1 != \"text\"", INDEX_FILTER_INPUT)).isNull(); - assertThat(parseFilter("100 != $.intBin1")).isNull(); - assertThat(parseFilter("100 != 'text'")).isNull(); - assertThat(parseFilter("100 != \"text\"")).isNull(); + assertThat(parseFilter("100 != $.intBin1", INDEX_FILTER_INPUT)).isNull(); + assertThat(parseFilter("100 != 'text'", INDEX_FILTER_INPUT)).isNull(); + assertThat(parseFilter("100 != \"text\"", INDEX_FILTER_INPUT)).isNull(); } } diff --git a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java index 427d042..95922a1 100644 --- a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java @@ -1,11 +1,15 @@ package com.aerospike.dsl.filter; import com.aerospike.client.query.Filter; +import com.aerospike.client.query.IndexType; +import com.aerospike.dsl.Index; +import com.aerospike.dsl.IndexFilterInput; import com.aerospike.dsl.exception.AerospikeDSLException; import com.aerospike.dsl.util.TestUtils; import org.junit.jupiter.api.Test; import java.util.Base64; +import java.util.List; import static com.aerospike.dsl.util.TestUtils.parseFilter; import static org.assertj.core.api.Assertions.assertThat; @@ -13,27 +17,38 @@ public class ExplicitTypesFiltersTests { + String NAMESPACE = "test1"; + List INDEXES = List.of( + Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(1).build(), + Index.builder().namespace("test1").bin("stringBin1").indexType(IndexType.STRING).binValuesRatio(1).build(), + Index.builder().namespace("test1").bin("blobBin1").indexType(IndexType.BLOB).binValuesRatio(1).build() + ); + IndexFilterInput INDEX_FILTER_INPUT = IndexFilterInput.of(NAMESPACE, INDEXES); + @Test void integerComparison() { - TestUtils.parseFilterAndCompare("$.intBin1.get(type: INT) > 5", + // Namespace and indexes must be given to create a Filter + TestUtils.parseFilterAndCompare("$.intBin1.get(type: INT) > 5", null); + + TestUtils.parseFilterAndCompare("$.intBin1.get(type: INT) > 5", INDEX_FILTER_INPUT, Filter.range("intBin1", 6, Long.MAX_VALUE)); - TestUtils.parseFilterAndCompare("5 < $.intBin1.get(type: INT)", + TestUtils.parseFilterAndCompare("5 < $.intBin1.get(type: INT)", INDEX_FILTER_INPUT, Filter.range("intBin1", 6, Long.MAX_VALUE)); } @Test void stringComparison() { - TestUtils.parseFilterAndCompare("$.stringBin1.get(type: STRING) == \"yes\"", + TestUtils.parseFilterAndCompare("$.stringBin1.get(type: STRING) == \"yes\"", INDEX_FILTER_INPUT, Filter.equal("stringBin1", "yes")); - TestUtils.parseFilterAndCompare("$.stringBin1.get(type: STRING) == 'yes'", + TestUtils.parseFilterAndCompare("$.stringBin1.get(type: STRING) == 'yes'", INDEX_FILTER_INPUT, Filter.equal("stringBin1", "yes")); - TestUtils.parseFilterAndCompare("\"yes\" == $.stringBin1.get(type: STRING)", + TestUtils.parseFilterAndCompare("\"yes\" == $.stringBin1.get(type: STRING)", INDEX_FILTER_INPUT, Filter.equal("stringBin1", "yes")); - TestUtils.parseFilterAndCompare("'yes' == $.stringBin1.get(type: STRING)", + TestUtils.parseFilterAndCompare("'yes' == $.stringBin1.get(type: STRING)", INDEX_FILTER_INPUT, Filter.equal("stringBin1", "yes")); } @@ -49,11 +64,11 @@ void stringComparisonNegativeTest() { void blobComparison() { byte[] data = new byte[]{1, 2, 3}; String encodedString = Base64.getEncoder().encodeToString(data); - TestUtils.parseFilterAndCompare("$.blobBin1.get(type: BLOB) == \"" + encodedString + "\"", + TestUtils.parseFilterAndCompare("$.blobBin1.get(type: BLOB) == \"" + encodedString + "\"", INDEX_FILTER_INPUT, Filter.equal("blobBin1", data)); // Reverse - TestUtils.parseFilterAndCompare("\"" + encodedString + "\" == $.blobBin1.get(type: BLOB)", + TestUtils.parseFilterAndCompare("\"" + encodedString + "\" == $.blobBin1.get(type: BLOB)", INDEX_FILTER_INPUT, Filter.equal("blobBin1", data)); } diff --git a/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java b/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java index c1e810d..3177f93 100644 --- a/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java +++ b/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java @@ -4,6 +4,7 @@ import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.dsl.Index; +import com.aerospike.dsl.IndexFilterInput; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -31,7 +32,8 @@ void binLogical_AND_2_all_indexes() { Filter filter = Filter.range("intBin2", 101, Long.MAX_VALUE); Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, namespace, indexes); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, + IndexFilterInput.of(namespace, indexes)); } @Test @@ -45,7 +47,8 @@ void binLogical_AND_2_all_indexes_no_cardinality() { Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, namespace, indexes); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, + IndexFilterInput.of(namespace, indexes)); } @Test @@ -56,7 +59,8 @@ void binLogical_AND_2_one_index() { Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); - parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, namespace, indexes); + parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, + IndexFilterInput.of(namespace, indexes)); } @Test @@ -75,7 +79,7 @@ void binLogical_AND_3_all_indexes() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, - namespace, indexes); + IndexFilterInput.of(namespace, indexes)); } @Test @@ -95,7 +99,7 @@ void binLogical_AND_3_all_indexes_same_cardinality() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, - namespace, indexes); + IndexFilterInput.of(namespace, indexes)); } @Test @@ -115,7 +119,7 @@ void binLogical_AND_3_all_indexes_no_cardinality() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, - namespace, indexes); + IndexFilterInput.of(namespace, indexes)); } @Test @@ -137,7 +141,7 @@ void binLogical_AND_3_all_indexes_partial_data() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, - namespace, indexes); + IndexFilterInput.of(namespace, indexes)); } @Test @@ -155,7 +159,7 @@ void binLogical_AND_3_two_indexes() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, - namespace, indexes); + IndexFilterInput.of(namespace, indexes)); } @Test @@ -178,7 +182,8 @@ void binLogical_OR_2_all_indexes() { Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), Exp.gt(Exp.intBin("intBin2"), Exp.val(100)) ); - parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", filter, exp, namespace, indexes); + parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", filter, exp, + IndexFilterInput.of(namespace, indexes)); } @Test @@ -192,7 +197,8 @@ void binLogical_OR_2_one_index() { Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), Exp.gt(Exp.intBin("intBin2"), Exp.val(100)) ); - parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", filter, exp, namespace, indexes); + parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", filter, exp, + IndexFilterInput.of(namespace, indexes)); } @Test @@ -212,7 +218,7 @@ void binLogical_OR_3_all_indexes() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100 or $.intBin3 > 100", filter, exp, - namespace, indexes); + IndexFilterInput.of(namespace, indexes)); } @Test @@ -232,9 +238,9 @@ void binLogical_prioritizedAND_OR_indexed() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 or $.intBin3 > 100", filter, exp, - namespace, indexes); + IndexFilterInput.of(namespace, indexes)); parseExpressionAndCompare("($.intBin1 > 100 and $.intBin2 > 100) or $.intBin3 > 100", filter, exp, - namespace, indexes); + IndexFilterInput.of(namespace, indexes)); } @Disabled // TODO: complex logical structures, different grouping @@ -255,6 +261,6 @@ void binLogical_AND_prioritizedOR_indexed() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 > 100)", filter, exp, - namespace, indexes); + IndexFilterInput.of(namespace, indexes)); } } diff --git a/src/test/java/com/aerospike/dsl/util/TestUtils.java b/src/test/java/com/aerospike/dsl/util/TestUtils.java index 69a3471..74e2478 100644 --- a/src/test/java/com/aerospike/dsl/util/TestUtils.java +++ b/src/test/java/com/aerospike/dsl/util/TestUtils.java @@ -5,6 +5,7 @@ import com.aerospike.client.query.Filter; import com.aerospike.dsl.DSLParserImpl; import com.aerospike.dsl.Index; +import com.aerospike.dsl.IndexFilterInput; import com.aerospike.dsl.ParsedExpression; import lombok.experimental.UtilityClass; @@ -16,22 +17,23 @@ public class TestUtils { private final DSLParserImpl parser = new DSLParserImpl(); + public static Expression parseExp(String input) { - return Exp.build(parser.parseExpression(input).getResultPair().getExp()); + return Exp.build(parser.parseExpression(input).getResult().getExp()); } public static void parseExpAndCompare(String input, Exp expected) { - Expression actualExpression = Exp.build(parser.parseExpression(input).getResultPair().getExp()); + Expression actualExpression = Exp.build(parser.parseExpression(input).getResult().getExp()); Expression expectedExpression = Exp.build(expected); assertEquals(actualExpression, expectedExpression); } public static Filter parseFilter(String input) { - return parser.parseExpression(input).getResultPair().getFilter(); + return parser.parseExpression(input).getResult().getFilter(); } - public static Filter parseFilter(String input, String namespace, List indexes) { - return parser.parseExpression(input, namespace, indexes).getResultPair().getFilter(); + public static Filter parseFilter(String input, IndexFilterInput indexFilterInput) { + return parser.parseExpression(input, indexFilterInput).getResult().getFilter(); } public static void parseFilterAndCompare(String input, Filter expected) { @@ -39,23 +41,22 @@ public static void parseFilterAndCompare(String input, Filter expected) { assertEquals(actualFilter, expected); } - public static void parseFilterAndCompare(String input, String namespace, List indexes, Filter expected) { - Filter actualFilter = parseFilter(input, namespace, indexes); + public static void parseFilterAndCompare(String input, IndexFilterInput indexFilterInput, Filter expected) { + Filter actualFilter = parseFilter(input, indexFilterInput); assertEquals(actualFilter, expected); } public static void parseExpressionAndCompare(String input, Filter filter, Exp exp) { ParsedExpression actualExpression = parser.parseExpression(input); - assertEquals(actualExpression.getResultPair().getFilter(), filter); - Exp actualExp = actualExpression.getResultPair().getExp(); + assertEquals(actualExpression.getResult().getFilter(), filter); + Exp actualExp = actualExpression.getResult().getExp(); assertEquals(actualExp == null ? null : Exp.build(actualExp), exp == null ? null : Exp.build(exp)); } - public static void parseExpressionAndCompare(String input, Filter filter, Exp exp, - String namespace, List indexes) { - ParsedExpression actualExpression = parser.parseExpression(input, namespace, indexes); - assertEquals(actualExpression.getResultPair().getFilter(), filter); - Exp actualExp = actualExpression.getResultPair().getExp(); + public static void parseExpressionAndCompare(String input, Filter filter, Exp exp, IndexFilterInput indexFilterInput) { + ParsedExpression actualExpression = parser.parseExpression(input, indexFilterInput); + assertEquals(actualExpression.getResult().getFilter(), filter); + Exp actualExp = actualExpression.getResult().getExp(); assertEquals(actualExp == null ? null : Exp.build(actualExp), exp == null ? null : Exp.build(exp)); } } From bbe2364fd2b0f5aa8141ddd6178d60c9d165463a Mon Sep 17 00:00:00 2001 From: agrgr Date: Tue, 29 Apr 2025 01:01:42 +0300 Subject: [PATCH 10/20] update building Filter --- .../java/com/aerospike/dsl/visitor/VisitorUtils.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index 3f6b5d1..6218b59 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -837,8 +837,14 @@ private static BinPart getBinPart(ExpressionContainer expr) { } } - if (expr.getRight() != null && expr.getRight().getPartType() == BIN_PART) { - return (BinPart) expr.getRight(); + if (expr.getRight() != null) { + if (expr.getRight().getPartType() == BIN_PART) { + return (BinPart) expr.getRight(); + } + if (expr.getRight().getPartType() == EXPRESSION_CONTAINER) { + result = getBinPart((ExpressionContainer) expr.getRight()); + if (result != null) return result; + } } } return result; From 7d0d3f25419f3a9845dd8b96dad72577abb5e039 Mon Sep 17 00:00:00 2001 From: agrgr Date: Tue, 29 Apr 2025 15:44:49 +0300 Subject: [PATCH 11/20] code format --- .../java/com/aerospike/dsl/DSLParserImpl.java | 4 +- .../com/aerospike/dsl/ParsedExpression.java | 5 +- .../com/aerospike/dsl/part/AbstractPart.java | 4 +- .../dsl/part/ExpressionContainer.java | 10 ++- .../aerospike/dsl/visitor/VisitorUtils.java | 62 +++++++++---------- 5 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/aerospike/dsl/DSLParserImpl.java b/src/main/java/com/aerospike/dsl/DSLParserImpl.java index 2e7cbed..a4fa58a 100644 --- a/src/main/java/com/aerospike/dsl/DSLParserImpl.java +++ b/src/main/java/com/aerospike/dsl/DSLParserImpl.java @@ -13,10 +13,10 @@ import java.util.HashMap; import java.util.Map; -import static com.aerospike.dsl.visitor.VisitorUtils.*; - public class DSLParserImpl implements DSLParser { + public static final String INDEX_NAME_SEPARATOR = "."; + @Beta public ParsedExpression parseExpression(String dslString) { ParseTree parseTree = getParseTree(dslString); diff --git a/src/main/java/com/aerospike/dsl/ParsedExpression.java b/src/main/java/com/aerospike/dsl/ParsedExpression.java index d9487bb..3bcf0b2 100644 --- a/src/main/java/com/aerospike/dsl/ParsedExpression.java +++ b/src/main/java/com/aerospike/dsl/ParsedExpression.java @@ -12,8 +12,7 @@ import java.util.Map; import static com.aerospike.dsl.part.AbstractPart.PartType.EXPRESSION_CONTAINER; -import static com.aerospike.dsl.visitor.VisitorUtils.*; - +import static com.aerospike.dsl.visitor.VisitorUtils.buildExpr; /** * A class to build and store the results of DSL expression parsing: secondary index {@link Filter} @@ -46,7 +45,7 @@ public Result getResult() { return result; } - public Result getResultPair() { + private Result getResultPair() { if (expressionTree != null) { if (expressionTree.getPartType() == EXPRESSION_CONTAINER) { AbstractPart result = buildExpr((ExpressionContainer) expressionTree, namespace, indexesMap); diff --git a/src/main/java/com/aerospike/dsl/part/AbstractPart.java b/src/main/java/com/aerospike/dsl/part/AbstractPart.java index 37a0cd1..c59f9ad 100644 --- a/src/main/java/com/aerospike/dsl/part/AbstractPart.java +++ b/src/main/java/com/aerospike/dsl/part/AbstractPart.java @@ -11,8 +11,8 @@ public abstract class AbstractPart { protected Exp.Type expType; protected PartType partType; - protected Exp exp; - protected Filter filter; + private Exp exp; + private Filter filter; protected AbstractPart(PartType partType) { this.partType = partType; diff --git a/src/main/java/com/aerospike/dsl/part/ExpressionContainer.java b/src/main/java/com/aerospike/dsl/part/ExpressionContainer.java index ce9e508..5b110fd 100644 --- a/src/main/java/com/aerospike/dsl/part/ExpressionContainer.java +++ b/src/main/java/com/aerospike/dsl/part/ExpressionContainer.java @@ -5,14 +5,17 @@ @Getter public class ExpressionContainer extends AbstractPart { - protected AbstractPart left; - protected AbstractPart right; - private ExprPartsOperation operationType; + private final AbstractPart left; + private final AbstractPart right; + private final ExprPartsOperation operationType; private final boolean isUnary; public ExpressionContainer() { super(PartType.EXPRESSION_CONTAINER); this.isUnary = false; + this.left = null; + this.right = null; + this.operationType = null; } public ExpressionContainer(AbstractPart left, AbstractPart right, ExprPartsOperation operationType) { @@ -26,6 +29,7 @@ public ExpressionContainer(AbstractPart left, AbstractPart right, ExprPartsOpera public ExpressionContainer(AbstractPart singleOperand, ExprPartsOperation operationType) { super(PartType.EXPRESSION_CONTAINER); this.left = singleOperand; + this.right = null; this.operationType = operationType; this.isUnary = true; } diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index 6218b59..15ef426 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -4,18 +4,19 @@ import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.dsl.ConditionParser; +import com.aerospike.dsl.Index; import com.aerospike.dsl.exception.AerospikeDSLException; import com.aerospike.dsl.exception.NoApplicableFilterException; -import com.aerospike.dsl.Index; -import com.aerospike.dsl.part.*; -import com.aerospike.dsl.part.path.BinPart; +import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.part.ExpressionContainer; import com.aerospike.dsl.part.controlstructure.ExclusiveStructure; +import com.aerospike.dsl.part.controlstructure.WhenStructure; +import com.aerospike.dsl.part.controlstructure.WithStructure; import com.aerospike.dsl.part.operand.IntOperand; import com.aerospike.dsl.part.operand.MetadataOperand; import com.aerospike.dsl.part.operand.StringOperand; -import com.aerospike.dsl.part.controlstructure.WhenStructure; import com.aerospike.dsl.part.operand.WithOperand; -import com.aerospike.dsl.part.controlstructure.WithStructure; +import com.aerospike.dsl.part.path.BinPart; import lombok.experimental.UtilityClass; import org.antlr.v4.runtime.misc.Pair; import org.antlr.v4.runtime.tree.ParseTree; @@ -32,6 +33,7 @@ import java.util.function.UnaryOperator; import java.util.stream.Stream; +import static com.aerospike.dsl.DSLParserImpl.INDEX_NAME_SEPARATOR; import static com.aerospike.dsl.part.AbstractPart.PartType.*; import static com.aerospike.dsl.part.ExpressionContainer.ExprPartsOperation.*; import static com.aerospike.dsl.util.ValidationUtils.validateComparableTypes; @@ -40,41 +42,17 @@ @UtilityClass public class VisitorUtils { - public final String INDEX_NAME_SEPARATOR = "."; private final Map expTypeToIndexType = Map.of( Exp.Type.INT, IndexType.NUMERIC, Exp.Type.STRING, IndexType.STRING, Exp.Type.BLOB, IndexType.BLOB ); - private final List CTRL_STRUCTURE_HOLDERS = List.of( + private final List CTRL_STRUCTURES = List.of( ExpressionContainer.ExprPartsOperation.WITH_STRUCTURE, ExpressionContainer.ExprPartsOperation.WHEN_STRUCTURE, ExpressionContainer.ExprPartsOperation.EXCLUSIVE_STRUCTURE ); - - 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); @@ -169,7 +147,7 @@ private static Exp getFilterExpression(ExpressionContainer expr, AbstractPart pa Exp leftExp = null; if (part.getPartType() == EXPRESSION_CONTAINER) { if (expr.isUnary()) { - if (!CTRL_STRUCTURE_HOLDERS.contains(expr.getOperationType())) { + if (!CTRL_STRUCTURES.contains(expr.getOperationType())) { // If the expression holds a control structure leftExp = getUnaryExpOrFail(part, getUnaryExpOperator(expr.getOperationType())); part.setExp(leftExp); @@ -923,4 +901,26 @@ private static UnaryOperator getUnaryExpOperator(ExpressionContainer.ExprPa default -> throw new NoApplicableFilterException("ExprPartsOperation has no matching UnaryOperator"); }; } + + protected enum FilterOperationType { + GT, + GTEQ, + LT, + LTEQ, + EQ, + NOTEQ + } + + protected enum ArithmeticTermType { + ADDEND, + SUBTR, + MIN, + DIFFERENCE, + DIVIDEND, + DIVISOR, + QUOTIENT, + MULTIPLICAND, + MULTIPLIER, + PRODUCT + } } From 99148130d7cf233ff40b00241f00f609634e8870 Mon Sep 17 00:00:00 2001 From: agrgr Date: Sun, 4 May 2025 14:29:29 +0300 Subject: [PATCH 12/20] optimize creating Exp for AND-combined queries, refactor VisitorUtils --- .../com/aerospike/dsl/ParsedExpression.java | 5 +- .../com/aerospike/dsl/part/AbstractPart.java | 4 +- .../dsl/part/ExpressionContainer.java | 11 +- .../com/aerospike/dsl/util/ParsingUtils.java | 44 + .../visitor/ExpressionConditionVisitor.java | 4 +- .../aerospike/dsl/visitor/VisitorUtils.java | 1268 +++++++++++------ .../dsl/expression/ExplicitTypesTests.java | 2 +- .../LogicalParsedExpressionTests.java | 29 +- 8 files changed, 889 insertions(+), 478 deletions(-) diff --git a/src/main/java/com/aerospike/dsl/ParsedExpression.java b/src/main/java/com/aerospike/dsl/ParsedExpression.java index 3bcf0b2..d9487bb 100644 --- a/src/main/java/com/aerospike/dsl/ParsedExpression.java +++ b/src/main/java/com/aerospike/dsl/ParsedExpression.java @@ -12,7 +12,8 @@ import java.util.Map; import static com.aerospike.dsl.part.AbstractPart.PartType.EXPRESSION_CONTAINER; -import static com.aerospike.dsl.visitor.VisitorUtils.buildExpr; +import static com.aerospike.dsl.visitor.VisitorUtils.*; + /** * A class to build and store the results of DSL expression parsing: secondary index {@link Filter} @@ -45,7 +46,7 @@ public Result getResult() { return result; } - private Result getResultPair() { + public Result getResultPair() { if (expressionTree != null) { if (expressionTree.getPartType() == EXPRESSION_CONTAINER) { AbstractPart result = buildExpr((ExpressionContainer) expressionTree, namespace, indexesMap); diff --git a/src/main/java/com/aerospike/dsl/part/AbstractPart.java b/src/main/java/com/aerospike/dsl/part/AbstractPart.java index c59f9ad..37a0cd1 100644 --- a/src/main/java/com/aerospike/dsl/part/AbstractPart.java +++ b/src/main/java/com/aerospike/dsl/part/AbstractPart.java @@ -11,8 +11,8 @@ public abstract class AbstractPart { protected Exp.Type expType; protected PartType partType; - private Exp exp; - private Filter filter; + protected Exp exp; + protected Filter filter; protected AbstractPart(PartType partType) { this.partType = partType; diff --git a/src/main/java/com/aerospike/dsl/part/ExpressionContainer.java b/src/main/java/com/aerospike/dsl/part/ExpressionContainer.java index 5b110fd..8d3548d 100644 --- a/src/main/java/com/aerospike/dsl/part/ExpressionContainer.java +++ b/src/main/java/com/aerospike/dsl/part/ExpressionContainer.java @@ -1,14 +1,19 @@ package com.aerospike.dsl.part; import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; @Getter public class ExpressionContainer extends AbstractPart { - private final AbstractPart left; - private final AbstractPart right; - private final ExprPartsOperation operationType; + protected final AbstractPart left; + protected final AbstractPart right; private final boolean isUnary; + private final ExprPartsOperation operationType; + @Setter() + @Accessors(fluent = true) + private boolean hasSIndexFilter; public ExpressionContainer() { super(PartType.EXPRESSION_CONTAINER); diff --git a/src/main/java/com/aerospike/dsl/util/ParsingUtils.java b/src/main/java/com/aerospike/dsl/util/ParsingUtils.java index 8677e88..3db3f25 100644 --- a/src/main/java/com/aerospike/dsl/util/ParsingUtils.java +++ b/src/main/java/com/aerospike/dsl/util/ParsingUtils.java @@ -1,5 +1,6 @@ package com.aerospike.dsl.util; +import com.aerospike.dsl.exception.AerospikeDSLException; import lombok.NonNull; import lombok.experimental.UtilityClass; @@ -28,4 +29,47 @@ public static String unquote(String str) { public static Integer subtractNullable(Integer a, @NonNull Integer b) { return a == null ? null : a - b; } + + /** + * Extracts the type string from a method name expected to start with "as" and end with "()". + * + * @param methodName The method name string + * @return The extracted type string + * @throws AerospikeDSLException if the method name is not in the correct format + */ + public 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)); + } + } + + /** + * Extracts the function name from a string that may include parameters in parentheses. + * + * @param text The input string containing the function name and potentially parameters + * @return The extracted function name + */ + public static String extractFunctionName(String text) { + int startParen = text.indexOf('('); + return (startParen != -1) ? text.substring(0, startParen) : text; + } + + /** + * Extracts an integer parameter from a string enclosed in parentheses. + * + * @param text The input string + * @return The extracted integer parameter, or {@code null} if not found or invalid + */ + public 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; + } } diff --git a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java index c6850a8..faf38e1 100644 --- a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java +++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java @@ -31,7 +31,7 @@ import java.util.List; import java.util.TreeMap; -import static com.aerospike.dsl.util.ParsingUtils.unquote; +import static com.aerospike.dsl.util.ParsingUtils.*; import static com.aerospike.dsl.visitor.VisitorUtils.*; public class ExpressionConditionVisitor extends ConditionBaseVisitor { @@ -420,7 +420,7 @@ public AbstractPart visitBasePath(ConditionParser.BasePathContext ctx) { @Override public AbstractPart visitVariable(ConditionParser.VariableContext ctx) { String text = ctx.VARIABLE_REFERENCE().getText(); - return new VariableOperand(extractVariableName(text)); + return new VariableOperand(extractVariableNameOrFail(text)); } private AbstractPart overrideType(AbstractPart part, ParseTree ctx) { diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index 15ef426..45b2db0 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -9,6 +9,7 @@ import com.aerospike.dsl.exception.NoApplicableFilterException; import com.aerospike.dsl.part.AbstractPart; import com.aerospike.dsl.part.ExpressionContainer; +import com.aerospike.dsl.part.ExpressionContainer.ExprPartsOperation; import com.aerospike.dsl.part.controlstructure.ExclusiveStructure; import com.aerospike.dsl.part.controlstructure.WhenStructure; import com.aerospike.dsl.part.controlstructure.WithStructure; @@ -30,10 +31,10 @@ import java.util.Map; import java.util.Objects; import java.util.function.BinaryOperator; +import java.util.function.Consumer; +import java.util.function.Predicate; import java.util.function.UnaryOperator; -import java.util.stream.Stream; -import static com.aerospike.dsl.DSLParserImpl.INDEX_NAME_SEPARATOR; import static com.aerospike.dsl.part.AbstractPart.PartType.*; import static com.aerospike.dsl.part.ExpressionContainer.ExprPartsOperation.*; import static com.aerospike.dsl.util.ValidationUtils.validateComparableTypes; @@ -42,25 +43,127 @@ @UtilityClass public class VisitorUtils { + public final String INDEX_NAME_SEPARATOR = "."; private final Map expTypeToIndexType = Map.of( Exp.Type.INT, IndexType.NUMERIC, Exp.Type.STRING, IndexType.STRING, Exp.Type.BLOB, IndexType.BLOB ); - private final List CTRL_STRUCTURES = List.of( - ExpressionContainer.ExprPartsOperation.WITH_STRUCTURE, - ExpressionContainer.ExprPartsOperation.WHEN_STRUCTURE, - ExpressionContainer.ExprPartsOperation.EXCLUSIVE_STRUCTURE - ); - static String extractVariableName(String variableReference) { + protected enum FilterOperationType { + GT, + GTEQ, + LT, + LTEQ, + EQ, + NOTEQ + } + + protected enum ArithmeticTermType { + ADDEND, + SUBTR, + MIN, + DIFFERENCE, + DIVIDEND, + DIVISOR, + QUOTIENT, + MULTIPLICAND, + MULTIPLIER, + PRODUCT + } + + /** + * Converts an {@link ExprPartsOperation} enum value to its corresponding {@link FilterOperationType}. + * + * @param exprPartsOperation The {@link ExprPartsOperation} to convert + * @return The corresponding {@link FilterOperationType} + * @throws NoApplicableFilterException if the {@link ExprPartsOperation} has no matching {@link FilterOperationType} + */ + private static FilterOperationType getFilterOperation(ExprPartsOperation exprPartsOperation) { + return switch (exprPartsOperation) { + case GT -> FilterOperationType.GT; + case GTEQ -> FilterOperationType.GTEQ; + case LT -> FilterOperationType.LT; + case LTEQ -> FilterOperationType.LTEQ; + case EQ -> FilterOperationType.EQ; + case NOTEQ -> FilterOperationType.NOTEQ; + default -> throw new NoApplicableFilterException("ExprPartsOperation has no matching FilterOperationType"); + }; + } + + /** + * Gets the appropriate {@link BinaryOperator} for a given {@link ExprPartsOperation}. + * + * @param exprPartsOperation The {@link ExprPartsOperation} for which to get the binary operator + * @return A {@link BinaryOperator} that performs the corresponding operation on two {@link Exp} operands + * @throws NoApplicableFilterException if the {@link ExprPartsOperation} has no matching {@link BinaryOperator} + */ + private static BinaryOperator getExpOperator(ExprPartsOperation exprPartsOperation) { + return switch (exprPartsOperation) { + case ADD -> Exp::add; + case SUB -> Exp::sub; + case MUL -> Exp::mul; + case DIV -> Exp::div; + case MOD -> Exp::mod; + case INT_XOR -> Exp::intXor; + case L_SHIFT -> Exp::lshift; + case R_SHIFT -> Exp::rshift; + case INT_AND -> Exp::intAnd; + case INT_OR -> Exp::intOr; + case AND -> Exp::and; + case OR -> Exp::or; + case EQ -> Exp::eq; + case NOTEQ -> Exp::ne; + case LT -> Exp::lt; + case LTEQ -> Exp::le; + case GT -> Exp::gt; + case GTEQ -> Exp::ge; + default -> throw new NoApplicableFilterException("ExprPartsOperation has no matching BinaryOperator"); + }; + } + + /** + * Gets the appropriate {@link UnaryOperator} for a given {@link ExprPartsOperation}. + * + * @param exprPartsOperation The {@link ExprPartsOperation} for which to get the unary operator + * @return A {@link UnaryOperator} that performs the corresponding operation on a single {@link Exp} operand + * @throws NoApplicableFilterException if the {@link ExprPartsOperation} has no matching {@link UnaryOperator} + */ + private static UnaryOperator getUnaryExpOperator(ExprPartsOperation exprPartsOperation) { + return switch (exprPartsOperation) { + case INT_NOT -> Exp::intNot; + case NOT -> Exp::not; + default -> throw new NoApplicableFilterException("ExprPartsOperation has no matching UnaryOperator"); + }; + } + + /** + * Extracts the variable name from a string formatted as "${variableName}". + * If it matches this format, it returns the substring between these markers, otherwise it throws an + * {@code IllegalArgumentException}. + * + * @param variableReference The input string + * @return The extracted variable name + * @throws IllegalArgumentException if the input string does not match the format + */ + static String extractVariableNameOrFail(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"); - } + /** + * The method traverses the parse tree from the given context {@code ctx} + * towards the root. At each level, it checks the children for operand contexts. + * If an operand context representing an integer, float, string, or boolean + * is found, its corresponding {@link Exp.Type} is returned. The search stops + * upon finding the first such operand in the upward path. + * + * @param ctx The current parse tree context to start searching from. + * @return The detected implicit {@link Exp.Type} (INT, FLOAT, STRING, or BOOL), + * or {@code null} if no such operand is found in the upper tree levels. + */ 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 @@ -89,17 +192,39 @@ static Exp.Type detectImplicitTypeFromUpperTree(ParseTree ctx) { return null; } + /** + * Sets the logical bin type for both the left and right expression containers + * to {@link Exp.Type#BOOL} if they represent a bin part. + * + * @param left The left {@link ExpressionContainer} + * @param right The right {@link ExpressionContainer} + */ static void logicalSetBinsAsBooleanExpr(ExpressionContainer left, ExpressionContainer right) { logicalSetBinAsBooleanExpr(left); logicalSetBinAsBooleanExpr(right); } + /** + * Sets the logical bin type for a single expression container to {@link Exp.Type#BOOL} + * if it represents a bin part. + * + * @param expr The {@link ExpressionContainer} to potentially update + */ static void logicalSetBinAsBooleanExpr(ExpressionContainer expr) { - if (expr instanceof BinPart) { + if (expr.getPartType() == BIN_PART) { ((BinPart) expr).updateExp(Exp.Type.BOOL); } } + /** + * Determines whether a child parse tree element at a specific index within a list + * should be visited during tree traversal. + * + * @param i The index of the child element + * @param size The total number of children in the list context + * @param child The parse tree child element at the given index + * @return {@code true} if the child should be visited as a list element, {@code false} otherwise + */ static boolean shouldVisitListElement(int i, int size, ParseTree child) { return size > 0 // size is not 0 && i != 0 // not the first element ('[') @@ -107,6 +232,15 @@ static boolean shouldVisitListElement(int i, int size, ParseTree child) { && !child.getText().equals(","); // not a comma (list elements separator) } + /** + * Determines whether a child parse tree element at a specific index within a map + * should be visited during tree traversal. + * + * @param i The index of the child element + * @param size The total number of children in the map context + * @param child The parse tree child element at the given index + * @return {@code true} if the child should be visited as a map element, {@code false} otherwise + */ static boolean shouldVisitMapElement(int i, int size, ParseTree child) { return size > 0 // size is not 0 && i != 0 // not the first element ('{') @@ -115,183 +249,116 @@ static boolean shouldVisitMapElement(int i, int size, ParseTree child) { && !child.getText().equals(","); // not a comma (map pairs separator) } - // 2 operands Expressions - static Exp exprToExp(ExpressionContainer expr) { - if (expr.isUnary()) { - return getUnaryExpOrFail(expr.getLeft(), getUnaryExpOperator(expr.getOperationType())); - } - - AbstractPart left = expr.getLeft(); - AbstractPart right = expr.getRight(); - if (left == null) { - throw new AerospikeDSLException("Unable to parse left operand"); - } - if (right == null) { - throw new AerospikeDSLException("Unable to parse right operand"); - } - - Exp leftExp = getFilterExpression(expr, left, right.getPartType()); - Exp rightExp = getFilterExpression(expr, right, left.getPartType()); - - BinaryOperator operator = getExpOperator(expr.getOperationType()); - if (left.getPartType() == BIN_PART) { - return getExpLeftBinTypeComparison((BinPart) left, right, operator); - } - if (right.getPartType() == BIN_PART) { - return getExpRightBinTypeComparison(left, (BinPart) right, operator); - } - return operator.apply(leftExp, rightExp); - } - - private static Exp getFilterExpression(ExpressionContainer expr, AbstractPart part, AbstractPart.PartType secondPartType) { - Exp leftExp = null; - if (part.getPartType() == EXPRESSION_CONTAINER) { - if (expr.isUnary()) { - if (!CTRL_STRUCTURES.contains(expr.getOperationType())) { - // If the expression holds a control structure - leftExp = getUnaryExpOrFail(part, getUnaryExpOperator(expr.getOperationType())); - part.setExp(leftExp); - } else { - leftExp = getFilterExp((ExpressionContainer) part); - part.setExp(leftExp); - } - } else { - leftExp = getFilterExp((ExpressionContainer) part); - part.setExp(leftExp); - } - } else if (part.getPartType() != BIN_PART && secondPartType != BIN_PART) { - leftExp = part.getExp(); - } - return leftExp; - } - - static Exp getExpLeftBinTypeComparison(BinPart left, AbstractPart right, BinaryOperator operator) { - Exp leftExp = Exp.bin(left.getBinName(), left.getExpType()); - return switch (right.getPartType()) { + /** + * Creates an expression for comparing a bin with another operand. + * + * @param binPart The bin part + * @param otherPart The other operand to compare with + * @param operator The binary operator to apply + * @param binIsLeft Whether the bin is on the left side of the comparison + * @return The resulting expression + * @throws AerospikeDSLException if the operand type is not supported + */ + private static Exp getExpBinComparison(BinPart binPart, AbstractPart otherPart, + BinaryOperator operator, boolean binIsLeft) { + Exp binExp = Exp.bin(binPart.getBinName(), binPart.getExpType()); + Exp otherExp = switch (otherPart.getPartType()) { case INT_OPERAND -> { - validateComparableTypes(left.getExpType(), Exp.Type.INT); - yield operator.apply(leftExp, right.getExp()); + validateComparableTypes(binPart.getExpType(), Exp.Type.INT); + yield otherPart.getExp(); } case FLOAT_OPERAND -> { - validateComparableTypes(left.getExpType(), Exp.Type.FLOAT); - yield operator.apply(leftExp, right.getExp()); + validateComparableTypes(binPart.getExpType(), Exp.Type.FLOAT); + yield otherPart.getExp(); } case BOOL_OPERAND -> { - validateComparableTypes(left.getExpType(), Exp.Type.BOOL); - yield operator.apply(leftExp, right.getExp()); - } - case STRING_OPERAND -> { - if (left.getExpType() != null && - left.getExpType().equals(Exp.Type.BLOB)) { - // Base64 Blob - validateComparableTypes(left.getExpType(), Exp.Type.BLOB); - StringOperand stringRight = (StringOperand) right; - stringRight.setBlob(true); - yield operator.apply(leftExp, stringRight.getExp()); - } else { - // String - validateComparableTypes(left.getExpType(), Exp.Type.STRING); - yield operator.apply(leftExp, right.getExp()); - } + validateComparableTypes(binPart.getExpType(), Exp.Type.BOOL); + yield otherPart.getExp(); } + case STRING_OPERAND -> handleStringOperandComparison(binPart, (StringOperand) otherPart); case METADATA_OPERAND -> { - // No need to validate, types are determined by metadata function - Exp.Type binType = Exp.Type.valueOf(((MetadataOperand) right).getMetadataType().toString()); - leftExp = Exp.bin(left.getBinName(), binType); - yield operator.apply(leftExp, right.getExp()); + // Handle metadata comparison - type determined by metadata function + Exp.Type binType = Exp.Type.valueOf(((MetadataOperand) otherPart).getMetadataType().toString()); + binExp = Exp.bin(binPart.getBinName(), binType); + yield otherPart.getExp(); } - case EXPRESSION_CONTAINER, PATH_OPERAND -> - operator.apply(leftExp, right.getExp()); // Can't validate with Expr on one side + case EXPRESSION_CONTAINER, PATH_OPERAND, VARIABLE_OPERAND -> + // Can't validate with expression container + otherPart.getExp(); case BIN_PART -> { - // Left and right are both bin parts - // Validate types if possible - validateComparableTypes(left.getExpType(), right.getExpType()); - yield operator.apply(leftExp, right.getExp()); + // Both are bin parts + validateComparableTypes(binPart.getExpType(), otherPart.getExpType()); + yield otherPart.getExp(); } case LIST_OPERAND -> { - validateComparableTypes(left.getExpType(), Exp.Type.LIST); - yield operator.apply(leftExp, right.getExp()); + validateComparableTypes(binPart.getExpType(), Exp.Type.LIST); + yield otherPart.getExp(); } case MAP_OPERAND -> { - validateComparableTypes(left.getExpType(), Exp.Type.MAP); - yield operator.apply(leftExp, right.getExp()); + validateComparableTypes(binPart.getExpType(), Exp.Type.MAP); + yield otherPart.getExp(); } - case VARIABLE_OPERAND -> operator.apply(leftExp, right.getExp()); - default -> throw new AerospikeDSLException("Operand type not supported: %s".formatted(right.getPartType())); + default -> + throw new AerospikeDSLException("Operand type not supported: %s".formatted(otherPart.getPartType())); }; - } - static Exp getExpRightBinTypeComparison(AbstractPart left, BinPart right, BinaryOperator operator) { - Exp rightExp = Exp.bin(right.getBinName(), right.getExpType()); - return switch (left.getPartType()) { - case INT_OPERAND -> { - validateComparableTypes(Exp.Type.INT, right.getExpType()); - yield operator.apply(left.getExp(), rightExp); - } - case FLOAT_OPERAND -> { - validateComparableTypes(Exp.Type.FLOAT, right.getExpType()); - yield operator.apply(left.getExp(), rightExp); - } - case BOOL_OPERAND -> { - validateComparableTypes(Exp.Type.BOOL, right.getExpType()); - yield operator.apply(left.getExp(), rightExp); - } - case STRING_OPERAND -> { - if (right.getExpType() != null && - right.getExpType().equals(Exp.Type.BLOB)) { - // Base64 Blob - validateComparableTypes(Exp.Type.BLOB, right.getExpType()); - StringOperand stringLeft = (StringOperand) left; - stringLeft.setBlob(true); - yield operator.apply(stringLeft.getExp(), rightExp); - } else { - // String - validateComparableTypes(Exp.Type.STRING, right.getExpType()); - yield operator.apply(left.getExp(), rightExp); - } - } - case METADATA_OPERAND -> { - // No need to validate, types are determined by metadata function - Exp.Type binType = Exp.Type.valueOf(((MetadataOperand) left).getMetadataType().toString()); - rightExp = Exp.bin(right.getBinName(), binType); - yield operator.apply(left.getExp(), rightExp); - } - case EXPRESSION_CONTAINER, 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(), rightExp); - } - case MAP_OPERAND -> { - validateComparableTypes(Exp.Type.MAP, right.getExpType()); - yield operator.apply(left.getExp(), rightExp); - } - case VARIABLE_OPERAND -> operator.apply(left.getExp(), rightExp); - default -> throw new AerospikeDSLException("Operand type not supported: %s".formatted(left.getPartType())); - }; + return binIsLeft ? operator.apply(binExp, otherExp) : operator.apply(otherExp, binExp); } - // 1 operand Expressions - static Exp getUnaryExpOrFail(AbstractPart operand, UnaryOperator operator) { - if (operand == null) { - throw new AerospikeDSLException("Unable to parse unary operand"); + /** + * Handles string operand comparison with type validation and blob handling. + * + * @param binPart The {@link BinPart} involved in the comparison + * @param stringOperand The {@link StringOperand} involved in the comparison + * @return The {@link Exp} generated from the {@link StringOperand} + * @throws AerospikeDSLException if type validation fails (e.g., comparing a non-string/blob bin with a String) + */ + private static Exp handleStringOperandComparison(BinPart binPart, StringOperand stringOperand) { + boolean isBlobType = binPart.getExpType() != null && binPart.getExpType().equals(Exp.Type.BLOB); + if (isBlobType) { + // Handle base64 blob comparison + validateComparableTypes(binPart.getExpType(), Exp.Type.BLOB); + stringOperand.setBlob(true); + } else { + // Handle regular string comparison + validateComparableTypes(binPart.getExpType(), Exp.Type.STRING); } + return stringOperand.getExp(); + } - return switch (operand.getPartType()) { - case BIN_PART -> { - BinPart binPart = ((BinPart) operand); - // There is only 1 case of a single bin expression - yield operator.apply(Exp.bin(binPart.getBinName(), binPart.getExpType())); - } - case METADATA_OPERAND -> { - MetadataOperand metadataOperand = ((MetadataOperand) operand); - yield operator.apply(metadataOperand.getExp()); - } - default -> throw new AerospikeDSLException("Unsupported part type for an unary expression"); - }; + /** + * Creates an expression for comparing a bin on the left with an operand on the right. + * + * @param left The {@link BinPart} on the left side of the comparison + * @param right The {@link AbstractPart} on the right side of the comparison + * @param operator The binary operator to apply + * @return The resulting {@link Exp} for the comparison + * @throws AerospikeDSLException if an unsupported operand type is encountered or type validation fails + */ + private static Exp getExpLeftBinTypeComparison(BinPart left, AbstractPart right, BinaryOperator operator) { + return getExpBinComparison(left, right, operator, true); + } + + /** + * Creates an expression for comparing an operand on the left with a bin on the right. + * + * @param left The {@link AbstractPart} on the left side of the comparison + * @param right The {@link BinPart} on the right side of the comparison + * @param operator The binary operator to apply + * @return The resulting {@link Exp} for the comparison + * @throws AerospikeDSLException if an unsupported operand type is encountered or type validation fails + */ + private static Exp getExpRightBinTypeComparison(AbstractPart left, BinPart right, BinaryOperator operator) { + return getExpBinComparison(right, left, operator, false); } + /** + * Extracts the value of a specific parameter from a Path Function parameter context. + * + * @param paramCtx The parse tree context for the Path Function parameter + * @param paramName The name of the parameter to extract the value for + * @return The value of the specified parameter if found and matches the name, otherwise {@code null}. + */ static String getPathFunctionParam(ConditionParser.PathFunctionParamContext paramCtx, String paramName) { String paramNameText; String paramNameValue; @@ -306,112 +373,15 @@ static String getPathFunctionParam(ConditionParser.PathFunctionParamContext para 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() == BIN_PART) { - return getFilter((BinPart) left, right, type); - } - if (right.getPartType() == BIN_PART) { - return getFilter((BinPart) right, left, invertType(type)); - } - - // Handle non Bin operands cases - if (left.getPartType() == EXPRESSION_CONTAINER) { - ExpressionContainer leftExpr = (ExpressionContainer) left; - return getFilterOrFail(leftExpr.getLeft(), leftExpr.getRight(), leftExpr.getOperationType(), right, type); - } - if (right.getPartType() == EXPRESSION_CONTAINER) { - ExpressionContainer rightExpr = (ExpressionContainer) right; - return getFilterOrFail(rightExpr.getLeft(), rightExpr.getRight(), rightExpr.getOperationType(), left, type); - } - return null; - } - - // 2 operands Filters - static Filter getFilterOrFail(AbstractPart exprLeft, AbstractPart exprRight, ExpressionContainer.ExprPartsOperation operationType, - AbstractPart right, FilterOperationType type) { - if (exprLeft == null) { - throw new NoApplicableFilterException("Unable to parse left operand of expression"); - } - if (exprRight == null) { - throw new NoApplicableFilterException("Unable to parse right operand of expression"); - } - - if (exprLeft.getPartType() == BIN_PART) { // bin is on the left side - if (exprRight.getPartType() == INT_OPERAND && right.getPartType() == INT_OPERAND) { -// validateNumericBinForFilter(left, right); - IntOperand leftOperand = (IntOperand) exprRight; - IntOperand rightOperand = (IntOperand) right; - validateComparableTypes(exprLeft.getExpType(), Exp.Type.INT); - return applyFilterOperator(((BinPart) exprLeft).getBinName(), leftOperand, rightOperand, - operationType, type, getFilterTermType(operationType, true)); - } - throw new NoApplicableFilterException( - String.format("Operands not supported in secondary index Filter: %s, %s", exprRight, right)); - } - if (exprRight.getPartType() == BIN_PART) { // bin is on the right side - if (exprLeft.getPartType() == INT_OPERAND && right.getPartType() == INT_OPERAND) { - IntOperand leftOperand = (IntOperand) exprLeft; - IntOperand rightOperand = (IntOperand) right; - validateComparableTypes(exprRight.getExpType(), Exp.Type.INT); - return applyFilterOperator(((BinPart) exprRight).getBinName(), leftOperand, rightOperand, - operationType, type, getFilterTermType(operationType, false)); - } - throw new NoApplicableFilterException( - String.format("Operands not supported in secondary index Filter: %s, %s", exprRight, right)); - } - - // Handle non Bin operands cases - if (exprLeft.getPartType() == EXPRESSION_CONTAINER) { - ExpressionContainer leftExpr = (ExpressionContainer) exprLeft; - return getFilterOrFail(leftExpr.getLeft(), leftExpr.getRight(), type); - } - return null; - } - - static void validateNumericBinForFilter(AbstractPart left, AbstractPart right) { - if (!isNumericBin(left, right)) { - throw new NoApplicableFilterException("The operation is not supported by secondary index filter"); - } - } - - private static boolean isNumericBin(AbstractPart left, AbstractPart right) { - return (left.getPartType() == BIN_PART && right.getPartType() == INT_OPERAND) - || (right.getPartType() == BIN_PART && left.getPartType() == INT_OPERAND); - } - - private static ArithmeticTermType getFilterTermType(ExpressionContainer.ExprPartsOperation operationType, + /** + * Determines the arithmetic term type based on the operation type and whether it is the left or right operand. + * + * @param operationType The type of the arithmetic operation + * @param isLeftTerm {@code true} if the term is the left operand, {@code false} if it's the right + * @return The corresponding {@link ArithmeticTermType} + * @throws NoApplicableFilterException if the operation type is not supported for determining arithmetic term type + */ + private static ArithmeticTermType getFilterTermType(ExprPartsOperation operationType, boolean isLeftTerm) { return switch (operationType) { case ADD -> ADDEND; @@ -423,6 +393,19 @@ private static ArithmeticTermType getFilterTermType(ExpressionContainer.ExprPart }; } + /** + * This method determines the possible range of values for a bin that is either the dividend or the divisor + * in a division operation, based on the values of the other operand and the filter operation type* + * + * @param left The value of the left operand + * @param right The value of the right operand + * @param type The type of the filter operation + * @param termType The {@link ArithmeticTermType} of the bin + * @return A {@link Pair} representing the lower and upper bounds of the range for the bin. + * A {@code null} value in the pair indicates no bound on that side + * @throws NoApplicableFilterException if division by zero occurs or the term type is unsupported + * @throws AerospikeDSLException if undefined division (0/0) occurs + */ private static Pair getLimitsForDivisionForFilter(long left, long right, FilterOperationType type, ArithmeticTermType termType) { // Prevent division by zero @@ -437,6 +420,17 @@ private static Pair getLimitsForDivisionForFilter(long left, long ri }; } + /** + * This method determines the possible range of values for a bin when it is the dividend in a division operation, + * based on the value of the divisor (right operand) and the filter operation type. + * + * @param left The value of the dividend (the bin's value) + * @param right The value of the divisor + * @param operationType The type of the filter operation + * @return A {@link Pair} representing the lower and upper bounds of the range for the bin. + * A {@code null} value in the pair indicates no bound on that side + * @throws AerospikeDSLException if undefined division (0/0) occurs or if the operation type is not supported + */ private static Pair LimitsForBinDividend(long left, long right, FilterOperationType operationType) { if (left > 0 && right > 0) { @@ -460,6 +454,15 @@ private static Pair LimitsForBinDividend(long left, long right, } } + /** + * Calculates the range limits for a bin that is the dividend when the left number is negative. + * + * @param operationType The type of the filter operation + * @param left The value of the dividend + * @param right The value of the divisor + * @return A {@link Pair} representing the lower and upper bounds of the range for the bin + * @throws AerospikeDSLException if the operation type is not supported for division + */ private static Pair getLimitsForBinDividendWithLeftNumberNegative(FilterOperationType operationType, long left, long right) { return switch (operationType) { @@ -476,6 +479,15 @@ private static Pair getLimitsForBinDividendWithLeftNumberNegative(Fi }; } + /** + * Calculates the range limits for a bin that is the dividend when the left number is positive. + * + * @param operationType The type of the filter operation + * @param left The value of the dividend + * @param right The value of the divisor + * @return A {@link Pair} representing the lower and upper bounds of the range for the bin + * @throws AerospikeDSLException if the operation type is not supported for division + */ private static Pair getLimitsForBinDividendWithLeftNumberPositive(FilterOperationType operationType, long left, long right) { return switch (operationType) { @@ -492,6 +504,16 @@ private static Pair getLimitsForBinDividendWithLeftNumberPositive(Fi }; } + /** + * Calculates the range limits for a bin that is the divisor in a division operation. + * + * @param left The value of the dividend + * @param right The value of the divisor + * @param operationType The type of the filter operation + * @return A {@link Pair} representing the lower and upper bounds of the range for the bin. + * A {@code null} value in the pair indicates no bound on that side + * @throws AerospikeDSLException if division by zero occurs or if the operation type is not supported + */ private static Pair getLimitsForBinDivisor(long left, long right, FilterOperationType operationType) { if (left > 0 && right > 0) { // both operands are positive @@ -550,6 +572,16 @@ private static Pair getLimitsForBinDivisor(long left, long right, Fi } } + /** + * Generates a {@link Filter} for a division operation based on the calculated value range and operation type. + * + * @param binName The name of the bin to filter on + * @param value A {@link Pair} representing the lower and upper bounds of the acceptable range for the bin. + * A {@code null} value in the pair indicates no bound on that side + * @param type The type of the filter operation + * @return A {@link Filter} representing the condition + * @throws AerospikeDSLException if the operation type is not supported for generating a filter + */ private static Filter getFilterForDivOrFail(String binName, Pair value, FilterOperationType type) { // Based on the operation type, generate the appropriate filter range return switch (type) { @@ -559,37 +591,225 @@ private static Filter getFilterForDivOrFail(String binName, Pair val }; } + /** + * Creates a Filter based on a bin and an operand. + * + * @param bin The bin part + * @param operand The operand part + * @param type The filter operation type + * @return The appropriate Filter + * @throws NoApplicableFilterException if no appropriate filter can be created + */ private static Filter getFilter(BinPart bin, AbstractPart operand, FilterOperationType type) { + validateOperands(bin, operand); 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 != FilterOperationType.EQ) throw new NoApplicableFilterException("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 NoApplicableFilterException("Operand type not supported: %s".formatted(operand.getPartType())); + case STRING_OPERAND -> handleStringOperand(bin, binName, (StringOperand) operand, type); + default -> throw new NoApplicableFilterException( + "Operand type not supported: %s".formatted(operand.getPartType())); }; } + /** + * This method is used to generate a {@link Filter} when one of the operands is a {@link BinPart} + * and the other is a {@link StringOperand}. It currently only supports equality (`EQ`) comparisons. + * It handles both regular strings and base64 encoded BLOBs. + * + * @param bin The {@link BinPart} involved in the filter + * @param binName The name of the bin + * @param operand The {@link StringOperand} involved in the filter + * @param type The type of the filter operation (must be {@link FilterOperationType#EQ}) + * @return An Aerospike {@link Filter} for the string or blob comparison + * @throws NoApplicableFilterException if the filter operation type is not equality + * @throws AerospikeDSLException if type validation fails or base64 decoding fails + */ + private static Filter handleStringOperand(BinPart bin, String binName, StringOperand operand, + FilterOperationType type) { + if (type != FilterOperationType.EQ) { + throw new NoApplicableFilterException("Only equality comparison is supported for string operands"); + } + + // Handle BLOB type + if (bin.getExpType() != null && bin.getExpType().equals(Exp.Type.BLOB)) { + validateComparableTypes(bin.getExpType(), Exp.Type.BLOB); + byte[] value = Base64.getDecoder().decode(operand.getValue()); + return Filter.equal(binName, value); + } + + // Handle STRING type + validateComparableTypes(bin.getExpType(), Exp.Type.STRING); + return Filter.equal(binName, operand.getValue()); + } + + /** + * Creates a Filter based on two operands and a filter operation type. + * + * @param left The left operand + * @param right The right operand + * @param type The filter operation type + * @return The appropriate Filter, or null if no filter can be created + * @throws AerospikeDSLException if operands are invalid + */ + private static Filter getFilterOrFail(AbstractPart left, AbstractPart right, FilterOperationType type) { + validateOperands(left, right); + + // Handle bin operands + if (left.getPartType() == BIN_PART) { + return getFilter((BinPart) left, right, type); + } + + if (right.getPartType() == BIN_PART) { + return getFilter((BinPart) right, left, invertType(type)); + } + + // Handle expressions + if (left.getPartType() == EXPRESSION_CONTAINER) { + return handleExpressionOperand((ExpressionContainer) left, right, type); + } + + if (right.getPartType() == EXPRESSION_CONTAINER) { + return handleExpressionOperand((ExpressionContainer) right, left, type); + } + + return null; + } + + /** + * This method is used when one of the operands is an {@link ExpressionContainer}. + * It recursively processes the nested expression to determine if a filter can be generated from it in combination + * with the {@code otherOperand} and the overall {@code type} of the filter operation. + * + * @param expr The {@link ExpressionContainer} operand + * @param otherOperand The other operand in the filter condition + * @param type The type of the filter operation + * @return A {@link Filter} if one can be generated from the nested expression, otherwise {@code null} + * @throws AerospikeDSLException if operands within the nested expression are null + * @throws NoApplicableFilterException if the nested expression structure is not supported for filtering + */ + private static Filter handleExpressionOperand(ExpressionContainer expr, AbstractPart otherOperand, + FilterOperationType type) { + AbstractPart exprLeft = expr.getLeft(); + AbstractPart exprRight = expr.getRight(); + ExprPartsOperation operation = expr.getOperationType(); + + validateOperands(exprLeft, exprRight); + + return getFilterFromExpressionOrFail(exprLeft, exprRight, operation, otherOperand, type); + } + + /** + * Creates a secondary index {@link Filter} based on an expression and an external operand. + * The method examines the structure of the nested expression and attempts to generate a {@link Filter} + * by combining it with the {@code externalOperand} and the overall {@code type} of the filter operation. + * It specifically looks for cases where a bin is involved in an arithmetic expression with an external operand. + * + * @param exprLeft The left part of an expression + * @param exprRight The right part of an expression + * @param operationType The operation type of the expression + * @param externalOperand The operand outside the expression + * @param type The type of the overall filter operation + * @return A {@link Filter} if one can be generated, otherwise {@code null} + * @throws NoApplicableFilterException if the expression structure is not supported for filtering + */ + private static Filter getFilterFromExpressionOrFail(AbstractPart exprLeft, AbstractPart exprRight, + ExprPartsOperation operationType, + AbstractPart externalOperand, FilterOperationType type) { + // Handle bin on left side + if (exprLeft.getPartType() == BIN_PART) { + return handleBinArithmeticExpression((BinPart) exprLeft, exprRight, externalOperand, + operationType, type, true); + } + + // Handle bin on right side + if (exprRight.getPartType() == BIN_PART) { + return handleBinArithmeticExpression((BinPart) exprRight, exprLeft, externalOperand, + operationType, type, false); + } + + // Handle nested expressions + if (exprLeft.getPartType() == EXPRESSION_CONTAINER) { + return getFilterOrFail(exprLeft, exprRight, type); + } + + return null; + } + + /** + * This method is used when a secondary index {@link Filter} is being generated from an arithmetic + * expression where one operand is a bin and the other is a literal value. It enforces + * that both the literal operand and the external operand (from the overall filter condition) + * must be integers for secondary index filtering. + * It then calls{@link #applyFilterOperator} to generate the actual filter. + * + * @param bin The {@link BinPart} involved in the arithmetic expression + * @param operand The other operand within the arithmetic expression (expected to be an integer) + * @param externalOperand The operand from the overall filter condition (expected to be an integer) + * @param operation The type of the arithmetic operation + * @param type The type of the overall filter operation + * @param binOnLeft {@code true} if the bin is on the left side of the arithmetic operation, {@code false} otherwise + * @return A {@link Filter} for the arithmetic condition + * @throws NoApplicableFilterException if operands are not integers or if the operation is not supported + * @throws AerospikeDSLException if type validation fails + */ + private static Filter handleBinArithmeticExpression(BinPart bin, AbstractPart operand, + AbstractPart externalOperand, + ExprPartsOperation operation, + FilterOperationType type, boolean binOnLeft) { + // Only support integer arithmetic in filters + if (operand.getPartType() != INT_OPERAND || externalOperand.getPartType() != INT_OPERAND) { + throw new NoApplicableFilterException( + "Only integer operands are supported in arithmetic filter expressions"); + } + + validateComparableTypes(bin.getExpType(), Exp.Type.INT); + + IntOperand firstOperand = (IntOperand) operand; + IntOperand secondOperand = (IntOperand) externalOperand; + + return applyFilterOperator(bin.getBinName(), firstOperand, secondOperand, + operation, type, getFilterTermType(operation, binOnLeft)); + } + + /** + * Validates that both left and right operands are not null. + * This is a basic validation helper used to ensure that essential parts + * of an expression are present before attempting to process them. + * + * @param left The left {@link AbstractPart} + * @param right The right {@link AbstractPart} + * @throws AerospikeDSLException if either the left or right operand is null + */ + private static void validateOperands(AbstractPart left, AbstractPart right) { + if (left == null) { + throw new AerospikeDSLException("Left operand cannot be null"); + } + if (right == null) { + throw new AerospikeDSLException("Right operand cannot be null"); + } + } + + /** + * This method handles arithmetic operations between two integer operands and converts the result + * into an appropriate secondary index {@link Filter} based on the filter operation type. + * + * @param binName The name of the bin to apply the filter to + * @param leftOperand The left {@link IntOperand} + * @param rightOperand The right {@link IntOperand} + * @param operationType The type of the arithmetic operation + * @param type The type of the filter operation + * @param termType The {@link ArithmeticTermType} of the bin + * @return A secondary index {@link Filter} + * @throws NoApplicableFilterException if the operation is not supported by secondary index filters, + * division by zero occurs, or the calculated range is invalid + * @throws AerospikeDSLException if undefined division (0/0) occurs or other issues arise + */ private static Filter applyFilterOperator(String binName, IntOperand leftOperand, IntOperand rightOperand, - ExpressionContainer.ExprPartsOperation operationType, FilterOperationType type, + ExprPartsOperation operationType, FilterOperationType type, ArithmeticTermType termType) { long leftValue = leftOperand.getValue(); long rightValue = rightOperand.getValue(); @@ -627,6 +847,15 @@ private static Filter applyFilterOperator(String binName, IntOperand leftOperand return getFilterForArithmeticOrFail(binName, value, type); } + /** + * Generates a {@link Filter} for an arithmetic operation involving a bin and a value. + * + * @param binName The name of the bin to filter on + * @param value The calculated value from the arithmetic operation + * @param type The type of the filter operation + * @return A {@link Filter} representing the condition + * @throws NoApplicableFilterException if the operation type is not supported for secondary index filter + */ private static Filter getFilterForArithmeticOrFail(String binName, float value, FilterOperationType type) { return switch (type) { // "$.intBin1 > 100" and "100 < $.intBin1" represent the same Filter @@ -640,6 +869,12 @@ private static Filter getFilterForArithmeticOrFail(String binName, float value, }; } + /** + * Finds the closest long integer to the left of a given float value. + * + * @param value The float value + * @return The closest long integer to the left + */ private static long getClosestLongToTheLeft(float value) { // Get the largest integer less than or equal to the float long flooredValue = (long) Math.floor(value); @@ -648,10 +883,15 @@ private static long getClosestLongToTheLeft(float value) { if (value == flooredValue) { return flooredValue - 1; } - return flooredValue; } + /** + * Finds the closest long integer to the right of a given float value. + * + * @param value The float value + * @return The closest long integer to the right + */ private static long getClosestLongToTheRight(float value) { // Get the smallest integer greater than or equal to the float long ceiledValue = (long) Math.ceil(value); @@ -664,7 +904,14 @@ private static long getClosestLongToTheRight(float value) { return ceiledValue; } - private FilterOperationType invertType(FilterOperationType type) { + /** + * This method provides the inverse operation for {@link FilterOperationType} comparison types. + * For other Filter operation types, it returns the original type. + * + * @param type Filter operation type to invert + * @return The inverted {@link FilterOperationType} + */ + private static FilterOperationType invertType(FilterOperationType type) { return switch (type) { case GT -> FilterOperationType.LT; case GTEQ -> FilterOperationType.LTEQ; @@ -674,6 +921,16 @@ private FilterOperationType invertType(FilterOperationType type) { }; } + /** + * Builds a secondary index {@link Filter} and a filter {@link Exp} for a given {@link ExpressionContainer}. + * This is the main entry point for enriching the parsed expression tree with query filters. + * + * @param expr The {@link ExpressionContainer} representing the expression tree + * @param namespace The namespace in use + * @param indexes A map of available secondary indexes, keyed by namespace and bin name + * @return The updated {@link ExpressionContainer} with the generated {@link Filter} and {@link Exp}. + * Either of them can be null if there is no suitable filter + */ public static AbstractPart buildExpr(ExpressionContainer expr, String namespace, Map indexes) { Exp exp; Filter sIndexFilter = null; @@ -688,16 +945,32 @@ public static AbstractPart buildExpr(ExpressionContainer expr, String namespace, return expr; } + /** + * Returns the {@link Exp} generated for a given {@link ExpressionContainer}. + * + * @param expr The input {@link ExpressionContainer} + * @return The corresponding {@link Exp}, or {@code null} if a secondary index filter was applied + * or if there is no suitable filter + */ private static Exp getFilterExp(ExpressionContainer expr) { + // Skip the expression already used in creating secondary index Filter + if (expr.hasSIndexFilter()) return null; + return switch (expr.getOperationType()) { - case WITH_STRUCTURE -> withStructureHolderToExp(expr); - case WHEN_STRUCTURE -> whenStructureHolderToExp(expr); - case EXCLUSIVE_STRUCTURE -> exclStructureHolderToExp(expr); - default -> exprToExp(expr); + case WITH_STRUCTURE -> withStructureToExp(expr); + case WHEN_STRUCTURE -> whenStructureToExp(expr); + case EXCLUSIVE_STRUCTURE -> exclStructureToExp(expr); + default -> processExpression(expr); }; } - private static Exp withStructureHolderToExp(ExpressionContainer expr) { + /** + * Generates filter {@link Exp} for a WITH structure {@link ExpressionContainer}. + * + * @param expr The {@link ExpressionContainer} representing WITH structure + * @return The resulting {@link Exp} expression + */ + private static Exp withStructureToExp(ExpressionContainer expr) { List expressions = new ArrayList<>(); WithStructure withOperandsList = (WithStructure) expr.getLeft(); // extract unary Expr operand List operands = withOperandsList.getOperands(); @@ -712,7 +985,14 @@ private static Exp withStructureHolderToExp(ExpressionContainer expr) { return Exp.let(expressions.toArray(new Exp[0])); } - private static Exp whenStructureHolderToExp(ExpressionContainer expr) { + + /** + * Generates filter {@link Exp} for a WHEN structure {@link ExpressionContainer}. + * + * @param expr The {@link ExpressionContainer} representing WHEN structure + * @return The resulting {@link Exp} expression + */ + private static Exp whenStructureToExp(ExpressionContainer expr) { List expressions = new ArrayList<>(); WhenStructure whenOperandsList = (WhenStructure) expr.getLeft(); // extract unary Expr operand List operands = whenOperandsList.getOperands(); @@ -722,7 +1002,13 @@ private static Exp whenStructureHolderToExp(ExpressionContainer expr) { return Exp.cond(expressions.toArray(new Exp[0])); } - private static Exp exclStructureHolderToExp(ExpressionContainer expr) { + /** + * Generates filter {@link Exp} for an EXCLUSIVE structure {@link ExpressionContainer}. + * + * @param expr The {@link ExpressionContainer} representing EXCLUSIVE structure + * @return The resulting {@link Exp} expression + */ + private static Exp exclStructureToExp(ExpressionContainer expr) { List expressions = new ArrayList<>(); ExclusiveStructure whenOperandsList = (ExclusiveStructure) expr.getLeft(); // extract unary Expr operand List operands = whenOperandsList.getOperands(); @@ -732,6 +1018,87 @@ private static Exp exclStructureHolderToExp(ExpressionContainer expr) { return Exp.exclusive(expressions.toArray(new Exp[0])); } + /** + * Processes an {@link ExpressionContainer} to generate the corresponding Exp. + * + * @param expr The expression to process + * @return The processed Exp + * @throws AerospikeDSLException if left or right operands are null in a binary expression + */ + private static Exp processExpression(ExpressionContainer expr) { + // For unary expressions + if (expr.isUnary()) { + Exp operandExp = processOperand(expr.getLeft()); + if (operandExp == null) return null; + + UnaryOperator operator = getUnaryExpOperator(expr.getOperationType()); + return operator.apply(operandExp); + } + + // For binary expressions + AbstractPart left = expr.getLeft(); + AbstractPart right = expr.getRight(); + if (left == null) { + throw new AerospikeDSLException("Unable to parse left operand"); + } + if (right == null) { + throw new AerospikeDSLException("Unable to parse right operand"); + } + + // Process operands + Exp leftExp = processOperand(left); + Exp rightExp = processOperand(right); + + // Special handling for BIN_PART + if (left.getPartType() == BIN_PART) { + return getExpLeftBinTypeComparison((BinPart) left, right, getExpOperator(expr.getOperationType())); + } else if (right.getPartType() == BIN_PART) { + return getExpRightBinTypeComparison(left, (BinPart) right, getExpOperator(expr.getOperationType())); + } + + // Special handling for AND operation + if (expr.getOperationType() == AND) { + if (leftExp == null) return rightExp; + if (rightExp == null) return leftExp; + } + + // Apply binary operator + BinaryOperator operator = getExpOperator(expr.getOperationType()); + return operator.apply(leftExp, rightExp); + } + + /** + * Processes an expression operand to generate its corresponding Aerospike {@link Exp}. + * If the operand is an {@link ExpressionContainer}, it recursively calls {@link #getFilterExp(ExpressionContainer)} + * to get the nested expression's {@link Exp}. Otherwise, it retrieves the {@link Exp} from the part itself. + * The generated {@link Exp} is set back on the {@link AbstractPart}. + * + * @param part The operand to process + * @return The processed Exp, or {@code null} if the part is null or represents + * an expression container that resulted in a null Exp + */ + private static Exp processOperand(AbstractPart part) { + if (part == null) return null; + + Exp exp; + if (part.getPartType() == EXPRESSION_CONTAINER) { + exp = getFilterExp((ExpressionContainer) part); + } else { + exp = part.getExp(); + } + part.setExp(exp); + return exp; + } + + /** + * This method that retrieves the {@link Exp} associated with an {@link AbstractPart}. + * If the part is an {@link ExpressionContainer}, it calls {@link #getFilterExp(ExpressionContainer)} + * to get the nested expression's {@link Exp}. Otherwise, it returns the {@link Exp} stored + * directly in the {@link AbstractPart}. + * + * @param part The {@link AbstractPart} for which to get the {@link Exp} + * @return The corresponding {@link Exp} or {@code null} + */ private static Exp getExp(AbstractPart part) { if (part.getPartType() == EXPRESSION_CONTAINER) { return getFilterExp((ExpressionContainer) part); @@ -739,188 +1106,195 @@ private static Exp getExp(AbstractPart part) { return part.getExp(); } + /** + * Attempts to generate a secondary index {@link Filter} for a given {@link ExpressionContainer}. + * If the expression is not an OR operation (which is not supported + * for secondary index filters), the method attempts to find the most suitable + * expression within the tree to apply a filter based on index availability and cardinality. + * + * @param expr The {@link ExpressionContainer} representing the expression tree + * @param namespace The namespace in use + * @param indexes A map of available secondary indexes, keyed by namespace and bin name + * @return A secondary index {@link Filter}, or {@code null} if no applicable filter can be generated + * @throws NoApplicableFilterException if the expression operation type is not supported + */ private static Filter getSIFilter(ExpressionContainer expr, String namespace, Map indexes) { // If it is an OR query if (expr.getOperationType() == OR) return null; - List exprs = flattenExprs(expr); - ExpressionContainer chosenExpr = chooseExprForFilter(exprs, namespace, indexes); - return chosenExpr == null ? null - : getFilterOrFail(chosenExpr.getLeft(), + ExpressionContainer chosenExpr = chooseExprForFilter(expr, namespace, indexes); + if (chosenExpr == null) return null; + return getFilterOrFail( + chosenExpr.getLeft(), chosenExpr.getRight(), getFilterOperation(chosenExpr.getOperationType()) ); } - private static ExpressionContainer chooseExprForFilter(List exprs, String namespace, Map indexes) { + /** + * Chooses the most suitable {@link ExpressionContainer} within a tree to apply a secondary index filter. + * Identifies all potential expressions within the tree that could + * utilize a secondary index. Selects the expression associated with the secondary index + * having the largest cardinality (highest ratio of unique + * bin values). If multiple expressions have the same largest cardinality, it + * chooses alphabetically based on the bin name. The chosen expression is marked + * as having a secondary index filter applied. + * + * @param exprContainer The root {@link ExpressionContainer} of the expression tree + * @param namespace The namespace in use + * @param indexes A map of available secondary indexes, keyed by namespace and bin name + * @return The chosen {@link ExpressionContainer} for secondary index filtering, + * or {@code null} if no suitable expression is found + */ + private static ExpressionContainer chooseExprForFilter(ExpressionContainer exprContainer, String namespace, + Map indexes) { if (indexes == null || indexes.isEmpty()) return null; - Map> exprsPerCardinality = new HashMap<>(); - for (ExpressionContainer expr : exprs) { - BinPart binPart = getBinPart(expr); - if (binPart == null) return null; // no bin found - Index index = indexes.get(namespace + INDEX_NAME_SEPARATOR + binPart.getBinName()); - if (index == null) continue; - if (expTypeToIndexType.get(binPart.getExpType()) == index.getIndexType()) { - List exprsList = exprsPerCardinality.get(index.getBinValuesRatio()); - if (exprsList != null) { - exprsList.add(expr); - } else { - exprsList = new ArrayList<>(); - exprsList.add(expr); - } - exprsPerCardinality.put(index.getBinValuesRatio(), exprsList); - } - } + Map> exprsPerCardinality = + getExpressionsPerCardinality(exprContainer, namespace, indexes); - // Find the entry with the largest key and put it in a new Map + // Find the entry with the largest key (cardinality) Map> largestCardinalityMap = exprsPerCardinality.entrySet().stream() .max(Map.Entry.comparingByKey()) .map(entry -> Map.of(entry.getKey(), entry.getValue())) .orElse(Collections.emptyMap()); - List largestCardinalityExprs = largestCardinalityMap.values().iterator().next(); + + List largestCardinalityExprs; + if (largestCardinalityMap.isEmpty()) return null; + largestCardinalityExprs = largestCardinalityMap.values().iterator().next(); + + ExpressionContainer chosenExpr; if (largestCardinalityExprs.size() > 1) { - // Choosing alphabetically - return largestCardinalityExprs.stream() - .min(Comparator.comparing(expr -> getBinPart(expr).getBinName())) + // Choosing alphabetically from a number of expressions + chosenExpr = largestCardinalityExprs.stream() + .min(Comparator.comparing(expr -> getBinPart(expr, 1).getBinName())) .orElse(null); + chosenExpr.hasSIndexFilter(true); + return chosenExpr; } - return largestCardinalityExprs.get(0); + // There is only one expression with the largest cardinality + chosenExpr = largestCardinalityExprs.get(0); + chosenExpr.hasSIndexFilter(true); + return chosenExpr; } - private static BinPart getBinPart(ExpressionContainer expr) { - BinPart result = null; - if (expr.getOperationType() == AND || expr.getOperationType() == OR) { - ExpressionContainer leftExpr = (ExpressionContainer) expr.getLeft(); - if (leftExpr.getLeft() != null && leftExpr.getLeft().getPartType() == EXPRESSION_CONTAINER) { - result = getBinPart(leftExpr); - if (result != null) return result; - } - - if (expr.getRight() != null && expr.getRight().getPartType() == EXPRESSION_CONTAINER) { - ExpressionContainer rightExpr = (ExpressionContainer) expr.getRight(); - if (rightExpr.getRight() != null && rightExpr.getRight().getPartType() == EXPRESSION_CONTAINER) { - result = getBinPart(rightExpr); - if (result != null) return result; - } - } - } else { - if (expr.getLeft() != null) { - if (expr.getLeft().getPartType() == BIN_PART) { - return (BinPart) expr.getLeft(); - } - if (expr.getLeft().getPartType() == EXPRESSION_CONTAINER) { - result = getBinPart((ExpressionContainer) expr.getLeft()); - if (result != null) return result; + /** + * Collects all {@link ExpressionContainer}s within an expression tree that + * correspond to a bin with a secondary index, grouped by the index's cardinality. + * + * @param exprContainer The root {@link ExpressionContainer} of the expression tree + * @param namespace The namespace in use + * @param indexes A map of available secondary indexes, keyed by namespace and bin name + * @return A map where keys are secondary index cardinalities (bin values ratio) + * and values are lists of {@link ExpressionContainer}s associated with bins + * having that cardinality + */ + private static Map> getExpressionsPerCardinality(ExpressionContainer exprContainer, + String namespace, + Map indexes) { + Map> exprsPerCardinality = new HashMap<>(); + final BinPart[] binPartPrev = {null}; + Consumer exprsPerCardinalityCollector = part -> { + if (part.getPartType() == EXPRESSION_CONTAINER) { + ExpressionContainer expr = (ExpressionContainer) part; + BinPart binPart = getBinPart(expr, 2); + + if (binPart == null) return; // no bin found + if (!binPart.equals(binPartPrev[0])) { + binPartPrev[0] = binPart; + } else { + return; // the same bin } - } - if (expr.getRight() != null) { - if (expr.getRight().getPartType() == BIN_PART) { - return (BinPart) expr.getRight(); - } - if (expr.getRight().getPartType() == EXPRESSION_CONTAINER) { - result = getBinPart((ExpressionContainer) expr.getRight()); - if (result != null) return result; + Index index = indexes.get(namespace + INDEX_NAME_SEPARATOR + binPart.getBinName()); + if (index == null) return; + if (expTypeToIndexType.get(binPart.getExpType()) == index.getIndexType()) { + List exprsList = exprsPerCardinality.get(index.getBinValuesRatio()); + if (exprsList != null) { + exprsList.add(expr); + } else { + exprsList = new ArrayList<>(); + exprsList.add(expr); + } + exprsPerCardinality.put(index.getBinValuesRatio(), exprsList); } } - } - return result; + }; + traverseTree(exprContainer, exprsPerCardinalityCollector, null); + return exprsPerCardinality; } - private static List flattenExprs(ExpressionContainer expr) { - List results = new ArrayList<>(); - if (expr.getOperationType() == AND || expr.getOperationType() == OR) { - if (expr.getLeft() != null && expr.getLeft().getPartType() == EXPRESSION_CONTAINER) { - ExpressionContainer leftExpr = (ExpressionContainer) expr.getLeft(); - if (leftExpr.getOperationType() == AND || leftExpr.getOperationType() == OR) { - Stream stream = flattenExprs(leftExpr).stream(); - results = Stream.concat(results.stream(), stream).toList(); - } else { - Stream stream = Stream.of(leftExpr); - results = Stream.concat(results.stream(), stream).toList(); - } + /** + * The method traverses the expression tree starting from the given {@link ExpressionContainer}, + * searching for a {@link BinPart}. It limits the search depth and stops + * traversing a branch if a logical expression (AND or OR) is found. + * + * @param expr The {@link ExpressionContainer} to start searching from + * @param depth The maximum depth to traverse + * @return The first {@link BinPart} found within the specified depth, or {@code null} if none is found + */ + private static BinPart getBinPart(ExpressionContainer expr, int depth) { + final BinPart[] singleBinPartArray = {null}; + Consumer binPartRetriever = part -> { + if (part.getPartType() == BIN_PART) { + singleBinPartArray[0] = (BinPart) part; } - - if (expr.getRight() != null && expr.getRight().getPartType() == EXPRESSION_CONTAINER) { - ExpressionContainer rightExpr = (ExpressionContainer) expr.getRight(); - if (rightExpr.getOperationType() == AND || rightExpr.getOperationType() == OR) { - Stream stream = flattenExprs(rightExpr).stream(); - results = Stream.concat(results.stream(), stream).toList(); - } else { - Stream stream = Stream.of(rightExpr); - results = Stream.concat(results.stream(), stream).toList(); - } + }; + Predicate stopOnLogicalExpr = part -> { + if (part.getPartType() == EXPRESSION_CONTAINER) { + ExpressionContainer logicalExpr = (ExpressionContainer) part; + return logicalExpr.getOperationType() == AND || logicalExpr.getOperationType() == OR; } - } else { - return List.of(expr); - } - return results; - } - - private static FilterOperationType getFilterOperation(ExpressionContainer.ExprPartsOperation exprPartsOperation) { - return switch (exprPartsOperation) { - case GT -> FilterOperationType.GT; - case GTEQ -> FilterOperationType.GTEQ; - case LT -> FilterOperationType.LT; - case LTEQ -> FilterOperationType.LTEQ; - case EQ -> FilterOperationType.EQ; - case NOTEQ -> FilterOperationType.NOTEQ; - default -> throw new NoApplicableFilterException("ExprPartsOperation has no matching FilterOperationType"); + return false; }; - } - private static BinaryOperator getExpOperator(ExpressionContainer.ExprPartsOperation exprPartsOperation) { - return switch (exprPartsOperation) { - case ADD -> Exp::add; - case SUB -> Exp::sub; - case MUL -> Exp::mul; - case DIV -> Exp::div; - case MOD -> Exp::mod; - case INT_XOR -> Exp::intXor; - case L_SHIFT -> Exp::lshift; - case R_SHIFT -> Exp::rshift; - case INT_AND -> Exp::intAnd; - case INT_OR -> Exp::intOr; - case AND -> Exp::and; - case OR -> Exp::or; - case EQ -> Exp::eq; - case NOTEQ -> Exp::ne; - case LT -> Exp::lt; - case LTEQ -> Exp::le; - case GT -> Exp::gt; - case GTEQ -> Exp::ge; - default -> throw new NoApplicableFilterException("ExprPartsOperation has no matching BinaryOperator"); - }; + traverseTree(expr, binPartRetriever, depth, stopOnLogicalExpr); + return singleBinPartArray[0]; } - private static UnaryOperator getUnaryExpOperator(ExpressionContainer.ExprPartsOperation exprPartsOperation) { - return switch (exprPartsOperation) { - case INT_NOT -> Exp::intNot; - case NOT -> Exp::not; - default -> throw new NoApplicableFilterException("ExprPartsOperation has no matching UnaryOperator"); - }; + /** + * Traverses the AbstractPart nodes tree and applies the visitor function to each node. + * Uses a pre-order traversal (root-left-right). + * The visitor function can be used to modify the node's state or to extract information. + * + * @param part The current node being visited (start with the root) + * @param visitor The function to apply to each AbstractPart node + * @param stopCondition The condition that causes stop of traversing + */ + public static void traverseTree(AbstractPart part, Consumer visitor, + Predicate stopCondition) { + traverseTree(part, visitor, Integer.MAX_VALUE, stopCondition); } - protected enum FilterOperationType { - GT, - GTEQ, - LT, - LTEQ, - EQ, - NOTEQ - } + /** + * Traverses the AbstractPart nodes tree and applies the visitor function to each node with limited depth. + * Uses a pre-order traversal (root-left-right). + * The visitor function can be used to modify the node's state or to extract information. + * + * @param part The current node being visited (start with the root) + * @param visitor The function to apply to each AbstractPart node + * @param depth The depth to limit traversing at + */ + public static void traverseTree(AbstractPart part, Consumer visitor, int depth, + Predicate stopCondition) { + if (part == null) return; + + // Stop if the depth limit is reached + if (depth < 0) { + return; + } - protected enum ArithmeticTermType { - ADDEND, - SUBTR, - MIN, - DIFFERENCE, - DIVIDEND, - DIVISOR, - QUOTIENT, - MULTIPLICAND, - MULTIPLIER, - PRODUCT + // Stop traversing this branch if the stop condition is met + if (stopCondition != null && stopCondition.test(part)) { + return; + } + + visitor.accept(part); + + if (part.getPartType() == EXPRESSION_CONTAINER && depth > 0) { + ExpressionContainer container = (ExpressionContainer) part; + traverseTree(container.getLeft(), visitor, depth - 1, stopCondition); + traverseTree(container.getRight(), visitor, depth - 1, stopCondition); + } } } diff --git a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java index ffdcbfe..5371e72 100644 --- a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java @@ -301,7 +301,7 @@ void mapComparison_constantOnLeftSide_NegativeTest() { Exp.eq(Exp.val(List.of("yes", "of course")), Exp.mapBin("mapBin1"))) ) .isInstanceOf(AerospikeDSLException.class) - .hasMessage("Cannot compare LIST to MAP"); + .hasMessage("Cannot compare MAP to LIST"); // Map key can only be Integer or String assertThatThrownBy(() -> diff --git a/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java b/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java index 3177f93..807696a 100644 --- a/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java +++ b/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java @@ -30,8 +30,7 @@ void binLogical_AND_2_all_indexes() { ); String namespace = "test1"; Filter filter = Filter.range("intBin2", 101, Long.MAX_VALUE); - Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), - Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); + Exp exp = Exp.gt(Exp.intBin("intBin1"), Exp.val(100)); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, IndexFilterInput.of(namespace, indexes)); } @@ -45,8 +44,7 @@ void binLogical_AND_2_all_indexes_no_cardinality() { String namespace = "test1"; // Filter is chosen alphabetically because no cardinality is given Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); - Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), - Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); + Exp exp = Exp.gt(Exp.intBin("intBin2"), Exp.val(100)); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, IndexFilterInput.of(namespace, indexes)); } @@ -57,8 +55,7 @@ void binLogical_AND_2_one_index() { Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build()); String namespace = "test1"; Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); - Exp exp = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), - Exp.gt(Exp.intBin("intBin2"), Exp.val(100))); + Exp exp = Exp.gt(Exp.intBin("intBin2"), Exp.val(100)); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, IndexFilterInput.of(namespace, indexes)); } @@ -73,9 +70,7 @@ void binLogical_AND_3_all_indexes() { String namespace = "test1"; Filter filter = Filter.range("intBin2", 101, Long.MAX_VALUE); Exp exp = Exp.and( - Exp.and( - Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), - Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), + Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, @@ -93,9 +88,7 @@ void binLogical_AND_3_all_indexes_same_cardinality() { // Filter is chosen alphabetically because the same cardinality is given Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); Exp exp = Exp.and( - Exp.and( - Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), - Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100)), Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, @@ -113,9 +106,7 @@ void binLogical_AND_3_all_indexes_no_cardinality() { // Filter is chosen alphabetically because no cardinality is given Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); Exp exp = Exp.and( - Exp.and( - Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), - Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), + Exp.gt(Exp.intBin("intBin2"), Exp.val(100)), Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, @@ -135,10 +126,8 @@ void binLogical_AND_3_all_indexes_partial_data() { // The only matching index with full data is for intBin3 Filter filter = Filter.range("intBin3", 101, Long.MAX_VALUE); Exp exp = Exp.and( - Exp.and( Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), - Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), - Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) + Exp.gt(Exp.intBin("intBin2"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, IndexFilterInput.of(namespace, indexes)); @@ -153,9 +142,7 @@ void binLogical_AND_3_two_indexes() { String namespace = "test1"; Filter filter = Filter.range("intBin2", 101, Long.MAX_VALUE); Exp exp = Exp.and( - Exp.and( - Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), - Exp.gt(Exp.intBin("intBin2"), Exp.val(100))), + Exp.gt(Exp.intBin("intBin1"), Exp.val(100)), Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, From 64c4890aabf533e9827eb91bb7ae2901e8428f5e Mon Sep 17 00:00:00 2001 From: agrgr Date: Sun, 4 May 2025 18:33:23 +0300 Subject: [PATCH 13/20] rename IndexFilterInput and Result, filter indexes by the given namespace, document exceptions --- .../java/com/aerospike/dsl/DSLParser.java | 4 +- .../java/com/aerospike/dsl/DSLParserImpl.java | 42 ++++--- ...ndexFilterInput.java => IndexContext.java} | 2 +- .../dsl/{Result.java => ParseResult.java} | 2 +- .../com/aerospike/dsl/ParsedExpression.java | 36 +++--- .../dsl/exception/AerospikeDSLException.java | 8 -- .../NoApplicableFilterException.java | 8 -- .../dsl/exceptions/AerospikeDSLException.java | 13 +++ .../NoApplicableFilterException.java | 18 +++ .../dsl/{part => parts}/AbstractPart.java | 2 +- .../{part => parts}/ExpressionContainer.java | 2 +- .../dsl/{part => parts}/cdt/CdtPart.java | 10 +- .../{part => parts}/cdt/list/ListIndex.java | 4 +- .../cdt/list/ListIndexRange.java | 6 +- .../{part => parts}/cdt/list/ListPart.java | 8 +- .../{part => parts}/cdt/list/ListRank.java | 4 +- .../cdt/list/ListRankRange.java | 6 +- .../cdt/list/ListRankRangeRelative.java | 6 +- .../cdt/list/ListTypeDesignator.java | 8 +- .../{part => parts}/cdt/list/ListValue.java | 4 +- .../cdt/list/ListValueList.java | 6 +- .../cdt/list/ListValueRange.java | 6 +- .../dsl/{part => parts}/cdt/map/MapIndex.java | 4 +- .../cdt/map/MapIndexRange.java | 6 +- .../cdt/map/MapIndexRangeRelative.java | 6 +- .../dsl/{part => parts}/cdt/map/MapKey.java | 6 +- .../{part => parts}/cdt/map/MapKeyList.java | 6 +- .../{part => parts}/cdt/map/MapKeyRange.java | 6 +- .../dsl/{part => parts}/cdt/map/MapPart.java | 6 +- .../dsl/{part => parts}/cdt/map/MapRank.java | 4 +- .../{part => parts}/cdt/map/MapRankRange.java | 6 +- .../cdt/map/MapRankRangeRelative.java | 6 +- .../cdt/map/MapTypeDesignator.java | 6 +- .../dsl/{part => parts}/cdt/map/MapValue.java | 4 +- .../{part => parts}/cdt/map/MapValueList.java | 6 +- .../cdt/map/MapValueRange.java | 6 +- .../controlstructure/ExclusiveStructure.java | 6 +- .../controlstructure/WhenStructure.java | 4 +- .../controlstructure/WithStructure.java | 6 +- .../operand/BooleanOperand.java | 4 +- .../{part => parts}/operand/FloatOperand.java | 4 +- .../{part => parts}/operand/IntOperand.java | 4 +- .../{part => parts}/operand/ListOperand.java | 4 +- .../{part => parts}/operand/MapOperand.java | 4 +- .../operand/MetadataOperand.java | 4 +- .../operand/ParsedValueOperand.java | 2 +- .../operand/StringOperand.java | 4 +- .../operand/VariableOperand.java | 4 +- .../{part => parts}/operand/WithOperand.java | 4 +- .../dsl/{part => parts}/path/BasePath.java | 4 +- .../dsl/{part => parts}/path/BinPart.java | 4 +- .../dsl/{part => parts}/path/Path.java | 6 +- .../{part => parts}/path/PathFunction.java | 4 +- .../com/aerospike/dsl/util/ParsingUtils.java | 2 +- .../aerospike/dsl/util/PathOperandUtils.java | 28 ++--- .../com/aerospike/dsl/util/TypeUtils.java | 6 +- .../aerospike/dsl/util/ValidationUtils.java | 2 +- .../visitor/ExpressionConditionVisitor.java | 40 +++---- .../aerospike/dsl/visitor/VisitorUtils.java | 104 +++++++++--------- .../ArithmeticExpressionsTests.java | 2 +- .../dsl/expression/BinExpressionsTests.java | 2 +- .../dsl/expression/CastingTests.java | 2 +- .../dsl/expression/ExplicitTypesTests.java | 2 +- .../dsl/expression/ListExpressionsTests.java | 2 +- .../expression/LogicalExpressionsTests.java | 2 +- .../dsl/expression/RecordMetadataTests.java | 2 +- .../dsl/filter/ArithmeticFiltersTests.java | 6 +- .../aerospike/dsl/filter/BinFiltersTests.java | 6 +- .../dsl/filter/ExplicitTypesFiltersTests.java | 6 +- .../LogicalParsedExpressionTests.java | 30 ++--- .../com/aerospike/dsl/util/TestUtils.java | 11 +- 71 files changed, 320 insertions(+), 290 deletions(-) rename src/main/java/com/aerospike/dsl/{IndexFilterInput.java => IndexContext.java} (95%) rename src/main/java/com/aerospike/dsl/{Result.java => ParseResult.java} (95%) delete mode 100644 src/main/java/com/aerospike/dsl/exception/AerospikeDSLException.java delete mode 100644 src/main/java/com/aerospike/dsl/exception/NoApplicableFilterException.java create mode 100644 src/main/java/com/aerospike/dsl/exceptions/AerospikeDSLException.java create mode 100644 src/main/java/com/aerospike/dsl/exceptions/NoApplicableFilterException.java rename src/main/java/com/aerospike/dsl/{part => parts}/AbstractPart.java (96%) rename src/main/java/com/aerospike/dsl/{part => parts}/ExpressionContainer.java (98%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/CdtPart.java (71%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/list/ListIndex.java (90%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/list/ListIndexRange.java (94%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/list/ListPart.java (85%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/list/ListRank.java (90%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/list/ListRankRange.java (94%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/list/ListRankRangeRelative.java (96%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/list/ListTypeDesignator.java (86%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/list/ListValue.java (95%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/list/ListValueList.java (94%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/list/ListValueRange.java (93%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapIndex.java (90%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapIndexRange.java (94%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapIndexRangeRelative.java (95%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapKey.java (89%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapKeyList.java (93%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapKeyRange.java (94%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapPart.java (90%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapRank.java (90%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapRankRange.java (94%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapRankRangeRelative.java (96%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapTypeDesignator.java (89%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapValue.java (95%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapValueList.java (93%) rename src/main/java/com/aerospike/dsl/{part => parts}/cdt/map/MapValueRange.java (93%) rename src/main/java/com/aerospike/dsl/{part => parts}/controlstructure/ExclusiveStructure.java (68%) rename src/main/java/com/aerospike/dsl/{part => parts}/controlstructure/WhenStructure.java (75%) rename src/main/java/com/aerospike/dsl/{part => parts}/controlstructure/WithStructure.java (66%) rename src/main/java/com/aerospike/dsl/{part => parts}/operand/BooleanOperand.java (80%) rename src/main/java/com/aerospike/dsl/{part => parts}/operand/FloatOperand.java (80%) rename src/main/java/com/aerospike/dsl/{part => parts}/operand/IntOperand.java (80%) rename src/main/java/com/aerospike/dsl/{part => parts}/operand/ListOperand.java (82%) rename src/main/java/com/aerospike/dsl/{part => parts}/operand/MapOperand.java (82%) rename src/main/java/com/aerospike/dsl/{part => parts}/operand/MetadataOperand.java (95%) rename src/main/java/com/aerospike/dsl/{part => parts}/operand/ParsedValueOperand.java (87%) rename src/main/java/com/aerospike/dsl/{part => parts}/operand/StringOperand.java (87%) rename src/main/java/com/aerospike/dsl/{part => parts}/operand/VariableOperand.java (81%) rename src/main/java/com/aerospike/dsl/{part => parts}/operand/WithOperand.java (87%) rename src/main/java/com/aerospike/dsl/{part => parts}/path/BasePath.java (90%) rename src/main/java/com/aerospike/dsl/{part => parts}/path/BinPart.java (84%) rename src/main/java/com/aerospike/dsl/{part => parts}/path/Path.java (93%) rename src/main/java/com/aerospike/dsl/{part => parts}/path/PathFunction.java (93%) diff --git a/src/main/java/com/aerospike/dsl/DSLParser.java b/src/main/java/com/aerospike/dsl/DSLParser.java index 06ecfb1..49db984 100644 --- a/src/main/java/com/aerospike/dsl/DSLParser.java +++ b/src/main/java/com/aerospike/dsl/DSLParser.java @@ -1,7 +1,7 @@ package com.aerospike.dsl; import com.aerospike.client.query.Filter; -import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.exceptions.AerospikeDSLException; /** * Contains API to convert dot separated String path into an Aerospike filter - @@ -161,5 +161,5 @@ public interface DSLParser { * @return {@link ParsedExpression} object * @throws AerospikeDSLException in case of or invalid syntax */ - ParsedExpression parseExpression(String dslString, IndexFilterInput indexFilterInput); + ParsedExpression parseExpression(String dslString, IndexContext indexFilterInput); } diff --git a/src/main/java/com/aerospike/dsl/DSLParserImpl.java b/src/main/java/com/aerospike/dsl/DSLParserImpl.java index a4fa58a..7bb36d0 100644 --- a/src/main/java/com/aerospike/dsl/DSLParserImpl.java +++ b/src/main/java/com/aerospike/dsl/DSLParserImpl.java @@ -1,22 +1,22 @@ package com.aerospike.dsl; import com.aerospike.dsl.annotation.Beta; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.exception.NoApplicableFilterException; -import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.NoApplicableFilterException; +import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.visitor.ExpressionConditionVisitor; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTree; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; public class DSLParserImpl implements DSLParser { - public static final String INDEX_NAME_SEPARATOR = "."; - @Beta public ParsedExpression parseExpression(String dslString) { ParseTree parseTree = getParseTree(dslString); @@ -24,7 +24,7 @@ public ParsedExpression parseExpression(String dslString) { } @Beta - public ParsedExpression parseExpression(String input, IndexFilterInput indexFilterInput) { + public ParsedExpression parseExpression(String input, IndexContext indexFilterInput) { ParseTree parseTree = getParseTree(input); return getParsedExpression(parseTree, indexFilterInput); } @@ -35,19 +35,33 @@ private ParseTree getParseTree(String input) { return parser.parse(); } - private ParsedExpression getParsedExpression(ParseTree parseTree, IndexFilterInput indexFilterInput) { + private ParsedExpression getParsedExpression(ParseTree parseTree, IndexContext indexContext) { + String namespace; + Collection indexes; + if (indexContext != null) { + namespace = indexContext.getNamespace(); + indexes = indexContext.getIndexes(); + } else { + namespace = null; + indexes = null; + } + boolean hasFilterParsingError = false; AbstractPart resultingPart = null; - Map indexesMap = new HashMap<>(); - String namespace = indexFilterInput == null ? null : indexFilterInput.getNamespace(); - Collection indexes = indexFilterInput == null ? null : indexFilterInput.getIndexes(); + Map> indexesMap = new HashMap<>(); if (indexes != null && !indexes.isEmpty()) { - indexes.forEach(idx -> indexesMap.put(idx.getNamespace() + INDEX_NAME_SEPARATOR + idx.getBin(), idx)); + indexes.forEach(idx -> { + // Filtering the indexes with the given namespace + if (idx.getNamespace() != null && idx.getNamespace().equals(namespace)) { + // Group the indexes by bin name + indexesMap.computeIfAbsent(idx.getBin(), k -> new ArrayList<>()).add(idx); + } + } + ); } try { - resultingPart = - new ExpressionConditionVisitor().visit(parseTree); + resultingPart = new ExpressionConditionVisitor().visit(parseTree); } catch (NoApplicableFilterException e) { hasFilterParsingError = true; } @@ -57,6 +71,6 @@ private ParsedExpression getParsedExpression(ParseTree parseTree, IndexFilterInp throw new AerospikeDSLException("Could not parse given input, wrong syntax"); } // Transfer the parsed tree along with namespace and indexes Map - return new ParsedExpression(resultingPart, namespace, indexesMap); + return new ParsedExpression(resultingPart, indexesMap); } } diff --git a/src/main/java/com/aerospike/dsl/IndexFilterInput.java b/src/main/java/com/aerospike/dsl/IndexContext.java similarity index 95% rename from src/main/java/com/aerospike/dsl/IndexFilterInput.java rename to src/main/java/com/aerospike/dsl/IndexContext.java index bba7a63..8229e26 100644 --- a/src/main/java/com/aerospike/dsl/IndexFilterInput.java +++ b/src/main/java/com/aerospike/dsl/IndexContext.java @@ -11,7 +11,7 @@ */ @AllArgsConstructor(staticName = "of") @Getter -public class IndexFilterInput { +public class IndexContext { /** * Namespace to be used for creating {@link Filter}. Is matched with namespace of indexes diff --git a/src/main/java/com/aerospike/dsl/Result.java b/src/main/java/com/aerospike/dsl/ParseResult.java similarity index 95% rename from src/main/java/com/aerospike/dsl/Result.java rename to src/main/java/com/aerospike/dsl/ParseResult.java index 97a46c1..398456d 100644 --- a/src/main/java/com/aerospike/dsl/Result.java +++ b/src/main/java/com/aerospike/dsl/ParseResult.java @@ -11,7 +11,7 @@ */ @AllArgsConstructor @Getter -public class Result { +public class ParseResult { /** * Secondary index {@link Filter}. Can be null in case of invalid or unsupported DSL string diff --git a/src/main/java/com/aerospike/dsl/ParsedExpression.java b/src/main/java/com/aerospike/dsl/ParsedExpression.java index d9487bb..66d48cd 100644 --- a/src/main/java/com/aerospike/dsl/ParsedExpression.java +++ b/src/main/java/com/aerospike/dsl/ParsedExpression.java @@ -1,36 +1,34 @@ package com.aerospike.dsl; 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.part.AbstractPart; -import com.aerospike.dsl.part.ExpressionContainer; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.AbstractPart; +import com.aerospike.dsl.parts.ExpressionContainer; import lombok.Getter; +import java.util.List; import java.util.Map; -import static com.aerospike.dsl.part.AbstractPart.PartType.EXPRESSION_CONTAINER; -import static com.aerospike.dsl.visitor.VisitorUtils.*; +import static com.aerospike.dsl.parts.AbstractPart.PartType.EXPRESSION_CONTAINER; +import static com.aerospike.dsl.visitor.VisitorUtils.buildExpr; /** - * A class to build and store the results of DSL expression parsing: secondary index {@link Filter} - * and/or filter {@link Exp} and {@link Expression}. + * A class to build and store the results of DSL expression parsing: {@link ParseResult} that holds + * a potential secondary index {@link Filter} and a potential filter {@link Exp}, and parsed {@code expressionTree}. */ @Beta @Getter public class ParsedExpression { private final AbstractPart expressionTree; - private final String namespace; - private final Map indexesMap; - private Result result; + private final Map> indexesMap; + private ParseResult result; - public ParsedExpression(AbstractPart expressionTree, String namespace, Map indexesMap) { + public ParsedExpression(AbstractPart expressionTree, Map> indexesMap) { this.expressionTree = expressionTree; - this.namespace = namespace; this.indexesMap = indexesMap; } @@ -39,24 +37,24 @@ public ParsedExpression(AbstractPart expressionTree, String namespace, MapThis exception is typically thrown when attempting to create a Filter for a DSL expression + * but the structure or types of the expression do not match any supported filtering patterns + * (e.g., comparing Strings using arithmetical operations, using OR-combined expression etc.). + * It signifies that while the expression might be valid in a broader context, it cannot be represented with a Filter. + */ +public class NoApplicableFilterException extends RuntimeException { + + public NoApplicableFilterException(String description) { + super(description); + } +} diff --git a/src/main/java/com/aerospike/dsl/part/AbstractPart.java b/src/main/java/com/aerospike/dsl/parts/AbstractPart.java similarity index 96% rename from src/main/java/com/aerospike/dsl/part/AbstractPart.java rename to src/main/java/com/aerospike/dsl/parts/AbstractPart.java index 37a0cd1..e0ae3c8 100644 --- a/src/main/java/com/aerospike/dsl/part/AbstractPart.java +++ b/src/main/java/com/aerospike/dsl/parts/AbstractPart.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.part; +package com.aerospike.dsl.parts; import com.aerospike.client.exp.Exp; import com.aerospike.client.query.Filter; diff --git a/src/main/java/com/aerospike/dsl/part/ExpressionContainer.java b/src/main/java/com/aerospike/dsl/parts/ExpressionContainer.java similarity index 98% rename from src/main/java/com/aerospike/dsl/part/ExpressionContainer.java rename to src/main/java/com/aerospike/dsl/parts/ExpressionContainer.java index 8d3548d..92e0a5c 100644 --- a/src/main/java/com/aerospike/dsl/part/ExpressionContainer.java +++ b/src/main/java/com/aerospike/dsl/parts/ExpressionContainer.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.part; +package com.aerospike.dsl.parts; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/CdtPart.java b/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java similarity index 71% rename from src/main/java/com/aerospike/dsl/part/cdt/CdtPart.java rename to src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java index 56373e1..dca3b44 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/CdtPart.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java @@ -1,11 +1,11 @@ -package com.aerospike.dsl.part.cdt; +package com.aerospike.dsl.parts.cdt; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.AbstractPart; -import com.aerospike.dsl.part.path.BasePath; -import com.aerospike.dsl.part.path.PathFunction; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.AbstractPart; +import com.aerospike.dsl.parts.path.BasePath; +import com.aerospike.dsl.parts.path.PathFunction; public abstract class CdtPart extends AbstractPart { diff --git a/src/main/java/com/aerospike/dsl/part/cdt/list/ListIndex.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndex.java similarity index 90% rename from src/main/java/com/aerospike/dsl/part/cdt/list/ListIndex.java rename to src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndex.java index c08431d..dbd6f56 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/list/ListIndex.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndex.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.part.cdt.list; +package com.aerospike.dsl.parts.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.parts.path.BasePath; public class ListIndex extends ListPart { private final int index; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/list/ListIndexRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java similarity index 94% rename from src/main/java/com/aerospike/dsl/part/cdt/list/ListIndexRange.java rename to src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java index 89216b7..4296407 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/list/ListIndexRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.list; +package com.aerospike.dsl.parts.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/list/ListPart.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java similarity index 85% rename from src/main/java/com/aerospike/dsl/part/cdt/list/ListPart.java rename to src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java index 111c5d5..db24095 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/list/ListPart.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java @@ -1,9 +1,9 @@ -package com.aerospike.dsl.part.cdt.list; +package com.aerospike.dsl.parts.cdt.list; import com.aerospike.client.cdt.ListReturnType; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.PathFunction; -import com.aerospike.dsl.part.cdt.CdtPart; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.PathFunction; +import com.aerospike.dsl.parts.cdt.CdtPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/part/cdt/list/ListRank.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRank.java similarity index 90% rename from src/main/java/com/aerospike/dsl/part/cdt/list/ListRank.java rename to src/main/java/com/aerospike/dsl/parts/cdt/list/ListRank.java index dd5e7d3..4e77d85 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/list/ListRank.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRank.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.part.cdt.list; +package com.aerospike.dsl.parts.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.parts.path.BasePath; public class ListRank extends ListPart { private final int rank; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/list/ListRankRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java similarity index 94% rename from src/main/java/com/aerospike/dsl/part/cdt/list/ListRankRange.java rename to src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java index 60c0a19..4d01f4f 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/list/ListRankRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.list; +package com.aerospike.dsl.parts.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/list/ListRankRangeRelative.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java similarity index 96% rename from src/main/java/com/aerospike/dsl/part/cdt/list/ListRankRangeRelative.java rename to src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java index 04b2508..3e88e16 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/list/ListRankRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.list; +package com.aerospike.dsl.parts.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/list/ListTypeDesignator.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListTypeDesignator.java similarity index 86% rename from src/main/java/com/aerospike/dsl/part/cdt/list/ListTypeDesignator.java rename to src/main/java/com/aerospike/dsl/parts/cdt/list/ListTypeDesignator.java index 8abfdfb..b8d7cb1 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/list/ListTypeDesignator.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListTypeDesignator.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.part.cdt.list; +package com.aerospike.dsl.parts.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.AbstractPart; -import com.aerospike.dsl.part.path.BasePath; -import com.aerospike.dsl.part.cdt.CdtPart; +import com.aerospike.dsl.parts.AbstractPart; +import com.aerospike.dsl.parts.path.BasePath; +import com.aerospike.dsl.parts.cdt.CdtPart; import java.util.Collections; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/list/ListValue.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValue.java similarity index 95% rename from src/main/java/com/aerospike/dsl/part/cdt/list/ListValue.java rename to src/main/java/com/aerospike/dsl/parts/cdt/list/ListValue.java index 7a4e43f..8cea8d2 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/list/ListValue.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValue.java @@ -1,11 +1,11 @@ -package com.aerospike.dsl.part.cdt.list; +package com.aerospike.dsl.parts.cdt.list; import com.aerospike.client.Value; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/list/ListValueList.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java similarity index 94% rename from src/main/java/com/aerospike/dsl/part/cdt/list/ListValueList.java rename to src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java index 8d57075..4c61ca0 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/list/ListValueList.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.list; +package com.aerospike.dsl.parts.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/list/ListValueRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java similarity index 93% rename from src/main/java/com/aerospike/dsl/part/cdt/list/ListValueRange.java rename to src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java index 22eb93e..7ff69cf 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/list/ListValueRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.list; +package com.aerospike.dsl.parts.cdt.list; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.ListReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; public class ListValueRange extends ListPart { private final boolean inverted; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapIndex.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndex.java similarity index 90% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapIndex.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndex.java index 01f774f..25dd0a4 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapIndex.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndex.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.parts.path.BasePath; public class MapIndex extends MapPart { private final int index; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapIndexRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java similarity index 94% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapIndexRange.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java index e9d42db..163796a 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapIndexRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapIndexRangeRelative.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java similarity index 95% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapIndexRangeRelative.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java index 3337130..57890b4 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapIndexRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapKey.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java similarity index 89% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapKey.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java index 3a57f6f..dd035b6 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapKey.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.Value; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapKeyList.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java similarity index 93% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapKeyList.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java index f6bf98e..baa1522 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapKeyList.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapKeyRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java similarity index 94% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapKeyRange.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java index f2e9fbe..ef84a11 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapKeyRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; import java.util.Optional; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapPart.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapPart.java similarity index 90% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapPart.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapPart.java index f969800..5550eba 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapPart.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapPart.java @@ -1,8 +1,8 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.cdt.MapReturnType; -import com.aerospike.dsl.part.path.PathFunction; -import com.aerospike.dsl.part.cdt.CdtPart; +import com.aerospike.dsl.parts.path.PathFunction; +import com.aerospike.dsl.parts.cdt.CdtPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapRank.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRank.java similarity index 90% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapRank.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapRank.java index 1e75c2d..9c84f13 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapRank.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRank.java @@ -1,10 +1,10 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.parts.path.BasePath; public class MapRank extends MapPart { private final int rank; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapRankRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java similarity index 94% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapRankRange.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java index 93d43a9..fd9d3c3 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapRankRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapRankRangeRelative.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java similarity index 96% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapRankRangeRelative.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java index 7d4cea6..db3aeca 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapRankRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapTypeDesignator.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapTypeDesignator.java similarity index 89% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapTypeDesignator.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapTypeDesignator.java index 70c94d7..226ba60 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapTypeDesignator.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapTypeDesignator.java @@ -1,9 +1,9 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.path.BasePath; -import com.aerospike.dsl.part.cdt.CdtPart; +import com.aerospike.dsl.parts.path.BasePath; +import com.aerospike.dsl.parts.cdt.CdtPart; /** * Designates that the element to the left is a Map. diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapValue.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValue.java similarity index 95% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapValue.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapValue.java index 26f1762..5ff7e9f 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapValue.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValue.java @@ -1,11 +1,11 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.Value; import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapValueList.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java similarity index 93% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapValueList.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java index c7ce146..4d96c5b 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapValueList.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/part/cdt/map/MapValueRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java similarity index 93% rename from src/main/java/com/aerospike/dsl/part/cdt/map/MapValueRange.java rename to src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java index 1348b5d..8f51700 100644 --- a/src/main/java/com/aerospike/dsl/part/cdt/map/MapValueRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java @@ -1,12 +1,12 @@ -package com.aerospike.dsl.part.cdt.map; +package com.aerospike.dsl.parts.cdt.map; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cdt.MapReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.part.path.BasePath; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.path.BasePath; public class MapValueRange extends MapPart { private final boolean inverted; diff --git a/src/main/java/com/aerospike/dsl/part/controlstructure/ExclusiveStructure.java b/src/main/java/com/aerospike/dsl/parts/controlstructure/ExclusiveStructure.java similarity index 68% rename from src/main/java/com/aerospike/dsl/part/controlstructure/ExclusiveStructure.java rename to src/main/java/com/aerospike/dsl/parts/controlstructure/ExclusiveStructure.java index 95cdabe..9be7857 100644 --- a/src/main/java/com/aerospike/dsl/part/controlstructure/ExclusiveStructure.java +++ b/src/main/java/com/aerospike/dsl/parts/controlstructure/ExclusiveStructure.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.part.controlstructure; +package com.aerospike.dsl.parts.controlstructure; -import com.aerospike.dsl.part.AbstractPart; -import com.aerospike.dsl.part.ExpressionContainer; +import com.aerospike.dsl.parts.AbstractPart; +import com.aerospike.dsl.parts.ExpressionContainer; import lombok.Getter; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/part/controlstructure/WhenStructure.java b/src/main/java/com/aerospike/dsl/parts/controlstructure/WhenStructure.java similarity index 75% rename from src/main/java/com/aerospike/dsl/part/controlstructure/WhenStructure.java rename to src/main/java/com/aerospike/dsl/parts/controlstructure/WhenStructure.java index 1e971d9..6849c9e 100644 --- a/src/main/java/com/aerospike/dsl/part/controlstructure/WhenStructure.java +++ b/src/main/java/com/aerospike/dsl/parts/controlstructure/WhenStructure.java @@ -1,6 +1,6 @@ -package com.aerospike.dsl.part.controlstructure; +package com.aerospike.dsl.parts.controlstructure; -import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.parts.AbstractPart; import lombok.Getter; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/part/controlstructure/WithStructure.java b/src/main/java/com/aerospike/dsl/parts/controlstructure/WithStructure.java similarity index 66% rename from src/main/java/com/aerospike/dsl/part/controlstructure/WithStructure.java rename to src/main/java/com/aerospike/dsl/parts/controlstructure/WithStructure.java index 892ef8a..6e1c413 100644 --- a/src/main/java/com/aerospike/dsl/part/controlstructure/WithStructure.java +++ b/src/main/java/com/aerospike/dsl/parts/controlstructure/WithStructure.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.part.controlstructure; +package com.aerospike.dsl.parts.controlstructure; -import com.aerospike.dsl.part.AbstractPart; -import com.aerospike.dsl.part.operand.WithOperand; +import com.aerospike.dsl.parts.AbstractPart; +import com.aerospike.dsl.parts.operand.WithOperand; import lombok.Getter; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/part/operand/BooleanOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/BooleanOperand.java similarity index 80% rename from src/main/java/com/aerospike/dsl/part/operand/BooleanOperand.java rename to src/main/java/com/aerospike/dsl/parts/operand/BooleanOperand.java index 0151aac..b98dc1c 100644 --- a/src/main/java/com/aerospike/dsl/part/operand/BooleanOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/BooleanOperand.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.part.operand; +package com.aerospike.dsl.parts.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.parts.AbstractPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/part/operand/FloatOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/FloatOperand.java similarity index 80% rename from src/main/java/com/aerospike/dsl/part/operand/FloatOperand.java rename to src/main/java/com/aerospike/dsl/parts/operand/FloatOperand.java index 11b4e47..f2a98a0 100644 --- a/src/main/java/com/aerospike/dsl/part/operand/FloatOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/FloatOperand.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.part.operand; +package com.aerospike.dsl.parts.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.parts.AbstractPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/part/operand/IntOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/IntOperand.java similarity index 80% rename from src/main/java/com/aerospike/dsl/part/operand/IntOperand.java rename to src/main/java/com/aerospike/dsl/parts/operand/IntOperand.java index 5a9e654..2ed5cdc 100644 --- a/src/main/java/com/aerospike/dsl/part/operand/IntOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/IntOperand.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.part.operand; +package com.aerospike.dsl.parts.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.parts.AbstractPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/part/operand/ListOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/ListOperand.java similarity index 82% rename from src/main/java/com/aerospike/dsl/part/operand/ListOperand.java rename to src/main/java/com/aerospike/dsl/parts/operand/ListOperand.java index a6b89ed..fb7c859 100644 --- a/src/main/java/com/aerospike/dsl/part/operand/ListOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/ListOperand.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.part.operand; +package com.aerospike.dsl.parts.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.parts.AbstractPart; import lombok.Getter; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/part/operand/MapOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/MapOperand.java similarity index 82% rename from src/main/java/com/aerospike/dsl/part/operand/MapOperand.java rename to src/main/java/com/aerospike/dsl/parts/operand/MapOperand.java index 2304a74..aa640a8 100644 --- a/src/main/java/com/aerospike/dsl/part/operand/MapOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/MapOperand.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.part.operand; +package com.aerospike.dsl.parts.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.parts.AbstractPart; import lombok.Getter; import java.util.TreeMap; diff --git a/src/main/java/com/aerospike/dsl/part/operand/MetadataOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/MetadataOperand.java similarity index 95% rename from src/main/java/com/aerospike/dsl/part/operand/MetadataOperand.java rename to src/main/java/com/aerospike/dsl/parts/operand/MetadataOperand.java index ada28ed..ba88c92 100644 --- a/src/main/java/com/aerospike/dsl/part/operand/MetadataOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/MetadataOperand.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.part.operand; +package com.aerospike.dsl.parts.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.ExpressionContainer; +import com.aerospike.dsl.parts.ExpressionContainer; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/part/operand/ParsedValueOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/ParsedValueOperand.java similarity index 87% rename from src/main/java/com/aerospike/dsl/part/operand/ParsedValueOperand.java rename to src/main/java/com/aerospike/dsl/parts/operand/ParsedValueOperand.java index 89b405f..d479108 100644 --- a/src/main/java/com/aerospike/dsl/part/operand/ParsedValueOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/ParsedValueOperand.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.part.operand; +package com.aerospike.dsl.parts.operand; /** * This interface provides an abstraction for an operand that returns a single value to be used for constructing diff --git a/src/main/java/com/aerospike/dsl/part/operand/StringOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/StringOperand.java similarity index 87% rename from src/main/java/com/aerospike/dsl/part/operand/StringOperand.java rename to src/main/java/com/aerospike/dsl/parts/operand/StringOperand.java index aa6eb76..6ecd067 100644 --- a/src/main/java/com/aerospike/dsl/part/operand/StringOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/StringOperand.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.part.operand; +package com.aerospike.dsl.parts.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.parts.AbstractPart; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/aerospike/dsl/part/operand/VariableOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/VariableOperand.java similarity index 81% rename from src/main/java/com/aerospike/dsl/part/operand/VariableOperand.java rename to src/main/java/com/aerospike/dsl/parts/operand/VariableOperand.java index f046b3f..a065422 100644 --- a/src/main/java/com/aerospike/dsl/part/operand/VariableOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/VariableOperand.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.part.operand; +package com.aerospike.dsl.parts.operand; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.parts.AbstractPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/part/operand/WithOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/WithOperand.java similarity index 87% rename from src/main/java/com/aerospike/dsl/part/operand/WithOperand.java rename to src/main/java/com/aerospike/dsl/parts/operand/WithOperand.java index 44b05ef..1611e4f 100644 --- a/src/main/java/com/aerospike/dsl/part/operand/WithOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/WithOperand.java @@ -1,6 +1,6 @@ -package com.aerospike.dsl.part.operand; +package com.aerospike.dsl.parts.operand; -import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.parts.AbstractPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/part/path/BasePath.java b/src/main/java/com/aerospike/dsl/parts/path/BasePath.java similarity index 90% rename from src/main/java/com/aerospike/dsl/part/path/BasePath.java rename to src/main/java/com/aerospike/dsl/parts/path/BasePath.java index 13250f9..d5b39cd 100644 --- a/src/main/java/com/aerospike/dsl/part/path/BasePath.java +++ b/src/main/java/com/aerospike/dsl/parts/path/BasePath.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.part.path; +package com.aerospike.dsl.parts.path; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.parts.AbstractPart; import lombok.Getter; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/part/path/BinPart.java b/src/main/java/com/aerospike/dsl/parts/path/BinPart.java similarity index 84% rename from src/main/java/com/aerospike/dsl/part/path/BinPart.java rename to src/main/java/com/aerospike/dsl/parts/path/BinPart.java index 48d2dae..7d78ded 100644 --- a/src/main/java/com/aerospike/dsl/part/path/BinPart.java +++ b/src/main/java/com/aerospike/dsl/parts/path/BinPart.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.part.path; +package com.aerospike.dsl.parts.path; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.ExpressionContainer; +import com.aerospike.dsl.parts.ExpressionContainer; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/part/path/Path.java b/src/main/java/com/aerospike/dsl/parts/path/Path.java similarity index 93% rename from src/main/java/com/aerospike/dsl/part/path/Path.java rename to src/main/java/com/aerospike/dsl/parts/path/Path.java index 50be659..97e6339 100644 --- a/src/main/java/com/aerospike/dsl/part/path/Path.java +++ b/src/main/java/com/aerospike/dsl/parts/path/Path.java @@ -1,8 +1,8 @@ -package com.aerospike.dsl.part.path; +package com.aerospike.dsl.parts.path; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.AbstractPart; -import com.aerospike.dsl.part.cdt.CdtPart; +import com.aerospike.dsl.parts.AbstractPart; +import com.aerospike.dsl.parts.cdt.CdtPart; import lombok.Getter; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/part/path/PathFunction.java b/src/main/java/com/aerospike/dsl/parts/path/PathFunction.java similarity index 93% rename from src/main/java/com/aerospike/dsl/part/path/PathFunction.java rename to src/main/java/com/aerospike/dsl/parts/path/PathFunction.java index f0d8260..0e7291f 100644 --- a/src/main/java/com/aerospike/dsl/part/path/PathFunction.java +++ b/src/main/java/com/aerospike/dsl/parts/path/PathFunction.java @@ -1,7 +1,7 @@ -package com.aerospike.dsl.part.path; +package com.aerospike.dsl.parts.path; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.AbstractPart; +import com.aerospike.dsl.parts.AbstractPart; import lombok.Getter; @Getter diff --git a/src/main/java/com/aerospike/dsl/util/ParsingUtils.java b/src/main/java/com/aerospike/dsl/util/ParsingUtils.java index 3db3f25..3866c18 100644 --- a/src/main/java/com/aerospike/dsl/util/ParsingUtils.java +++ b/src/main/java/com/aerospike/dsl/util/ParsingUtils.java @@ -1,6 +1,6 @@ package com.aerospike.dsl.util; -import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.exceptions.AerospikeDSLException; import lombok.NonNull; import lombok.experimental.UtilityClass; diff --git a/src/main/java/com/aerospike/dsl/util/PathOperandUtils.java b/src/main/java/com/aerospike/dsl/util/PathOperandUtils.java index d0290d0..3da3d49 100644 --- a/src/main/java/com/aerospike/dsl/util/PathOperandUtils.java +++ b/src/main/java/com/aerospike/dsl/util/PathOperandUtils.java @@ -4,26 +4,26 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.client.exp.MapExp; -import com.aerospike.dsl.part.AbstractPart; -import com.aerospike.dsl.part.path.BasePath; -import com.aerospike.dsl.part.path.BinPart; -import com.aerospike.dsl.part.path.PathFunction; -import com.aerospike.dsl.part.cdt.CdtPart; -import com.aerospike.dsl.part.cdt.list.ListPart; -import com.aerospike.dsl.part.cdt.list.ListTypeDesignator; -import com.aerospike.dsl.part.cdt.map.MapPart; -import com.aerospike.dsl.part.cdt.map.MapTypeDesignator; +import com.aerospike.dsl.parts.AbstractPart; +import com.aerospike.dsl.parts.path.BasePath; +import com.aerospike.dsl.parts.path.BinPart; +import com.aerospike.dsl.parts.path.PathFunction; +import com.aerospike.dsl.parts.cdt.CdtPart; +import com.aerospike.dsl.parts.cdt.list.ListPart; +import com.aerospike.dsl.parts.cdt.list.ListTypeDesignator; +import com.aerospike.dsl.parts.cdt.map.MapPart; +import com.aerospike.dsl.parts.cdt.map.MapTypeDesignator; import lombok.experimental.UtilityClass; import java.util.ArrayList; import java.util.List; import java.util.function.UnaryOperator; -import static com.aerospike.dsl.part.AbstractPart.PartType.LIST_PART; -import static com.aerospike.dsl.part.AbstractPart.PartType.MAP_PART; -import static com.aerospike.dsl.part.path.PathFunction.PathFunctionType.*; -import static com.aerospike.dsl.part.cdt.list.ListPart.ListPartType.*; -import static com.aerospike.dsl.part.cdt.map.MapPart.MapPartType.MAP_TYPE_DESIGNATOR; +import static com.aerospike.dsl.parts.AbstractPart.PartType.LIST_PART; +import static com.aerospike.dsl.parts.AbstractPart.PartType.MAP_PART; +import static com.aerospike.dsl.parts.path.PathFunction.PathFunctionType.*; +import static com.aerospike.dsl.parts.cdt.list.ListPart.ListPartType.*; +import static com.aerospike.dsl.parts.cdt.map.MapPart.MapPartType.MAP_TYPE_DESIGNATOR; @UtilityClass public class PathOperandUtils { diff --git a/src/main/java/com/aerospike/dsl/util/TypeUtils.java b/src/main/java/com/aerospike/dsl/util/TypeUtils.java index 32a2c38..ac8ea38 100644 --- a/src/main/java/com/aerospike/dsl/util/TypeUtils.java +++ b/src/main/java/com/aerospike/dsl/util/TypeUtils.java @@ -1,9 +1,9 @@ package com.aerospike.dsl.util; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.part.AbstractPart; -import com.aerospike.dsl.part.cdt.map.MapPart; -import com.aerospike.dsl.part.cdt.map.MapTypeDesignator; +import com.aerospike.dsl.parts.AbstractPart; +import com.aerospike.dsl.parts.cdt.map.MapPart; +import com.aerospike.dsl.parts.cdt.map.MapTypeDesignator; import lombok.experimental.UtilityClass; @UtilityClass diff --git a/src/main/java/com/aerospike/dsl/util/ValidationUtils.java b/src/main/java/com/aerospike/dsl/util/ValidationUtils.java index f79bbee..a6f188e 100644 --- a/src/main/java/com/aerospike/dsl/util/ValidationUtils.java +++ b/src/main/java/com/aerospike/dsl/util/ValidationUtils.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.util; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.exceptions.AerospikeDSLException; import lombok.experimental.UtilityClass; @UtilityClass diff --git a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java index faf38e1..9571fa7 100644 --- a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java +++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java @@ -3,26 +3,26 @@ 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.part.*; -import com.aerospike.dsl.part.cdt.list.ListIndex; -import com.aerospike.dsl.part.cdt.list.ListIndexRange; -import com.aerospike.dsl.part.cdt.list.ListRank; -import com.aerospike.dsl.part.cdt.list.ListRankRange; -import com.aerospike.dsl.part.cdt.list.ListRankRangeRelative; -import com.aerospike.dsl.part.cdt.list.ListTypeDesignator; -import com.aerospike.dsl.part.cdt.list.ListValue; -import com.aerospike.dsl.part.cdt.list.ListValueList; -import com.aerospike.dsl.part.cdt.list.ListValueRange; -import com.aerospike.dsl.part.cdt.map.*; -import com.aerospike.dsl.part.operand.*; -import com.aerospike.dsl.part.controlstructure.ExclusiveStructure; -import com.aerospike.dsl.part.controlstructure.WhenStructure; -import com.aerospike.dsl.part.controlstructure.WithStructure; -import com.aerospike.dsl.part.path.BasePath; -import com.aerospike.dsl.part.path.BinPart; -import com.aerospike.dsl.part.path.Path; -import com.aerospike.dsl.part.path.PathFunction; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.parts.*; +import com.aerospike.dsl.parts.cdt.list.ListIndex; +import com.aerospike.dsl.parts.cdt.list.ListIndexRange; +import com.aerospike.dsl.parts.cdt.list.ListRank; +import com.aerospike.dsl.parts.cdt.list.ListRankRange; +import com.aerospike.dsl.parts.cdt.list.ListRankRangeRelative; +import com.aerospike.dsl.parts.cdt.list.ListTypeDesignator; +import com.aerospike.dsl.parts.cdt.list.ListValue; +import com.aerospike.dsl.parts.cdt.list.ListValueList; +import com.aerospike.dsl.parts.cdt.list.ListValueRange; +import com.aerospike.dsl.parts.cdt.map.*; +import com.aerospike.dsl.parts.operand.*; +import com.aerospike.dsl.parts.controlstructure.ExclusiveStructure; +import com.aerospike.dsl.parts.controlstructure.WhenStructure; +import com.aerospike.dsl.parts.controlstructure.WithStructure; +import com.aerospike.dsl.parts.path.BasePath; +import com.aerospike.dsl.parts.path.BinPart; +import com.aerospike.dsl.parts.path.Path; +import com.aerospike.dsl.parts.path.PathFunction; import com.aerospike.dsl.util.TypeUtils; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.RuleNode; diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index 45b2db0..ef1fed8 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -5,19 +5,19 @@ import com.aerospike.client.query.IndexType; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.Index; -import com.aerospike.dsl.exception.AerospikeDSLException; -import com.aerospike.dsl.exception.NoApplicableFilterException; -import com.aerospike.dsl.part.AbstractPart; -import com.aerospike.dsl.part.ExpressionContainer; -import com.aerospike.dsl.part.ExpressionContainer.ExprPartsOperation; -import com.aerospike.dsl.part.controlstructure.ExclusiveStructure; -import com.aerospike.dsl.part.controlstructure.WhenStructure; -import com.aerospike.dsl.part.controlstructure.WithStructure; -import com.aerospike.dsl.part.operand.IntOperand; -import com.aerospike.dsl.part.operand.MetadataOperand; -import com.aerospike.dsl.part.operand.StringOperand; -import com.aerospike.dsl.part.operand.WithOperand; -import com.aerospike.dsl.part.path.BinPart; +import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.NoApplicableFilterException; +import com.aerospike.dsl.parts.AbstractPart; +import com.aerospike.dsl.parts.ExpressionContainer; +import com.aerospike.dsl.parts.ExpressionContainer.ExprPartsOperation; +import com.aerospike.dsl.parts.controlstructure.ExclusiveStructure; +import com.aerospike.dsl.parts.controlstructure.WhenStructure; +import com.aerospike.dsl.parts.controlstructure.WithStructure; +import com.aerospike.dsl.parts.operand.IntOperand; +import com.aerospike.dsl.parts.operand.MetadataOperand; +import com.aerospike.dsl.parts.operand.StringOperand; +import com.aerospike.dsl.parts.operand.WithOperand; +import com.aerospike.dsl.parts.path.BinPart; import lombok.experimental.UtilityClass; import org.antlr.v4.runtime.misc.Pair; import org.antlr.v4.runtime.tree.ParseTree; @@ -35,15 +35,14 @@ import java.util.function.Predicate; import java.util.function.UnaryOperator; -import static com.aerospike.dsl.part.AbstractPart.PartType.*; -import static com.aerospike.dsl.part.ExpressionContainer.ExprPartsOperation.*; +import static com.aerospike.dsl.parts.AbstractPart.PartType.*; +import static com.aerospike.dsl.parts.ExpressionContainer.ExprPartsOperation.*; import static com.aerospike.dsl.util.ValidationUtils.validateComparableTypes; import static com.aerospike.dsl.visitor.VisitorUtils.ArithmeticTermType.*; @UtilityClass public class VisitorUtils { - public final String INDEX_NAME_SEPARATOR = "."; private final Map expTypeToIndexType = Map.of( Exp.Type.INT, IndexType.NUMERIC, Exp.Type.STRING, IndexType.STRING, @@ -226,6 +225,7 @@ static void logicalSetBinAsBooleanExpr(ExpressionContainer expr) { * @return {@code true} if the child should be visited as a list element, {@code false} otherwise */ static boolean shouldVisitListElement(int i, int size, ParseTree child) { + //noinspection GrazieInspection return size > 0 // size is not 0 && i != 0 // not the first element ('[') && i != size - 1 // not the last element (']') @@ -242,6 +242,7 @@ static boolean shouldVisitListElement(int i, int size, ParseTree child) { * @return {@code true} if the child should be visited as a map element, {@code false} otherwise */ static boolean shouldVisitMapElement(int i, int size, ParseTree child) { + //noinspection GrazieInspection return size > 0 // size is not 0 && i != 0 // not the first element ('{') && i != size - 1 // not the last element ('}') @@ -925,17 +926,16 @@ private static FilterOperationType invertType(FilterOperationType type) { * Builds a secondary index {@link Filter} and a filter {@link Exp} for a given {@link ExpressionContainer}. * This is the main entry point for enriching the parsed expression tree with query filters. * - * @param expr The {@link ExpressionContainer} representing the expression tree - * @param namespace The namespace in use - * @param indexes A map of available secondary indexes, keyed by namespace and bin name + * @param expr The {@link ExpressionContainer} representing the expression tree + * @param indexes A map of available secondary indexes, keyed by bin name * @return The updated {@link ExpressionContainer} with the generated {@link Filter} and {@link Exp}. * Either of them can be null if there is no suitable filter */ - public static AbstractPart buildExpr(ExpressionContainer expr, String namespace, Map indexes) { + public static AbstractPart buildExpr(ExpressionContainer expr, Map> indexes) { Exp exp; Filter sIndexFilter = null; try { - sIndexFilter = getSIFilter(expr, namespace, indexes); + sIndexFilter = getSIFilter(expr, indexes); } catch (NoApplicableFilterException ignored) { } expr.setFilter(sIndexFilter); @@ -1112,17 +1112,16 @@ private static Exp getExp(AbstractPart part) { * for secondary index filters), the method attempts to find the most suitable * expression within the tree to apply a filter based on index availability and cardinality. * - * @param expr The {@link ExpressionContainer} representing the expression tree - * @param namespace The namespace in use - * @param indexes A map of available secondary indexes, keyed by namespace and bin name + * @param expr The {@link ExpressionContainer} representing the expression tree + * @param indexes A map of available secondary indexes, keyed by bin name * @return A secondary index {@link Filter}, or {@code null} if no applicable filter can be generated * @throws NoApplicableFilterException if the expression operation type is not supported */ - private static Filter getSIFilter(ExpressionContainer expr, String namespace, Map indexes) { + private static Filter getSIFilter(ExpressionContainer expr, Map> indexes) { // If it is an OR query if (expr.getOperationType() == OR) return null; - ExpressionContainer chosenExpr = chooseExprForFilter(expr, namespace, indexes); + ExpressionContainer chosenExpr = chooseExprForFilter(expr, indexes); if (chosenExpr == null) return null; return getFilterOrFail( chosenExpr.getLeft(), @@ -1141,17 +1140,16 @@ private static Filter getSIFilter(ExpressionContainer expr, String namespace, Ma * as having a secondary index filter applied. * * @param exprContainer The root {@link ExpressionContainer} of the expression tree - * @param namespace The namespace in use - * @param indexes A map of available secondary indexes, keyed by namespace and bin name + * @param indexes A map of available secondary indexes, keyed by bin name * @return The chosen {@link ExpressionContainer} for secondary index filtering, * or {@code null} if no suitable expression is found */ - private static ExpressionContainer chooseExprForFilter(ExpressionContainer exprContainer, String namespace, - Map indexes) { + private static ExpressionContainer chooseExprForFilter(ExpressionContainer exprContainer, + Map> indexes) { if (indexes == null || indexes.isEmpty()) return null; Map> exprsPerCardinality = - getExpressionsPerCardinality(exprContainer, namespace, indexes); + getExpressionsPerCardinality(exprContainer, indexes); // Find the entry with the largest key (cardinality) Map> largestCardinalityMap = exprsPerCardinality.entrySet().stream() @@ -1183,15 +1181,13 @@ private static ExpressionContainer chooseExprForFilter(ExpressionContainer exprC * correspond to a bin with a secondary index, grouped by the index's cardinality. * * @param exprContainer The root {@link ExpressionContainer} of the expression tree - * @param namespace The namespace in use - * @param indexes A map of available secondary indexes, keyed by namespace and bin name + * @param indexes A map of available secondary indexes, keyed by bin name * @return A map where keys are secondary index cardinalities (bin values ratio) * and values are lists of {@link ExpressionContainer}s associated with bins * having that cardinality */ private static Map> getExpressionsPerCardinality(ExpressionContainer exprContainer, - String namespace, - Map indexes) { + Map> indexes) { Map> exprsPerCardinality = new HashMap<>(); final BinPart[] binPartPrev = {null}; Consumer exprsPerCardinalityCollector = part -> { @@ -1206,28 +1202,38 @@ private static Map> getExpressionsPerCardinal return; // the same bin } - Index index = indexes.get(namespace + INDEX_NAME_SEPARATOR + binPart.getBinName()); - if (index == null) return; - if (expTypeToIndexType.get(binPart.getExpType()) == index.getIndexType()) { - List exprsList = exprsPerCardinality.get(index.getBinValuesRatio()); - if (exprsList != null) { - exprsList.add(expr); - } else { - exprsList = new ArrayList<>(); - exprsList.add(expr); - } - exprsPerCardinality.put(index.getBinValuesRatio(), exprsList); - } + updateExpressionsPerCardinality(exprsPerCardinality, expr, binPart, indexes); } }; traverseTree(exprContainer, exprsPerCardinalityCollector, null); return exprsPerCardinality; } + private static void updateExpressionsPerCardinality(Map> exprsPerCardinality, + ExpressionContainer expr, BinPart binPart, + Map> indexes) { + List indexesByBin = indexes.get(binPart.getBinName()); + if (indexesByBin == null || indexesByBin.isEmpty()) return; + + for (Index idx : indexesByBin) { + // Iterate over all indexes for the same bin + if (expTypeToIndexType.get(binPart.getExpType()) == idx.getIndexType()) { + List exprsList = exprsPerCardinality.get(idx.getBinValuesRatio()); + if (exprsList != null) { + exprsList.add(expr); + } else { + exprsList = new ArrayList<>(); + exprsList.add(expr); + } + exprsPerCardinality.put(idx.getBinValuesRatio(), exprsList); + } + } + } + /** * The method traverses the expression tree starting from the given {@link ExpressionContainer}, * searching for a {@link BinPart}. It limits the search depth and stops - * traversing a branch if a logical expression (AND or OR) is found. + * traversing a branch if a logical expression (AND / OR) is found. * * @param expr The {@link ExpressionContainer} to start searching from * @param depth The maximum depth to traverse @@ -1254,7 +1260,7 @@ private static BinPart getBinPart(ExpressionContainer expr, int depth) { /** * Traverses the AbstractPart nodes tree and applies the visitor function to each node. - * Uses a pre-order traversal (root-left-right). + * Uses a pre-order traversal (top-down, root-left-right). * The visitor function can be used to modify the node's state or to extract information. * * @param part The current node being visited (start with the root) diff --git a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java index 826f63b..580d033 100644 --- a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.exceptions.AerospikeDSLException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; diff --git a/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java index 39033ab..8289f35 100644 --- a/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.exceptions.AerospikeDSLException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; diff --git a/src/test/java/com/aerospike/dsl/expression/CastingTests.java b/src/test/java/com/aerospike/dsl/expression/CastingTests.java index 75a1848..423fa25 100644 --- a/src/test/java/com/aerospike/dsl/expression/CastingTests.java +++ b/src/test/java/com/aerospike/dsl/expression/CastingTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.exceptions.AerospikeDSLException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; diff --git a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java index 5371e72..d1f3a7b 100644 --- a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.exceptions.AerospikeDSLException; import org.junit.jupiter.api.Test; import java.util.Base64; diff --git a/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java index 06ef10e..c9fb665 100644 --- a/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java @@ -4,7 +4,7 @@ import com.aerospike.client.cdt.ListReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; -import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.exceptions.AerospikeDSLException; import org.junit.jupiter.api.Test; import java.util.List; diff --git a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java index fe4bc97..dfa3306 100644 --- a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.exceptions.AerospikeDSLException; import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; diff --git a/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java index 9c99f09..d023b2e 100644 --- a/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java +++ b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.exceptions.AerospikeDSLException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; diff --git a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java index 88ede8d..e3d5191 100644 --- a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java @@ -3,8 +3,8 @@ import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.dsl.Index; -import com.aerospike.dsl.IndexFilterInput; -import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.IndexContext; +import com.aerospike.dsl.exceptions.AerospikeDSLException; import org.junit.jupiter.api.Test; import java.util.Collection; @@ -22,7 +22,7 @@ public class ArithmeticFiltersTests { Index.builder().namespace("test1").bin("apples").indexType(IndexType.NUMERIC).binValuesRatio(1).build(), Index.builder().namespace("test1").bin("bananas").indexType(IndexType.NUMERIC).binValuesRatio(1).build() ); - IndexFilterInput INDEX_FILTER_INPUT = IndexFilterInput.of(NAMESPACE, INDEXES); + IndexContext INDEX_FILTER_INPUT = IndexContext.of(NAMESPACE, INDEXES); @Test void add() { diff --git a/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java index 4108ecd..091cc94 100644 --- a/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java @@ -3,7 +3,7 @@ import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.dsl.Index; -import com.aerospike.dsl.IndexFilterInput; +import com.aerospike.dsl.IndexContext; import org.junit.jupiter.api.Test; import java.util.List; @@ -19,7 +19,7 @@ class BinFiltersTests { Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(1).build(), Index.builder().namespace("test1").bin("stringBin1").indexType(IndexType.STRING).binValuesRatio(1).build() ); - IndexFilterInput INDEX_FILTER_INPUT = IndexFilterInput.of(NAMESPACE, INDEXES); + IndexContext INDEX_FILTER_INPUT = IndexContext.of(NAMESPACE, INDEXES); @Test void binGT() { @@ -47,7 +47,7 @@ void binGT_logical_combinations() { Index.builder().namespace("test1").bin("intBin1").indexType(IndexType.NUMERIC).binValuesRatio(0).build(), Index.builder().namespace("test1").bin("intBin2").indexType(IndexType.NUMERIC).binValuesRatio(1).build() ); - parseFilterAndCompare("$.intBin1 > 100 and $.intBin2 < 1000", IndexFilterInput.of(NAMESPACE, indexes), + parseFilterAndCompare("$.intBin1 > 100 and $.intBin2 < 1000", IndexContext.of(NAMESPACE, indexes), Filter.range("intBin2", Long.MIN_VALUE, 999)); parseFilterAndCompare("$.intBin1 > 100 and $.intBin2 < 1000", diff --git a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java index 95922a1..22414bf 100644 --- a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java @@ -3,8 +3,8 @@ import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.dsl.Index; -import com.aerospike.dsl.IndexFilterInput; -import com.aerospike.dsl.exception.AerospikeDSLException; +import com.aerospike.dsl.IndexContext; +import com.aerospike.dsl.exceptions.AerospikeDSLException; import com.aerospike.dsl.util.TestUtils; import org.junit.jupiter.api.Test; @@ -23,7 +23,7 @@ public class ExplicitTypesFiltersTests { Index.builder().namespace("test1").bin("stringBin1").indexType(IndexType.STRING).binValuesRatio(1).build(), Index.builder().namespace("test1").bin("blobBin1").indexType(IndexType.BLOB).binValuesRatio(1).build() ); - IndexFilterInput INDEX_FILTER_INPUT = IndexFilterInput.of(NAMESPACE, INDEXES); + IndexContext INDEX_FILTER_INPUT = IndexContext.of(NAMESPACE, INDEXES); @Test void integerComparison() { diff --git a/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java b/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java index 807696a..9b545df 100644 --- a/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java +++ b/src/test/java/com/aerospike/dsl/parsedExpression/LogicalParsedExpressionTests.java @@ -4,7 +4,7 @@ import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.dsl.Index; -import com.aerospike.dsl.IndexFilterInput; +import com.aerospike.dsl.IndexContext; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -32,7 +32,7 @@ void binLogical_AND_2_all_indexes() { Filter filter = Filter.range("intBin2", 101, Long.MAX_VALUE); Exp exp = Exp.gt(Exp.intBin("intBin1"), Exp.val(100)); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); } @Test @@ -46,7 +46,7 @@ void binLogical_AND_2_all_indexes_no_cardinality() { Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); Exp exp = Exp.gt(Exp.intBin("intBin2"), Exp.val(100)); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); } @Test @@ -57,7 +57,7 @@ void binLogical_AND_2_one_index() { Filter filter = Filter.range("intBin1", 101, Long.MAX_VALUE); Exp exp = Exp.gt(Exp.intBin("intBin2"), Exp.val(100)); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); } @Test @@ -74,7 +74,7 @@ void binLogical_AND_3_all_indexes() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); } @Test @@ -92,7 +92,7 @@ void binLogical_AND_3_all_indexes_same_cardinality() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); } @Test @@ -110,7 +110,7 @@ void binLogical_AND_3_all_indexes_no_cardinality() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); } @Test @@ -130,7 +130,7 @@ void binLogical_AND_3_all_indexes_partial_data() { Exp.gt(Exp.intBin("intBin2"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); } @Test @@ -146,7 +146,7 @@ void binLogical_AND_3_two_indexes() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 > 100", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); } @Test @@ -170,7 +170,7 @@ void binLogical_OR_2_all_indexes() { Exp.gt(Exp.intBin("intBin2"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); } @Test @@ -185,7 +185,7 @@ void binLogical_OR_2_one_index() { Exp.gt(Exp.intBin("intBin2"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); } @Test @@ -205,7 +205,7 @@ void binLogical_OR_3_all_indexes() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 or $.intBin2 > 100 or $.intBin3 > 100", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); } @Test @@ -225,9 +225,9 @@ void binLogical_prioritizedAND_OR_indexed() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 or $.intBin3 > 100", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); parseExpressionAndCompare("($.intBin1 > 100 and $.intBin2 > 100) or $.intBin3 > 100", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); } @Disabled // TODO: complex logical structures, different grouping @@ -248,6 +248,6 @@ void binLogical_AND_prioritizedOR_indexed() { Exp.gt(Exp.intBin("intBin3"), Exp.val(100)) ); parseExpressionAndCompare("$.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 > 100)", filter, exp, - IndexFilterInput.of(namespace, indexes)); + IndexContext.of(namespace, indexes)); } } diff --git a/src/test/java/com/aerospike/dsl/util/TestUtils.java b/src/test/java/com/aerospike/dsl/util/TestUtils.java index 74e2478..c5b95ed 100644 --- a/src/test/java/com/aerospike/dsl/util/TestUtils.java +++ b/src/test/java/com/aerospike/dsl/util/TestUtils.java @@ -4,13 +4,10 @@ import com.aerospike.client.exp.Expression; import com.aerospike.client.query.Filter; import com.aerospike.dsl.DSLParserImpl; -import com.aerospike.dsl.Index; -import com.aerospike.dsl.IndexFilterInput; +import com.aerospike.dsl.IndexContext; import com.aerospike.dsl.ParsedExpression; import lombok.experimental.UtilityClass; -import java.util.List; - import static org.junit.jupiter.api.Assertions.assertEquals; @UtilityClass @@ -32,7 +29,7 @@ public static Filter parseFilter(String input) { return parser.parseExpression(input).getResult().getFilter(); } - public static Filter parseFilter(String input, IndexFilterInput indexFilterInput) { + public static Filter parseFilter(String input, IndexContext indexFilterInput) { return parser.parseExpression(input, indexFilterInput).getResult().getFilter(); } @@ -41,7 +38,7 @@ public static void parseFilterAndCompare(String input, Filter expected) { assertEquals(actualFilter, expected); } - public static void parseFilterAndCompare(String input, IndexFilterInput indexFilterInput, Filter expected) { + public static void parseFilterAndCompare(String input, IndexContext indexFilterInput, Filter expected) { Filter actualFilter = parseFilter(input, indexFilterInput); assertEquals(actualFilter, expected); } @@ -53,7 +50,7 @@ public static void parseExpressionAndCompare(String input, Filter filter, Exp ex assertEquals(actualExp == null ? null : Exp.build(actualExp), exp == null ? null : Exp.build(exp)); } - public static void parseExpressionAndCompare(String input, Filter filter, Exp exp, IndexFilterInput indexFilterInput) { + public static void parseExpressionAndCompare(String input, Filter filter, Exp exp, IndexContext indexFilterInput) { ParsedExpression actualExpression = parser.parseExpression(input, indexFilterInput); assertEquals(actualExpression.getResult().getFilter(), filter); Exp actualExp = actualExpression.getResult().getExp(); From b0e0dba36bbd5682e5c847cf13a1dfad896c7253 Mon Sep 17 00:00:00 2001 From: agrgr Date: Sun, 4 May 2025 18:40:58 +0300 Subject: [PATCH 14/20] add Javadoc --- .../NoApplicableFilterException.java | 3 ++- .../aerospike/dsl/visitor/VisitorUtils.java | 20 +++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/aerospike/dsl/exceptions/NoApplicableFilterException.java b/src/main/java/com/aerospike/dsl/exceptions/NoApplicableFilterException.java index c36b788..58a734a 100644 --- a/src/main/java/com/aerospike/dsl/exceptions/NoApplicableFilterException.java +++ b/src/main/java/com/aerospike/dsl/exceptions/NoApplicableFilterException.java @@ -8,7 +8,8 @@ *

This exception is typically thrown when attempting to create a Filter for a DSL expression * but the structure or types of the expression do not match any supported filtering patterns * (e.g., comparing Strings using arithmetical operations, using OR-combined expression etc.). - * It signifies that while the expression might be valid in a broader context, it cannot be represented with a Filter. + * It signifies that while the expression might be valid in a broader context, it cannot be represented with a + * secondary index Filter. */ public class NoApplicableFilterException extends RuntimeException { diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index ef1fed8..d25b901 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -1209,9 +1209,25 @@ private static Map> getExpressionsPerCardinal return exprsPerCardinality; } + /** + * Updates a map of expression containers grouped by the cardinality of the indexes associated with an + * expression container's bin part. + * This method iterates through the indexes related to the provided {@code binPart}. + * For each index that matches the expression type of the {@code binPart}, it adds the given {@code expr} + * to the {@code exprsPerCardinality} map. + * + * @param exprsPerCardinality A map where keys are integer ratios (representing index cardinality) + * and values are lists of {@link ExpressionContainer} objects. The map is updated by this method + * @param expr The {@link ExpressionContainer} to be added to the appropriate list + * within {@code exprsPerCardinality} + * @param binPart The {@link BinPart} associated with the expression, used to find + * relevant indexes and determine the expression type + * @param indexes A map where keys are bin names and values are lists of + * {@link Index} objects associated with that bin + */ private static void updateExpressionsPerCardinality(Map> exprsPerCardinality, - ExpressionContainer expr, BinPart binPart, - Map> indexes) { + ExpressionContainer expr, BinPart binPart, + Map> indexes) { List indexesByBin = indexes.get(binPart.getBinName()); if (indexesByBin == null || indexesByBin.isEmpty()) return; From 9a2de5812d0cb120904dd0365b6b122b800f08c9 Mon Sep 17 00:00:00 2001 From: agrgr Date: Sun, 4 May 2025 20:42:33 +0300 Subject: [PATCH 15/20] rename exception --- .../java/com/aerospike/dsl/DSLParser.java | 14 ++-- .../java/com/aerospike/dsl/DSLParserImpl.java | 8 +-- .../com/aerospike/dsl/ParsedExpression.java | 8 +-- ...eDSLException.java => ParseException.java} | 4 +- .../com/aerospike/dsl/parts/cdt/CdtPart.java | 4 +- .../dsl/parts/cdt/list/ListIndexRange.java | 4 +- .../dsl/parts/cdt/list/ListPart.java | 4 +- .../dsl/parts/cdt/list/ListRankRange.java | 4 +- .../parts/cdt/list/ListRankRangeRelative.java | 6 +- .../dsl/parts/cdt/list/ListValueList.java | 4 +- .../dsl/parts/cdt/list/ListValueRange.java | 4 +- .../dsl/parts/cdt/map/MapIndexRange.java | 4 +- .../parts/cdt/map/MapIndexRangeRelative.java | 4 +- .../aerospike/dsl/parts/cdt/map/MapKey.java | 4 +- .../dsl/parts/cdt/map/MapKeyList.java | 4 +- .../dsl/parts/cdt/map/MapKeyRange.java | 4 +- .../dsl/parts/cdt/map/MapRankRange.java | 4 +- .../parts/cdt/map/MapRankRangeRelative.java | 6 +- .../dsl/parts/cdt/map/MapValueList.java | 4 +- .../dsl/parts/cdt/map/MapValueRange.java | 4 +- .../com/aerospike/dsl/util/ParsingUtils.java | 6 +- .../aerospike/dsl/util/ValidationUtils.java | 4 +- .../visitor/ExpressionConditionVisitor.java | 20 +++--- .../aerospike/dsl/visitor/VisitorUtils.java | 68 +++++++++---------- .../ArithmeticExpressionsTests.java | 4 +- .../dsl/expression/BinExpressionsTests.java | 4 +- .../dsl/expression/CastingTests.java | 4 +- .../dsl/expression/ExplicitTypesTests.java | 24 +++---- .../dsl/expression/ListExpressionsTests.java | 4 +- .../expression/LogicalExpressionsTests.java | 12 ++-- .../dsl/expression/RecordMetadataTests.java | 4 +- .../dsl/filter/ArithmeticFiltersTests.java | 8 +-- .../dsl/filter/ExplicitTypesFiltersTests.java | 16 ++--- 33 files changed, 140 insertions(+), 140 deletions(-) rename src/main/java/com/aerospike/dsl/exceptions/{AerospikeDSLException.java => ParseException.java} (75%) diff --git a/src/main/java/com/aerospike/dsl/DSLParser.java b/src/main/java/com/aerospike/dsl/DSLParser.java index 49db984..fd3c6e1 100644 --- a/src/main/java/com/aerospike/dsl/DSLParser.java +++ b/src/main/java/com/aerospike/dsl/DSLParser.java @@ -1,7 +1,7 @@ package com.aerospike.dsl; import com.aerospike.client.query.Filter; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; /** * Contains API to convert dot separated String path into an Aerospike filter - @@ -85,7 +85,7 @@ public interface DSLParser { * * @param dslString String consisting of dot separated elements, typically bin name and optional context * @return {@link ParsedExpression} object - * @throws AerospikeDSLException in case of invalid syntax + * @throws ParseException in case of invalid syntax */ ParsedExpression parseExpression(String dslString); @@ -155,11 +155,11 @@ public interface DSLParser { * * * - * @param dslString String consisting of dot separated elements, typically bin name and optional context - * @param indexFilterInput Class containing namespace and collection of {@link Index} objects that represent - * created secondary indexes. Required for creating {@link Filter}. Can be null + * @param dslString String consisting of dot separated elements, typically bin name and optional context + * @param indexContext Class containing namespace and collection of {@link Index} objects that represent + * existing secondary indexes. Required for creating {@link Filter}. Can be null * @return {@link ParsedExpression} object - * @throws AerospikeDSLException in case of or invalid syntax + * @throws ParseException in case of or invalid syntax */ - ParsedExpression parseExpression(String dslString, IndexContext indexFilterInput); + ParsedExpression parseExpression(String dslString, IndexContext indexContext); } diff --git a/src/main/java/com/aerospike/dsl/DSLParserImpl.java b/src/main/java/com/aerospike/dsl/DSLParserImpl.java index 7bb36d0..4749a49 100644 --- a/src/main/java/com/aerospike/dsl/DSLParserImpl.java +++ b/src/main/java/com/aerospike/dsl/DSLParserImpl.java @@ -1,7 +1,7 @@ package com.aerospike.dsl; import com.aerospike.dsl.annotation.Beta; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.exceptions.NoApplicableFilterException; import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.visitor.ExpressionConditionVisitor; @@ -24,9 +24,9 @@ public ParsedExpression parseExpression(String dslString) { } @Beta - public ParsedExpression parseExpression(String input, IndexContext indexFilterInput) { + public ParsedExpression parseExpression(String input, IndexContext indexContext) { ParseTree parseTree = getParseTree(input); - return getParsedExpression(parseTree, indexFilterInput); + return getParsedExpression(parseTree, indexContext); } private ParseTree getParseTree(String input) { @@ -68,7 +68,7 @@ private ParsedExpression getParsedExpression(ParseTree parseTree, IndexContext i // When we can't identify a specific case of syntax error, we throw a generic DSL syntax error if (!hasFilterParsingError && resultingPart == null) { - throw new AerospikeDSLException("Could not parse given input, wrong syntax"); + throw new ParseException("Could not parse given input, wrong syntax"); } // Transfer the parsed tree along with namespace and indexes Map return new ParsedExpression(resultingPart, indexesMap); diff --git a/src/main/java/com/aerospike/dsl/ParsedExpression.java b/src/main/java/com/aerospike/dsl/ParsedExpression.java index 66d48cd..b961513 100644 --- a/src/main/java/com/aerospike/dsl/ParsedExpression.java +++ b/src/main/java/com/aerospike/dsl/ParsedExpression.java @@ -3,7 +3,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.query.Filter; import com.aerospike.dsl.annotation.Beta; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.parts.ExpressionContainer; import lombok.Getter; @@ -35,16 +35,16 @@ public ParsedExpression(AbstractPart expressionTree, Map> in /** * @return Pair of secondary index {@link Filter} and filter {@link Exp}. Each can be null in case of invalid or * unsupported DSL string - * @throws AerospikeDSLException If there was an error + * @throws ParseException If there was an error */ public ParseResult getResult() { if (result == null) { - result = getResultPair(); + result = getParseResult(); } return result; } - public ParseResult getResultPair() { + private ParseResult getParseResult() { if (expressionTree != null) { if (expressionTree.getPartType() == EXPRESSION_CONTAINER) { AbstractPart result = buildExpr((ExpressionContainer) expressionTree, indexesMap); diff --git a/src/main/java/com/aerospike/dsl/exceptions/AerospikeDSLException.java b/src/main/java/com/aerospike/dsl/exceptions/ParseException.java similarity index 75% rename from src/main/java/com/aerospike/dsl/exceptions/AerospikeDSLException.java rename to src/main/java/com/aerospike/dsl/exceptions/ParseException.java index 354d10d..6802235 100644 --- a/src/main/java/com/aerospike/dsl/exceptions/AerospikeDSLException.java +++ b/src/main/java/com/aerospike/dsl/exceptions/ParseException.java @@ -5,9 +5,9 @@ * It is typically not expected to be caught by the caller, but rather indicates a potentially * unrecoverable issue like invalid input, failing validation or unsupported functionality. */ -public class AerospikeDSLException extends RuntimeException { +public class ParseException extends RuntimeException { - public AerospikeDSLException(String description) { + public ParseException(String description) { super(description); } } diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java b/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java index dca3b44..86182fe 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java @@ -2,7 +2,7 @@ import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.parts.path.BasePath; import com.aerospike.dsl.parts.path.PathFunction; @@ -17,7 +17,7 @@ protected CdtPart(PartType partType) { public CTX getContext() { // should print the subclass of the cdt type - throw new AerospikeDSLException("Context is not supported for %s".formatted(this.getClass().getName())); + throw new ParseException("Context is not supported for %s".formatted(this.getClass().getName())); } public abstract int getReturnType(PathFunction.ReturnParam returnParam); diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java index 4296407..f921c5c 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; @@ -39,7 +39,7 @@ public static ListIndexRange from(ConditionParser.ListIndexRangeContext ctx) { return new ListIndexRange(isInverted, start, end); } - throw new AerospikeDSLException("Could not translate ListIndexRange from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate ListIndexRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java index db24095..d41890f 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.parts.cdt.list; import com.aerospike.client.cdt.ListReturnType; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.PathFunction; import com.aerospike.dsl.parts.cdt.CdtPart; import lombok.Getter; @@ -27,7 +27,7 @@ public int getReturnType(PathFunction.ReturnParam returnParam) { case REVERSE_INDEX -> ListReturnType.REVERSE_INDEX; case REVERSE_RANK -> ListReturnType.REVERSE_RANK; default -> - throw new AerospikeDSLException("Unsupported Return Param for List CDT: %s".formatted(returnParam)); + throw new ParseException("Unsupported Return Param for List CDT: %s".formatted(returnParam)); }; } diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java index 4d01f4f..7e34503 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; @@ -39,7 +39,7 @@ public static ListRankRange from(ConditionParser.ListRankRangeContext ctx) { return new ListRankRange(isInverted, start, end); } - throw new AerospikeDSLException("Could not translate ListRankRange from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate ListRankRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java index 3e88e16..56e03e2 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; @@ -57,7 +57,7 @@ public static ListRankRangeRelative from(ConditionParser.ListRankRangeRelativeCo return new ListRankRangeRelative(isInverted, start, end, relativeValue); } - throw new AerospikeDSLException("Could not translate ListRankRangeRelative from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate ListRankRangeRelative from ctx: %s".formatted(ctx)); } @Override @@ -72,7 +72,7 @@ public Exp constructExp(BasePath basePath, Exp.Type valueType, int cdtReturnType } else if (relative instanceof Integer rel) { relativeExp = Exp.val(rel); } else { - throw new AerospikeDSLException("Unsupported value relative rank"); + throw new ParseException("Unsupported value relative rank"); } Exp startExp = Exp.val(start); diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java index 4c61ca0..dd8649f 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; import java.util.List; @@ -44,7 +44,7 @@ public static ListValueList from(ConditionParser.ListValueListContext ctx) { return new ListValueList(isInverted, valueListObjects); } - throw new AerospikeDSLException("Could not translate ListValueList from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate ListValueList from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java index 7ff69cf..5df9c32 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; public class ListValueRange extends ListPart { @@ -39,7 +39,7 @@ public static ListValueRange from(ConditionParser.ListValueRangeContext ctx) { return new ListValueRange(isInverted, startValue, endValue); } - throw new AerospikeDSLException("Could not translate ListValueRange from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate ListValueRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java index 163796a..0605241 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; @@ -39,7 +39,7 @@ public static MapIndexRange from(ConditionParser.MapIndexRangeContext ctx) { return new MapIndexRange(isInverted, start, end); } - throw new AerospikeDSLException("Could not translate MapIndexRange from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate MapIndexRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java index 57890b4..ef66a7f 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; @@ -52,7 +52,7 @@ public static MapIndexRangeRelative from(ConditionParser.MapIndexRangeRelativeCo } return new MapIndexRangeRelative(isInverted, start, end, relativeKey); } - throw new AerospikeDSLException("Could not translate MapIndexRangeRelative from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate MapIndexRangeRelative from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java index dd035b6..5af9f45 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; @@ -25,7 +25,7 @@ public static MapKey from(ConditionParser.MapKeyContext ctx) { if (ctx.NAME_IDENTIFIER() != null) { return new MapKey(ctx.NAME_IDENTIFIER().getText()); } - throw new AerospikeDSLException("Could not translate MapKey from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate MapKey from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java index baa1522..6a1bc4e 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; import java.util.List; @@ -43,7 +43,7 @@ public static MapKeyList from(ConditionParser.MapKeyListContext ctx) { return new MapKeyList(isInverted, keyListStrings); } - throw new AerospikeDSLException("Could not translate MapKeyList from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate MapKeyList from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java index ef84a11..113aaa2 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; import java.util.Optional; @@ -45,7 +45,7 @@ public static MapKeyRange from(ConditionParser.MapKeyRangeContext ctx) { return new MapKeyRange(isInverted, startKey, endKey); } - throw new AerospikeDSLException("Could not translate MapKeyRange from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate MapKeyRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java index fd9d3c3..035cbaa 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; @@ -39,7 +39,7 @@ public static MapRankRange from(ConditionParser.MapRankRangeContext ctx) { return new MapRankRange(isInverted, start, end); } - throw new AerospikeDSLException("Could not translate MapRankRange from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate MapRankRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java index db3aeca..03f1448 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; @@ -56,7 +56,7 @@ public static MapRankRangeRelative from(ConditionParser.MapRankRangeRelativeCont return new MapRankRangeRelative(isInverted, start, end, relativeValue); } - throw new AerospikeDSLException("Could not translate MapRankRangeRelative from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate MapRankRangeRelative from ctx: %s".formatted(ctx)); } @Override @@ -71,7 +71,7 @@ public Exp constructExp(BasePath basePath, Exp.Type valueType, int cdtReturnType } else if (relative instanceof Integer rel) { relativeExp = Exp.val(rel); } else { - throw new AerospikeDSLException("Unsupported value relative rank"); + throw new ParseException("Unsupported value relative rank"); } Exp startExp = Exp.val(start); diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java index 4d96c5b..1f8fdc5 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; import java.util.List; @@ -44,7 +44,7 @@ public static MapValueList from(ConditionParser.MapValueListContext ctx) { return new MapValueList(isInverted, valueListObjects); } - throw new AerospikeDSLException("Could not translate MapValueList from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate MapValueList from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java index 8f51700..9805f26 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.path.BasePath; public class MapValueRange extends MapPart { @@ -38,7 +38,7 @@ public static MapValueRange from(ConditionParser.MapValueRangeContext ctx) { return new MapValueRange(isInverted, startValue, endValue); } - throw new AerospikeDSLException("Could not translate MapValueRange from ctx: %s".formatted(ctx)); + throw new ParseException("Could not translate MapValueRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/util/ParsingUtils.java b/src/main/java/com/aerospike/dsl/util/ParsingUtils.java index 3866c18..3fc46be 100644 --- a/src/main/java/com/aerospike/dsl/util/ParsingUtils.java +++ b/src/main/java/com/aerospike/dsl/util/ParsingUtils.java @@ -1,6 +1,6 @@ package com.aerospike.dsl.util; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import lombok.NonNull; import lombok.experimental.UtilityClass; @@ -35,13 +35,13 @@ public static Integer subtractNullable(Integer a, @NonNull Integer b) { * * @param methodName The method name string * @return The extracted type string - * @throws AerospikeDSLException if the method name is not in the correct format + * @throws ParseException if the method name is not in the correct format */ public 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)); + throw new ParseException("Invalid method name: %s".formatted(methodName)); } } diff --git a/src/main/java/com/aerospike/dsl/util/ValidationUtils.java b/src/main/java/com/aerospike/dsl/util/ValidationUtils.java index a6f188e..ab0cb24 100644 --- a/src/main/java/com/aerospike/dsl/util/ValidationUtils.java +++ b/src/main/java/com/aerospike/dsl/util/ValidationUtils.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.util; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import lombok.experimental.UtilityClass; @UtilityClass @@ -14,7 +14,7 @@ public static void validateComparableTypes(Exp.Type leftType, Exp.Type rightType (leftType.equals(Exp.Type.FLOAT) && rightType.equals(Exp.Type.INT)); if (!leftType.equals(rightType) && !isIntAndFloat) { - throw new AerospikeDSLException("Cannot compare %s to %s".formatted(leftType, rightType)); + throw new ParseException("Cannot compare %s to %s".formatted(leftType, rightType)); } } } diff --git a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java index 9571fa7..4b68c82 100644 --- a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java +++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java @@ -3,7 +3,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.dsl.ConditionBaseVisitor; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.parts.*; import com.aerospike.dsl.parts.cdt.list.ListIndex; import com.aerospike.dsl.parts.cdt.list.ListIndexRange; @@ -96,7 +96,7 @@ public AbstractPart visitNotExpression(ConditionParser.NotExpressionContext ctx) @Override public AbstractPart visitExclusiveExpression(ConditionParser.ExclusiveExpressionContext ctx) { if (ctx.expression().size() < 2) { - throw new AerospikeDSLException("Exclusive logical operator requires 2 or more expressions"); + throw new ParseException("Exclusive logical operator requires 2 or more expressions"); } List expressions = new ArrayList<>(); // iterate through each definition @@ -313,13 +313,13 @@ public ListOperand readChildrenIntoListOperand(RuleNode listNode) { AbstractPart operand = visit(child); // delegate to a dedicated visitor if (operand == null) { - throw new AerospikeDSLException("Unable to parse list operand"); + throw new ParseException("Unable to parse list operand"); } try { values.add(((ParsedValueOperand) operand).getValue()); } catch (ClassCastException e) { - throw new AerospikeDSLException("List constant contains elements of different type"); + throw new ParseException("List constant contains elements of different type"); } } @@ -333,7 +333,7 @@ public AbstractPart visitOrderedMapConstant(ConditionParser.OrderedMapConstantCo public TreeMap getOrderedMapPair(ParseTree ctx) { if (ctx.getChild(0) == null || ctx.getChild(2) == null) { - throw new AerospikeDSLException("Unable to parse map operand"); + throw new ParseException("Unable to parse map operand"); } Object key = ((ParsedValueOperand) visit(ctx.getChild(0))).getValue(); Object value = ((ParsedValueOperand) visit(ctx.getChild(2))).getValue(); @@ -356,7 +356,7 @@ public MapOperand readChildrenIntoMapOperand(RuleNode mapNode) { try { mapOfPair.forEach(map::putIfAbsent); // put contents of the current map pair to the resulting map } catch (ClassCastException e) { - throw new AerospikeDSLException("Map constant contains elements of different type"); + throw new ParseException("Map constant contains elements of different type"); } } @@ -406,12 +406,12 @@ public AbstractPart visitBasePath(ConditionParser.BasePathContext ctx) { switch (part.getPartType()) { case BIN_PART -> binPart = (BinPart) overrideType(part, ctx); case LIST_PART, MAP_PART -> parts.add(overrideType(part, ctx)); - default -> throw new AerospikeDSLException("Unexpected path part: %s".formatted(part.getPartType())); + default -> throw new ParseException("Unexpected path part: %s".formatted(part.getPartType())); } } if (binPart == null) { - throw new AerospikeDSLException("Expecting bin to be the first path part from the left"); + throw new ParseException("Expecting bin to be the first path part from the left"); } return new BasePath(binPart, parts); @@ -484,7 +484,7 @@ public AbstractPart visitListPart(ConditionParser.ListPartContext ctx) { if (ctx.listRankRange() != null) return ListRankRange.from(ctx.listRankRange()); if (ctx.listRankRangeRelative() != null) return ListRankRangeRelative.from(ctx.listRankRangeRelative()); - throw new AerospikeDSLException("Unexpected list part: %s".formatted(ctx.getText())); + throw new ParseException("Unexpected list part: %s".formatted(ctx.getText())); } @Override @@ -504,7 +504,7 @@ public AbstractPart visitMapPart(ConditionParser.MapPartContext ctx) { return MapRankRangeRelative.from(ctx.mapRankRangeRelative()); if (ctx.mapIndexRangeRelative() != null) return MapIndexRangeRelative.from(ctx.mapIndexRangeRelative()); - throw new AerospikeDSLException("Unexpected map part: %s".formatted(ctx.getText())); + throw new ParseException("Unexpected map part: %s".formatted(ctx.getText())); } @Override diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index d25b901..13a78c4 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -5,7 +5,7 @@ import com.aerospike.client.query.IndexType; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.Index; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.exceptions.NoApplicableFilterException; import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.parts.ExpressionContainer; @@ -258,7 +258,7 @@ static boolean shouldVisitMapElement(int i, int size, ParseTree child) { * @param operator The binary operator to apply * @param binIsLeft Whether the bin is on the left side of the comparison * @return The resulting expression - * @throws AerospikeDSLException if the operand type is not supported + * @throws ParseException if the operand type is not supported */ private static Exp getExpBinComparison(BinPart binPart, AbstractPart otherPart, BinaryOperator operator, boolean binIsLeft) { @@ -300,7 +300,7 @@ private static Exp getExpBinComparison(BinPart binPart, AbstractPart otherPart, yield otherPart.getExp(); } default -> - throw new AerospikeDSLException("Operand type not supported: %s".formatted(otherPart.getPartType())); + throw new ParseException("Operand type not supported: %s".formatted(otherPart.getPartType())); }; return binIsLeft ? operator.apply(binExp, otherExp) : operator.apply(otherExp, binExp); @@ -312,7 +312,7 @@ private static Exp getExpBinComparison(BinPart binPart, AbstractPart otherPart, * @param binPart The {@link BinPart} involved in the comparison * @param stringOperand The {@link StringOperand} involved in the comparison * @return The {@link Exp} generated from the {@link StringOperand} - * @throws AerospikeDSLException if type validation fails (e.g., comparing a non-string/blob bin with a String) + * @throws ParseException if type validation fails (e.g., comparing a non-string/blob bin with a String) */ private static Exp handleStringOperandComparison(BinPart binPart, StringOperand stringOperand) { boolean isBlobType = binPart.getExpType() != null && binPart.getExpType().equals(Exp.Type.BLOB); @@ -334,7 +334,7 @@ private static Exp handleStringOperandComparison(BinPart binPart, StringOperand * @param right The {@link AbstractPart} on the right side of the comparison * @param operator The binary operator to apply * @return The resulting {@link Exp} for the comparison - * @throws AerospikeDSLException if an unsupported operand type is encountered or type validation fails + * @throws ParseException if an unsupported operand type is encountered or type validation fails */ private static Exp getExpLeftBinTypeComparison(BinPart left, AbstractPart right, BinaryOperator operator) { return getExpBinComparison(left, right, operator, true); @@ -347,7 +347,7 @@ private static Exp getExpLeftBinTypeComparison(BinPart left, AbstractPart right, * @param right The {@link BinPart} on the right side of the comparison * @param operator The binary operator to apply * @return The resulting {@link Exp} for the comparison - * @throws AerospikeDSLException if an unsupported operand type is encountered or type validation fails + * @throws ParseException if an unsupported operand type is encountered or type validation fails */ private static Exp getExpRightBinTypeComparison(AbstractPart left, BinPart right, BinaryOperator operator) { return getExpBinComparison(right, left, operator, false); @@ -405,7 +405,7 @@ private static ArithmeticTermType getFilterTermType(ExprPartsOperation operation * @return A {@link Pair} representing the lower and upper bounds of the range for the bin. * A {@code null} value in the pair indicates no bound on that side * @throws NoApplicableFilterException if division by zero occurs or the term type is unsupported - * @throws AerospikeDSLException if undefined division (0/0) occurs + * @throws ParseException if undefined division (0/0) occurs */ private static Pair getLimitsForDivisionForFilter(long left, long right, FilterOperationType type, ArithmeticTermType termType) { @@ -430,7 +430,7 @@ private static Pair getLimitsForDivisionForFilter(long left, long ri * @param operationType The type of the filter operation * @return A {@link Pair} representing the lower and upper bounds of the range for the bin. * A {@code null} value in the pair indicates no bound on that side - * @throws AerospikeDSLException if undefined division (0/0) occurs or if the operation type is not supported + * @throws ParseException if undefined division (0/0) occurs or if the operation type is not supported */ private static Pair LimitsForBinDividend(long left, long right, FilterOperationType operationType) { @@ -438,7 +438,7 @@ private static Pair LimitsForBinDividend(long left, long right, // both operands are positive return getLimitsForBinDividendWithLeftNumberPositive(operationType, left, right); } else if (left == 0 && right == 0) { - throw new AerospikeDSLException("Undefined division for 0 / 0"); + throw new ParseException("Undefined division for 0 / 0"); } else if (left < 0 && right < 0) { // both operands are negative return getLimitsForBinDividendWithLeftNumberNegative(operationType, left, right); @@ -449,7 +449,7 @@ private static Pair LimitsForBinDividend(long left, long right, // left negative, right positive return getLimitsForBinDividendWithLeftNumberNegative(operationType, left, right); } else if (left != 0) { - throw new AerospikeDSLException("Division by zero is not allowed"); + throw new ParseException("Division by zero is not allowed"); } else { return new Pair<>(null, null); } @@ -462,7 +462,7 @@ private static Pair LimitsForBinDividend(long left, long right, * @param left The value of the dividend * @param right The value of the divisor * @return A {@link Pair} representing the lower and upper bounds of the range for the bin - * @throws AerospikeDSLException if the operation type is not supported for division + * @throws ParseException if the operation type is not supported for division */ private static Pair getLimitsForBinDividendWithLeftNumberNegative(FilterOperationType operationType, long left, long right) { @@ -476,7 +476,7 @@ private static Pair getLimitsForBinDividendWithLeftNumberNegative(Fi case LTEQ: yield new Pair<>(left * right, Long.MAX_VALUE); default: - throw new AerospikeDSLException("OperationType not supported for division: " + operationType); + throw new ParseException("OperationType not supported for division: " + operationType); }; } @@ -487,7 +487,7 @@ private static Pair getLimitsForBinDividendWithLeftNumberNegative(Fi * @param left The value of the dividend * @param right The value of the divisor * @return A {@link Pair} representing the lower and upper bounds of the range for the bin - * @throws AerospikeDSLException if the operation type is not supported for division + * @throws ParseException if the operation type is not supported for division */ private static Pair getLimitsForBinDividendWithLeftNumberPositive(FilterOperationType operationType, long left, long right) { @@ -501,7 +501,7 @@ private static Pair getLimitsForBinDividendWithLeftNumberPositive(Fi case LTEQ: yield new Pair<>(Long.MIN_VALUE, left * right); default: - throw new AerospikeDSLException("OperationType not supported for division: " + operationType); + throw new ParseException("OperationType not supported for division: " + operationType); }; } @@ -513,7 +513,7 @@ private static Pair getLimitsForBinDividendWithLeftNumberPositive(Fi * @param operationType The type of the filter operation * @return A {@link Pair} representing the lower and upper bounds of the range for the bin. * A {@code null} value in the pair indicates no bound on that side - * @throws AerospikeDSLException if division by zero occurs or if the operation type is not supported + * @throws ParseException if division by zero occurs or if the operation type is not supported */ private static Pair getLimitsForBinDivisor(long left, long right, FilterOperationType operationType) { if (left > 0 && right > 0) { @@ -526,10 +526,10 @@ private static Pair getLimitsForBinDivisor(long left, long right, Fi case LT, LTEQ: yield new Pair<>(null, null); default: - throw new AerospikeDSLException("OperationType not supported for division: " + operationType); + throw new ParseException("OperationType not supported for division: " + operationType); }; } else if (left == 0 && right == 0) { - throw new AerospikeDSLException("Cannot divide by zero"); + throw new ParseException("Cannot divide by zero"); } else if (left < 0 && right < 0) { // both operands are negative return switch (operationType) { @@ -540,7 +540,7 @@ private static Pair getLimitsForBinDivisor(long left, long right, Fi case LTEQ: yield new Pair<>(1L, left / right); default: - throw new AerospikeDSLException("OperationType not supported for division: " + operationType); + throw new ParseException("OperationType not supported for division: " + operationType); }; } else if (left > 0 && right < 0) { // left positive, right negative @@ -552,7 +552,7 @@ private static Pair getLimitsForBinDivisor(long left, long right, Fi case LTEQ: yield new Pair<>(left / right, -1L); default: - throw new AerospikeDSLException("OperationType not supported for division: " + operationType); + throw new ParseException("OperationType not supported for division: " + operationType); }; } else if (right > 0 && left < 0) { // right positive, left negative @@ -564,10 +564,10 @@ private static Pair getLimitsForBinDivisor(long left, long right, Fi case LT, LTEQ: yield new Pair<>(null, null); default: - throw new AerospikeDSLException("OperationType not supported for division: " + operationType); + throw new ParseException("OperationType not supported for division: " + operationType); }; } else if (left != 0) { - throw new AerospikeDSLException("Division by zero is not allowed"); + throw new ParseException("Division by zero is not allowed"); } else { return new Pair<>(null, null); } @@ -581,14 +581,14 @@ private static Pair getLimitsForBinDivisor(long left, long right, Fi * A {@code null} value in the pair indicates no bound on that side * @param type The type of the filter operation * @return A {@link Filter} representing the condition - * @throws AerospikeDSLException if the operation type is not supported for generating a filter + * @throws ParseException if the operation type is not supported for generating a filter */ 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); + default -> throw new ParseException("OperationType not supported for division: " + type); }; } @@ -627,7 +627,7 @@ private static Filter getFilter(BinPart bin, AbstractPart operand, FilterOperati * @param type The type of the filter operation (must be {@link FilterOperationType#EQ}) * @return An Aerospike {@link Filter} for the string or blob comparison * @throws NoApplicableFilterException if the filter operation type is not equality - * @throws AerospikeDSLException if type validation fails or base64 decoding fails + * @throws ParseException if type validation fails or base64 decoding fails */ private static Filter handleStringOperand(BinPart bin, String binName, StringOperand operand, FilterOperationType type) { @@ -654,7 +654,7 @@ private static Filter handleStringOperand(BinPart bin, String binName, StringOpe * @param right The right operand * @param type The filter operation type * @return The appropriate Filter, or null if no filter can be created - * @throws AerospikeDSLException if operands are invalid + * @throws ParseException if operands are invalid */ private static Filter getFilterOrFail(AbstractPart left, AbstractPart right, FilterOperationType type) { validateOperands(left, right); @@ -689,7 +689,7 @@ private static Filter getFilterOrFail(AbstractPart left, AbstractPart right, Fil * @param otherOperand The other operand in the filter condition * @param type The type of the filter operation * @return A {@link Filter} if one can be generated from the nested expression, otherwise {@code null} - * @throws AerospikeDSLException if operands within the nested expression are null + * @throws ParseException if operands within the nested expression are null * @throws NoApplicableFilterException if the nested expression structure is not supported for filtering */ private static Filter handleExpressionOperand(ExpressionContainer expr, AbstractPart otherOperand, @@ -755,7 +755,7 @@ private static Filter getFilterFromExpressionOrFail(AbstractPart exprLeft, Abstr * @param binOnLeft {@code true} if the bin is on the left side of the arithmetic operation, {@code false} otherwise * @return A {@link Filter} for the arithmetic condition * @throws NoApplicableFilterException if operands are not integers or if the operation is not supported - * @throws AerospikeDSLException if type validation fails + * @throws ParseException if type validation fails */ private static Filter handleBinArithmeticExpression(BinPart bin, AbstractPart operand, AbstractPart externalOperand, @@ -783,14 +783,14 @@ private static Filter handleBinArithmeticExpression(BinPart bin, AbstractPart op * * @param left The left {@link AbstractPart} * @param right The right {@link AbstractPart} - * @throws AerospikeDSLException if either the left or right operand is null + * @throws ParseException if either the left or right operand is null */ private static void validateOperands(AbstractPart left, AbstractPart right) { if (left == null) { - throw new AerospikeDSLException("Left operand cannot be null"); + throw new ParseException("Left operand cannot be null"); } if (right == null) { - throw new AerospikeDSLException("Right operand cannot be null"); + throw new ParseException("Right operand cannot be null"); } } @@ -807,7 +807,7 @@ private static void validateOperands(AbstractPart left, AbstractPart right) { * @return A secondary index {@link Filter} * @throws NoApplicableFilterException if the operation is not supported by secondary index filters, * division by zero occurs, or the calculated range is invalid - * @throws AerospikeDSLException if undefined division (0/0) occurs or other issues arise + * @throws ParseException if undefined division (0/0) occurs or other issues arise */ private static Filter applyFilterOperator(String binName, IntOperand leftOperand, IntOperand rightOperand, ExprPartsOperation operationType, FilterOperationType type, @@ -1023,7 +1023,7 @@ private static Exp exclStructureToExp(ExpressionContainer expr) { * * @param expr The expression to process * @return The processed Exp - * @throws AerospikeDSLException if left or right operands are null in a binary expression + * @throws ParseException if left or right operands are null in a binary expression */ private static Exp processExpression(ExpressionContainer expr) { // For unary expressions @@ -1039,10 +1039,10 @@ private static Exp processExpression(ExpressionContainer expr) { AbstractPart left = expr.getLeft(); AbstractPart right = expr.getRight(); if (left == null) { - throw new AerospikeDSLException("Unable to parse left operand"); + throw new ParseException("Unable to parse left operand"); } if (right == null) { - throw new AerospikeDSLException("Unable to parse right operand"); + throw new ParseException("Unable to parse right operand"); } // Process operands diff --git a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java index 580d033..1b54719 100644 --- a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; @@ -118,7 +118,7 @@ void intRShift() { @Test void negativeArithmetic() { assertThatThrownBy(() -> parseExp("($.apples.get(type: STRING) + 5) > 10")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessageContaining("Cannot compare STRING to INT"); // TODO: should throw an exception (cannot use arithmetic operations on Strings) diff --git a/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java index 8289f35..83dd8c2 100644 --- a/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; @@ -59,7 +59,7 @@ void binNotEquals() { @Test void negativeStringBinEquals() { assertThatThrownBy(() -> parseExp("$.strBin == yes")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Unable to parse right operand"); } diff --git a/src/test/java/com/aerospike/dsl/expression/CastingTests.java b/src/test/java/com/aerospike/dsl/expression/CastingTests.java index 423fa25..418c27e 100644 --- a/src/test/java/com/aerospike/dsl/expression/CastingTests.java +++ b/src/test/java/com/aerospike/dsl/expression/CastingTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; @@ -27,7 +27,7 @@ void intToFloatComparison() { @Test void negativeInvalidTypesComparison() { assertThatThrownBy(() -> parseExp("$.stringBin1.get(type: STRING) > $.intBin2.asFloat()")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessageContaining("Cannot compare STRING to FLOAT"); } } diff --git a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java index d1f3a7b..cc1e3ee 100644 --- a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import org.junit.jupiter.api.Test; import java.util.Base64; @@ -45,7 +45,7 @@ void stringComparisonNegativeTest() { // A String constant must be quoted assertThatThrownBy(() -> parseExpAndCompare("$.stringBin1.get(type: STRING) == yes", Exp.eq(Exp.stringBin("stringBin1"), Exp.val("yes")))) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Unable to parse right operand"); } @@ -82,7 +82,7 @@ void booleanComparison() { @Test void negativeBooleanComparison() { assertThatThrownBy(() -> parseExp("$.boolBin1.get(type: BOOL) == 5")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessageContaining("Cannot compare BOOL to INT"); } @@ -122,7 +122,7 @@ void listComparison_constantOnRightSide_NegativeTest() { parseExpAndCompare("$.listBin1.get(type: LIST) == [yes, of course]", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of("yes", "of course")))) ) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Unable to parse list operand"); } @@ -162,7 +162,7 @@ void listComparison_constantOnLeftSide_NegativeTest() { parseExpAndCompare("[yes, of course] == $.listBin1.get(type: LIST)", Exp.eq(Exp.val(List.of("yes", "of course")), Exp.listBin("listBin1"))) ) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Could not parse given input, wrong syntax"); } @@ -228,14 +228,14 @@ void mapComparison_constantOnRightSide_NegativeTest() { parseExpAndCompare("$.mapBin1.get(type: MAP) == {yes, of course}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("yes", "of course")))) ) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Unable to parse map operand"); assertThatThrownBy(() -> parseExpAndCompare("$.mapBin1.get(type: MAP) == ['yes', 'of course']", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(List.of("yes", "of course")))) ) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Cannot compare MAP to LIST"); // Map key can only be Integer or String @@ -243,7 +243,7 @@ void mapComparison_constantOnRightSide_NegativeTest() { parseExpAndCompare("$.mapBin1.get(type: MAP) == {[100]:[100]}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(List.of("yes", "of course")))) ) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Unable to parse map operand"); } @@ -293,14 +293,14 @@ void mapComparison_constantOnLeftSide_NegativeTest() { parseExpAndCompare("{yes, of course} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("of course", "yes")))) ) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Could not parse given input, wrong syntax"); assertThatThrownBy(() -> parseExpAndCompare("['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) + .isInstanceOf(ParseException.class) .hasMessage("Cannot compare MAP to LIST"); // Map key can only be Integer or String @@ -308,7 +308,7 @@ void mapComparison_constantOnLeftSide_NegativeTest() { parseExpAndCompare("{[100]:[100]} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(List.of("yes", "of course")), Exp.mapBin("mapBin1"))) ) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Could not parse given input, wrong syntax"); } @@ -339,7 +339,7 @@ void twoBlobBinsComparison() { @Test void negativeTwoDifferentBinTypesComparison() { assertThatThrownBy(() -> parseExp("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessageContaining("Cannot compare STRING to FLOAT"); } diff --git a/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java index c9fb665..8fc9c66 100644 --- a/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java @@ -4,7 +4,7 @@ import com.aerospike.client.cdt.ListReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import org.junit.jupiter.api.Test; import java.util.List; @@ -231,7 +231,7 @@ void listBinElementCount() { void negativeSyntaxList() { // TODO: throw meaningful exception (by ANTLR?) assertThatThrownBy(() -> parseExp("$.listBin1.[stringValue] == 100")) - .isInstanceOf(AerospikeDSLException.class); + .isInstanceOf(ParseException.class); } //@Test diff --git a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java index dfa3306..7a2f400 100644 --- a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; @@ -82,19 +82,19 @@ void flatHierarchyAnd() { @Test void negativeSyntaxLogicalOperators() { assertThatThrownBy(() -> parseExp("($.intBin1 > 100 and ($.intBin2 > 100) or")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessageContaining("Could not parse given input"); assertThatThrownBy(() -> parseExp("and ($.intBin1 > 100 and ($.intBin2 > 100)")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessageContaining("Could not parse given input"); assertThatThrownBy(() -> parseExp("($.intBin1 > 100 and ($.intBin2 > 100) not")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessageContaining("Could not parse given input"); assertThatThrownBy(() -> parseExp("($.intBin1 > 100 and ($.intBin2 > 100) exclusive")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessageContaining("Could not parse given input"); } @@ -103,7 +103,7 @@ void negativeBinLogicalExclusiveWithOneParam() { assertThatThrownBy(() -> parseExpAndCompare("exclusive($.hand == \"hook\")", Exp.exclusive( Exp.eq(Exp.stringBin("hand"), Exp.val("hook"))))) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Exclusive logical operator requires 2 or more expressions"); } } diff --git a/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java index d023b2e..c9ca08b 100644 --- a/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java +++ b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; @@ -128,7 +128,7 @@ void ttl() { void negativeTtlAsDifferentType() { // TODO: should be supported when adding operator + metadata validations (requires a refactor) assertThatThrownBy(() -> parseExp("$.ttl() == true")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessageContaining("Expecting non-bin operand, got BOOL_OPERAND"); } diff --git a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java index e3d5191..f9c7868 100644 --- a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java @@ -4,7 +4,7 @@ import com.aerospike.client.query.IndexType; import com.aerospike.dsl.Index; import com.aerospike.dsl.IndexContext; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import org.junit.jupiter.api.Test; import java.util.Collection; @@ -49,7 +49,7 @@ void add() { assertThat(parseFilter("(5.2 + $.bananas) > 10.2")).isNull(); // not supported by secondary index filter assertThatThrownBy(() -> parseFilter("($.apples + $.bananas + 5) > 10")) - .isInstanceOf(AerospikeDSLException.class) // not supported by the current grammar + .isInstanceOf(ParseException.class) // not supported by the current grammar .hasMessageContaining("Could not parse given input, wrong syntax"); } @@ -86,7 +86,7 @@ void sub() { assertThat(parseFilter("($.apples - $.bananas) > 10")).isNull(); // not supported by secondary index filter assertThatThrownBy(() -> parseFilter("($.apples - $.bananas - 5) > 10")) - .isInstanceOf(AerospikeDSLException.class) // not supported by the current grammar + .isInstanceOf(ParseException.class) // not supported by the current grammar .hasMessageContaining("Could not parse given input, wrong syntax"); } @@ -127,7 +127,7 @@ void mul() { Filter.range("bananas", 0 / 9 + 1, Long.MAX_VALUE)); assertThatThrownBy(() -> parseFilter("($.apples * $.bananas - 5) > 10")) - .isInstanceOf(AerospikeDSLException.class) // not supported by the current grammar + .isInstanceOf(ParseException.class) // not supported by the current grammar .hasMessageContaining("Could not parse given input, wrong syntax"); } diff --git a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java index 22414bf..7246be6 100644 --- a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java @@ -4,7 +4,7 @@ import com.aerospike.client.query.IndexType; import com.aerospike.dsl.Index; import com.aerospike.dsl.IndexContext; -import com.aerospike.dsl.exceptions.AerospikeDSLException; +import com.aerospike.dsl.exceptions.ParseException; import com.aerospike.dsl.util.TestUtils; import org.junit.jupiter.api.Test; @@ -56,7 +56,7 @@ void stringComparison() { void stringComparisonNegativeTest() { // A String constant must be quoted assertThatThrownBy(() -> parseFilter("$.stringBin1.get(type: STRING) == yes")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Unable to parse right operand"); } @@ -89,7 +89,7 @@ void booleanComparison() { @Test void negativeBooleanComparison() { assertThatThrownBy(() -> parseFilter("$.boolBin1.get(type: BOOL) == 5")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Cannot compare BOOL to INT"); } @@ -102,7 +102,7 @@ void listComparison_constantOnRightSide() { @Test void listComparison_constantOnRightSide_NegativeTest() { assertThatThrownBy(() -> parseFilter("$.listBin1.get(type: LIST) == [yes, of course]")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Unable to parse list operand"); } @@ -114,7 +114,7 @@ void listComparison_constantOnLeftSide() { @Test void listComparison_constantOnLeftSide_NegativeTest() { assertThatThrownBy(() -> parseFilter("[yes, of course] == $.listBin1.get(type: LIST)")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Could not parse given input, wrong syntax"); } @@ -126,7 +126,7 @@ void mapComparison_constantOnRightSide() { @Test void mapComparison_constantOnRightSide_NegativeTest() { assertThatThrownBy(() -> parseFilter("$.mapBin1.get(type: MAP) == {yes, of course}")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Unable to parse map operand"); } @@ -138,7 +138,7 @@ void mapComparison_constantOnLeftSide() { @Test void mapComparison_constantOnLeftSide_NegativeTest() { assertThatThrownBy(() -> parseFilter("{yes, of course} == $.mapBin1.get(type: MAP)")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Could not parse given input, wrong syntax"); } @@ -165,7 +165,7 @@ void twoBlobBinsComparison() { @Test void negativeTwoDifferentBinTypesComparison() { assertThatThrownBy(() -> parseFilter("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")) - .isInstanceOf(AerospikeDSLException.class) + .isInstanceOf(ParseException.class) .hasMessage("Cannot compare STRING to FLOAT"); } } From f22899d30781b6e99046955a0d47d955ac69c4c3 Mon Sep 17 00:00:00 2001 From: agrgr Date: Sun, 4 May 2025 20:45:01 +0300 Subject: [PATCH 16/20] rename exception --- .../java/com/aerospike/dsl/DSLParser.java | 6 +- .../java/com/aerospike/dsl/DSLParserImpl.java | 4 +- .../com/aerospike/dsl/ParsedExpression.java | 4 +- ...eException.java => DslParseException.java} | 4 +- .../com/aerospike/dsl/parts/cdt/CdtPart.java | 4 +- .../dsl/parts/cdt/list/ListIndexRange.java | 4 +- .../dsl/parts/cdt/list/ListPart.java | 4 +- .../dsl/parts/cdt/list/ListRankRange.java | 4 +- .../parts/cdt/list/ListRankRangeRelative.java | 6 +- .../dsl/parts/cdt/list/ListValueList.java | 4 +- .../dsl/parts/cdt/list/ListValueRange.java | 4 +- .../dsl/parts/cdt/map/MapIndexRange.java | 4 +- .../parts/cdt/map/MapIndexRangeRelative.java | 4 +- .../aerospike/dsl/parts/cdt/map/MapKey.java | 4 +- .../dsl/parts/cdt/map/MapKeyList.java | 4 +- .../dsl/parts/cdt/map/MapKeyRange.java | 4 +- .../dsl/parts/cdt/map/MapRankRange.java | 4 +- .../parts/cdt/map/MapRankRangeRelative.java | 6 +- .../dsl/parts/cdt/map/MapValueList.java | 4 +- .../dsl/parts/cdt/map/MapValueRange.java | 4 +- .../com/aerospike/dsl/util/ParsingUtils.java | 6 +- .../aerospike/dsl/util/ValidationUtils.java | 4 +- .../visitor/ExpressionConditionVisitor.java | 20 +++--- .../aerospike/dsl/visitor/VisitorUtils.java | 68 +++++++++---------- .../ArithmeticExpressionsTests.java | 4 +- .../dsl/expression/BinExpressionsTests.java | 4 +- .../dsl/expression/CastingTests.java | 4 +- .../dsl/expression/ExplicitTypesTests.java | 24 +++---- .../dsl/expression/ListExpressionsTests.java | 4 +- .../expression/LogicalExpressionsTests.java | 12 ++-- .../dsl/expression/RecordMetadataTests.java | 4 +- .../dsl/filter/ArithmeticFiltersTests.java | 8 +-- .../dsl/filter/ExplicitTypesFiltersTests.java | 16 ++--- .../com/aerospike/dsl/util/TestUtils.java | 12 ++-- 34 files changed, 138 insertions(+), 138 deletions(-) rename src/main/java/com/aerospike/dsl/exceptions/{ParseException.java => DslParseException.java} (76%) diff --git a/src/main/java/com/aerospike/dsl/DSLParser.java b/src/main/java/com/aerospike/dsl/DSLParser.java index fd3c6e1..0cb4419 100644 --- a/src/main/java/com/aerospike/dsl/DSLParser.java +++ b/src/main/java/com/aerospike/dsl/DSLParser.java @@ -1,7 +1,7 @@ package com.aerospike.dsl; import com.aerospike.client.query.Filter; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; /** * Contains API to convert dot separated String path into an Aerospike filter - @@ -85,7 +85,7 @@ public interface DSLParser { * * @param dslString String consisting of dot separated elements, typically bin name and optional context * @return {@link ParsedExpression} object - * @throws ParseException in case of invalid syntax + * @throws DslParseException in case of invalid syntax */ ParsedExpression parseExpression(String dslString); @@ -159,7 +159,7 @@ public interface DSLParser { * @param indexContext Class containing namespace and collection of {@link Index} objects that represent * existing secondary indexes. Required for creating {@link Filter}. Can be null * @return {@link ParsedExpression} object - * @throws ParseException in case of or invalid syntax + * @throws DslParseException in case of or invalid syntax */ ParsedExpression parseExpression(String dslString, IndexContext indexContext); } diff --git a/src/main/java/com/aerospike/dsl/DSLParserImpl.java b/src/main/java/com/aerospike/dsl/DSLParserImpl.java index 4749a49..86c3bf1 100644 --- a/src/main/java/com/aerospike/dsl/DSLParserImpl.java +++ b/src/main/java/com/aerospike/dsl/DSLParserImpl.java @@ -1,7 +1,7 @@ package com.aerospike.dsl; import com.aerospike.dsl.annotation.Beta; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.exceptions.NoApplicableFilterException; import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.visitor.ExpressionConditionVisitor; @@ -68,7 +68,7 @@ private ParsedExpression getParsedExpression(ParseTree parseTree, IndexContext i // When we can't identify a specific case of syntax error, we throw a generic DSL syntax error if (!hasFilterParsingError && resultingPart == null) { - throw new ParseException("Could not parse given input, wrong syntax"); + throw new DslParseException("Could not parse given input, wrong syntax"); } // Transfer the parsed tree along with namespace and indexes Map return new ParsedExpression(resultingPart, indexesMap); diff --git a/src/main/java/com/aerospike/dsl/ParsedExpression.java b/src/main/java/com/aerospike/dsl/ParsedExpression.java index b961513..06c77c9 100644 --- a/src/main/java/com/aerospike/dsl/ParsedExpression.java +++ b/src/main/java/com/aerospike/dsl/ParsedExpression.java @@ -3,7 +3,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.query.Filter; import com.aerospike.dsl.annotation.Beta; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.parts.ExpressionContainer; import lombok.Getter; @@ -35,7 +35,7 @@ public ParsedExpression(AbstractPart expressionTree, Map> in /** * @return Pair of secondary index {@link Filter} and filter {@link Exp}. Each can be null in case of invalid or * unsupported DSL string - * @throws ParseException If there was an error + * @throws DslParseException If there was an error */ public ParseResult getResult() { if (result == null) { diff --git a/src/main/java/com/aerospike/dsl/exceptions/ParseException.java b/src/main/java/com/aerospike/dsl/exceptions/DslParseException.java similarity index 76% rename from src/main/java/com/aerospike/dsl/exceptions/ParseException.java rename to src/main/java/com/aerospike/dsl/exceptions/DslParseException.java index 6802235..3c4eed2 100644 --- a/src/main/java/com/aerospike/dsl/exceptions/ParseException.java +++ b/src/main/java/com/aerospike/dsl/exceptions/DslParseException.java @@ -5,9 +5,9 @@ * It is typically not expected to be caught by the caller, but rather indicates a potentially * unrecoverable issue like invalid input, failing validation or unsupported functionality. */ -public class ParseException extends RuntimeException { +public class DslParseException extends RuntimeException { - public ParseException(String description) { + public DslParseException(String description) { super(description); } } diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java b/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java index 86182fe..e226681 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java @@ -2,7 +2,7 @@ import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.parts.path.BasePath; import com.aerospike.dsl.parts.path.PathFunction; @@ -17,7 +17,7 @@ protected CdtPart(PartType partType) { public CTX getContext() { // should print the subclass of the cdt type - throw new ParseException("Context is not supported for %s".formatted(this.getClass().getName())); + throw new DslParseException("Context is not supported for %s".formatted(this.getClass().getName())); } public abstract int getReturnType(PathFunction.ReturnParam returnParam); diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java index f921c5c..0c02060 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; @@ -39,7 +39,7 @@ public static ListIndexRange from(ConditionParser.ListIndexRangeContext ctx) { return new ListIndexRange(isInverted, start, end); } - throw new ParseException("Could not translate ListIndexRange from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate ListIndexRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java index d41890f..f9bad98 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.parts.cdt.list; import com.aerospike.client.cdt.ListReturnType; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.PathFunction; import com.aerospike.dsl.parts.cdt.CdtPart; import lombok.Getter; @@ -27,7 +27,7 @@ public int getReturnType(PathFunction.ReturnParam returnParam) { case REVERSE_INDEX -> ListReturnType.REVERSE_INDEX; case REVERSE_RANK -> ListReturnType.REVERSE_RANK; default -> - throw new ParseException("Unsupported Return Param for List CDT: %s".formatted(returnParam)); + throw new DslParseException("Unsupported Return Param for List CDT: %s".formatted(returnParam)); }; } diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java index 7e34503..4cf34e8 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; @@ -39,7 +39,7 @@ public static ListRankRange from(ConditionParser.ListRankRangeContext ctx) { return new ListRankRange(isInverted, start, end); } - throw new ParseException("Could not translate ListRankRange from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate ListRankRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java index 56e03e2..d5beeac 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; @@ -57,7 +57,7 @@ public static ListRankRangeRelative from(ConditionParser.ListRankRangeRelativeCo return new ListRankRangeRelative(isInverted, start, end, relativeValue); } - throw new ParseException("Could not translate ListRankRangeRelative from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate ListRankRangeRelative from ctx: %s".formatted(ctx)); } @Override @@ -72,7 +72,7 @@ public Exp constructExp(BasePath basePath, Exp.Type valueType, int cdtReturnType } else if (relative instanceof Integer rel) { relativeExp = Exp.val(rel); } else { - throw new ParseException("Unsupported value relative rank"); + throw new DslParseException("Unsupported value relative rank"); } Exp startExp = Exp.val(start); diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java index dd8649f..b9355f7 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import java.util.List; @@ -44,7 +44,7 @@ public static ListValueList from(ConditionParser.ListValueListContext ctx) { return new ListValueList(isInverted, valueListObjects); } - throw new ParseException("Could not translate ListValueList from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate ListValueList from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java index 5df9c32..ab9e6c7 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; public class ListValueRange extends ListPart { @@ -39,7 +39,7 @@ public static ListValueRange from(ConditionParser.ListValueRangeContext ctx) { return new ListValueRange(isInverted, startValue, endValue); } - throw new ParseException("Could not translate ListValueRange from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate ListValueRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java index 0605241..7a2b985 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; @@ -39,7 +39,7 @@ public static MapIndexRange from(ConditionParser.MapIndexRangeContext ctx) { return new MapIndexRange(isInverted, start, end); } - throw new ParseException("Could not translate MapIndexRange from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate MapIndexRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java index ef66a7f..914a3bf 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; @@ -52,7 +52,7 @@ public static MapIndexRangeRelative from(ConditionParser.MapIndexRangeRelativeCo } return new MapIndexRangeRelative(isInverted, start, end, relativeKey); } - throw new ParseException("Could not translate MapIndexRangeRelative from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate MapIndexRangeRelative from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java index 5af9f45..ba636fd 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; @@ -25,7 +25,7 @@ public static MapKey from(ConditionParser.MapKeyContext ctx) { if (ctx.NAME_IDENTIFIER() != null) { return new MapKey(ctx.NAME_IDENTIFIER().getText()); } - throw new ParseException("Could not translate MapKey from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate MapKey from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java index 6a1bc4e..f89eda1 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import java.util.List; @@ -43,7 +43,7 @@ public static MapKeyList from(ConditionParser.MapKeyListContext ctx) { return new MapKeyList(isInverted, keyListStrings); } - throw new ParseException("Could not translate MapKeyList from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate MapKeyList from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java index 113aaa2..3e22d60 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import java.util.Optional; @@ -45,7 +45,7 @@ public static MapKeyRange from(ConditionParser.MapKeyRangeContext ctx) { return new MapKeyRange(isInverted, startKey, endKey); } - throw new ParseException("Could not translate MapKeyRange from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate MapKeyRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java index 035cbaa..d236e27 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; @@ -39,7 +39,7 @@ public static MapRankRange from(ConditionParser.MapRankRangeContext ctx) { return new MapRankRange(isInverted, start, end); } - throw new ParseException("Could not translate MapRankRange from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate MapRankRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java index 03f1448..75f6796 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; @@ -56,7 +56,7 @@ public static MapRankRangeRelative from(ConditionParser.MapRankRangeRelativeCont return new MapRankRangeRelative(isInverted, start, end, relativeValue); } - throw new ParseException("Could not translate MapRankRangeRelative from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate MapRankRangeRelative from ctx: %s".formatted(ctx)); } @Override @@ -71,7 +71,7 @@ public Exp constructExp(BasePath basePath, Exp.Type valueType, int cdtReturnType } else if (relative instanceof Integer rel) { relativeExp = Exp.val(rel); } else { - throw new ParseException("Unsupported value relative rank"); + throw new DslParseException("Unsupported value relative rank"); } Exp startExp = Exp.val(start); diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java index 1f8fdc5..afb183c 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import java.util.List; @@ -44,7 +44,7 @@ public static MapValueList from(ConditionParser.MapValueListContext ctx) { return new MapValueList(isInverted, valueListObjects); } - throw new ParseException("Could not translate MapValueList from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate MapValueList from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java index 9805f26..b300eec 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.path.BasePath; public class MapValueRange extends MapPart { @@ -38,7 +38,7 @@ public static MapValueRange from(ConditionParser.MapValueRangeContext ctx) { return new MapValueRange(isInverted, startValue, endValue); } - throw new ParseException("Could not translate MapValueRange from ctx: %s".formatted(ctx)); + throw new DslParseException("Could not translate MapValueRange from ctx: %s".formatted(ctx)); } @Override diff --git a/src/main/java/com/aerospike/dsl/util/ParsingUtils.java b/src/main/java/com/aerospike/dsl/util/ParsingUtils.java index 3fc46be..6b7c9f9 100644 --- a/src/main/java/com/aerospike/dsl/util/ParsingUtils.java +++ b/src/main/java/com/aerospike/dsl/util/ParsingUtils.java @@ -1,6 +1,6 @@ package com.aerospike.dsl.util; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import lombok.NonNull; import lombok.experimental.UtilityClass; @@ -35,13 +35,13 @@ public static Integer subtractNullable(Integer a, @NonNull Integer b) { * * @param methodName The method name string * @return The extracted type string - * @throws ParseException if the method name is not in the correct format + * @throws DslParseException if the method name is not in the correct format */ public static String extractTypeFromMethod(String methodName) { if (methodName.startsWith("as") && methodName.endsWith("()")) { return methodName.substring(2, methodName.length() - 2); } else { - throw new ParseException("Invalid method name: %s".formatted(methodName)); + throw new DslParseException("Invalid method name: %s".formatted(methodName)); } } diff --git a/src/main/java/com/aerospike/dsl/util/ValidationUtils.java b/src/main/java/com/aerospike/dsl/util/ValidationUtils.java index ab0cb24..3867a31 100644 --- a/src/main/java/com/aerospike/dsl/util/ValidationUtils.java +++ b/src/main/java/com/aerospike/dsl/util/ValidationUtils.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.util; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import lombok.experimental.UtilityClass; @UtilityClass @@ -14,7 +14,7 @@ public static void validateComparableTypes(Exp.Type leftType, Exp.Type rightType (leftType.equals(Exp.Type.FLOAT) && rightType.equals(Exp.Type.INT)); if (!leftType.equals(rightType) && !isIntAndFloat) { - throw new ParseException("Cannot compare %s to %s".formatted(leftType, rightType)); + throw new DslParseException("Cannot compare %s to %s".formatted(leftType, rightType)); } } } diff --git a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java index 4b68c82..1f76337 100644 --- a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java +++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java @@ -3,7 +3,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.dsl.ConditionBaseVisitor; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.*; import com.aerospike.dsl.parts.cdt.list.ListIndex; import com.aerospike.dsl.parts.cdt.list.ListIndexRange; @@ -96,7 +96,7 @@ public AbstractPart visitNotExpression(ConditionParser.NotExpressionContext ctx) @Override public AbstractPart visitExclusiveExpression(ConditionParser.ExclusiveExpressionContext ctx) { if (ctx.expression().size() < 2) { - throw new ParseException("Exclusive logical operator requires 2 or more expressions"); + throw new DslParseException("Exclusive logical operator requires 2 or more expressions"); } List expressions = new ArrayList<>(); // iterate through each definition @@ -313,13 +313,13 @@ public ListOperand readChildrenIntoListOperand(RuleNode listNode) { AbstractPart operand = visit(child); // delegate to a dedicated visitor if (operand == null) { - throw new ParseException("Unable to parse list operand"); + throw new DslParseException("Unable to parse list operand"); } try { values.add(((ParsedValueOperand) operand).getValue()); } catch (ClassCastException e) { - throw new ParseException("List constant contains elements of different type"); + throw new DslParseException("List constant contains elements of different type"); } } @@ -333,7 +333,7 @@ public AbstractPart visitOrderedMapConstant(ConditionParser.OrderedMapConstantCo public TreeMap getOrderedMapPair(ParseTree ctx) { if (ctx.getChild(0) == null || ctx.getChild(2) == null) { - throw new ParseException("Unable to parse map operand"); + throw new DslParseException("Unable to parse map operand"); } Object key = ((ParsedValueOperand) visit(ctx.getChild(0))).getValue(); Object value = ((ParsedValueOperand) visit(ctx.getChild(2))).getValue(); @@ -356,7 +356,7 @@ public MapOperand readChildrenIntoMapOperand(RuleNode mapNode) { try { mapOfPair.forEach(map::putIfAbsent); // put contents of the current map pair to the resulting map } catch (ClassCastException e) { - throw new ParseException("Map constant contains elements of different type"); + throw new DslParseException("Map constant contains elements of different type"); } } @@ -406,12 +406,12 @@ public AbstractPart visitBasePath(ConditionParser.BasePathContext ctx) { switch (part.getPartType()) { case BIN_PART -> binPart = (BinPart) overrideType(part, ctx); case LIST_PART, MAP_PART -> parts.add(overrideType(part, ctx)); - default -> throw new ParseException("Unexpected path part: %s".formatted(part.getPartType())); + default -> throw new DslParseException("Unexpected path part: %s".formatted(part.getPartType())); } } if (binPart == null) { - throw new ParseException("Expecting bin to be the first path part from the left"); + throw new DslParseException("Expecting bin to be the first path part from the left"); } return new BasePath(binPart, parts); @@ -484,7 +484,7 @@ public AbstractPart visitListPart(ConditionParser.ListPartContext ctx) { if (ctx.listRankRange() != null) return ListRankRange.from(ctx.listRankRange()); if (ctx.listRankRangeRelative() != null) return ListRankRangeRelative.from(ctx.listRankRangeRelative()); - throw new ParseException("Unexpected list part: %s".formatted(ctx.getText())); + throw new DslParseException("Unexpected list part: %s".formatted(ctx.getText())); } @Override @@ -504,7 +504,7 @@ public AbstractPart visitMapPart(ConditionParser.MapPartContext ctx) { return MapRankRangeRelative.from(ctx.mapRankRangeRelative()); if (ctx.mapIndexRangeRelative() != null) return MapIndexRangeRelative.from(ctx.mapIndexRangeRelative()); - throw new ParseException("Unexpected map part: %s".formatted(ctx.getText())); + throw new DslParseException("Unexpected map part: %s".formatted(ctx.getText())); } @Override diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index 13a78c4..0c6ebc7 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -5,7 +5,7 @@ import com.aerospike.client.query.IndexType; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.Index; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.exceptions.NoApplicableFilterException; import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.parts.ExpressionContainer; @@ -258,7 +258,7 @@ static boolean shouldVisitMapElement(int i, int size, ParseTree child) { * @param operator The binary operator to apply * @param binIsLeft Whether the bin is on the left side of the comparison * @return The resulting expression - * @throws ParseException if the operand type is not supported + * @throws DslParseException if the operand type is not supported */ private static Exp getExpBinComparison(BinPart binPart, AbstractPart otherPart, BinaryOperator operator, boolean binIsLeft) { @@ -300,7 +300,7 @@ private static Exp getExpBinComparison(BinPart binPart, AbstractPart otherPart, yield otherPart.getExp(); } default -> - throw new ParseException("Operand type not supported: %s".formatted(otherPart.getPartType())); + throw new DslParseException("Operand type not supported: %s".formatted(otherPart.getPartType())); }; return binIsLeft ? operator.apply(binExp, otherExp) : operator.apply(otherExp, binExp); @@ -312,7 +312,7 @@ private static Exp getExpBinComparison(BinPart binPart, AbstractPart otherPart, * @param binPart The {@link BinPart} involved in the comparison * @param stringOperand The {@link StringOperand} involved in the comparison * @return The {@link Exp} generated from the {@link StringOperand} - * @throws ParseException if type validation fails (e.g., comparing a non-string/blob bin with a String) + * @throws DslParseException if type validation fails (e.g., comparing a non-string/blob bin with a String) */ private static Exp handleStringOperandComparison(BinPart binPart, StringOperand stringOperand) { boolean isBlobType = binPart.getExpType() != null && binPart.getExpType().equals(Exp.Type.BLOB); @@ -334,7 +334,7 @@ private static Exp handleStringOperandComparison(BinPart binPart, StringOperand * @param right The {@link AbstractPart} on the right side of the comparison * @param operator The binary operator to apply * @return The resulting {@link Exp} for the comparison - * @throws ParseException if an unsupported operand type is encountered or type validation fails + * @throws DslParseException if an unsupported operand type is encountered or type validation fails */ private static Exp getExpLeftBinTypeComparison(BinPart left, AbstractPart right, BinaryOperator operator) { return getExpBinComparison(left, right, operator, true); @@ -347,7 +347,7 @@ private static Exp getExpLeftBinTypeComparison(BinPart left, AbstractPart right, * @param right The {@link BinPart} on the right side of the comparison * @param operator The binary operator to apply * @return The resulting {@link Exp} for the comparison - * @throws ParseException if an unsupported operand type is encountered or type validation fails + * @throws DslParseException if an unsupported operand type is encountered or type validation fails */ private static Exp getExpRightBinTypeComparison(AbstractPart left, BinPart right, BinaryOperator operator) { return getExpBinComparison(right, left, operator, false); @@ -405,7 +405,7 @@ private static ArithmeticTermType getFilterTermType(ExprPartsOperation operation * @return A {@link Pair} representing the lower and upper bounds of the range for the bin. * A {@code null} value in the pair indicates no bound on that side * @throws NoApplicableFilterException if division by zero occurs or the term type is unsupported - * @throws ParseException if undefined division (0/0) occurs + * @throws DslParseException if undefined division (0/0) occurs */ private static Pair getLimitsForDivisionForFilter(long left, long right, FilterOperationType type, ArithmeticTermType termType) { @@ -430,7 +430,7 @@ private static Pair getLimitsForDivisionForFilter(long left, long ri * @param operationType The type of the filter operation * @return A {@link Pair} representing the lower and upper bounds of the range for the bin. * A {@code null} value in the pair indicates no bound on that side - * @throws ParseException if undefined division (0/0) occurs or if the operation type is not supported + * @throws DslParseException if undefined division (0/0) occurs or if the operation type is not supported */ private static Pair LimitsForBinDividend(long left, long right, FilterOperationType operationType) { @@ -438,7 +438,7 @@ private static Pair LimitsForBinDividend(long left, long right, // both operands are positive return getLimitsForBinDividendWithLeftNumberPositive(operationType, left, right); } else if (left == 0 && right == 0) { - throw new ParseException("Undefined division for 0 / 0"); + throw new DslParseException("Undefined division for 0 / 0"); } else if (left < 0 && right < 0) { // both operands are negative return getLimitsForBinDividendWithLeftNumberNegative(operationType, left, right); @@ -449,7 +449,7 @@ private static Pair LimitsForBinDividend(long left, long right, // left negative, right positive return getLimitsForBinDividendWithLeftNumberNegative(operationType, left, right); } else if (left != 0) { - throw new ParseException("Division by zero is not allowed"); + throw new DslParseException("Division by zero is not allowed"); } else { return new Pair<>(null, null); } @@ -462,7 +462,7 @@ private static Pair LimitsForBinDividend(long left, long right, * @param left The value of the dividend * @param right The value of the divisor * @return A {@link Pair} representing the lower and upper bounds of the range for the bin - * @throws ParseException if the operation type is not supported for division + * @throws DslParseException if the operation type is not supported for division */ private static Pair getLimitsForBinDividendWithLeftNumberNegative(FilterOperationType operationType, long left, long right) { @@ -476,7 +476,7 @@ private static Pair getLimitsForBinDividendWithLeftNumberNegative(Fi case LTEQ: yield new Pair<>(left * right, Long.MAX_VALUE); default: - throw new ParseException("OperationType not supported for division: " + operationType); + throw new DslParseException("OperationType not supported for division: " + operationType); }; } @@ -487,7 +487,7 @@ private static Pair getLimitsForBinDividendWithLeftNumberNegative(Fi * @param left The value of the dividend * @param right The value of the divisor * @return A {@link Pair} representing the lower and upper bounds of the range for the bin - * @throws ParseException if the operation type is not supported for division + * @throws DslParseException if the operation type is not supported for division */ private static Pair getLimitsForBinDividendWithLeftNumberPositive(FilterOperationType operationType, long left, long right) { @@ -501,7 +501,7 @@ private static Pair getLimitsForBinDividendWithLeftNumberPositive(Fi case LTEQ: yield new Pair<>(Long.MIN_VALUE, left * right); default: - throw new ParseException("OperationType not supported for division: " + operationType); + throw new DslParseException("OperationType not supported for division: " + operationType); }; } @@ -513,7 +513,7 @@ private static Pair getLimitsForBinDividendWithLeftNumberPositive(Fi * @param operationType The type of the filter operation * @return A {@link Pair} representing the lower and upper bounds of the range for the bin. * A {@code null} value in the pair indicates no bound on that side - * @throws ParseException if division by zero occurs or if the operation type is not supported + * @throws DslParseException if division by zero occurs or if the operation type is not supported */ private static Pair getLimitsForBinDivisor(long left, long right, FilterOperationType operationType) { if (left > 0 && right > 0) { @@ -526,10 +526,10 @@ private static Pair getLimitsForBinDivisor(long left, long right, Fi case LT, LTEQ: yield new Pair<>(null, null); default: - throw new ParseException("OperationType not supported for division: " + operationType); + throw new DslParseException("OperationType not supported for division: " + operationType); }; } else if (left == 0 && right == 0) { - throw new ParseException("Cannot divide by zero"); + throw new DslParseException("Cannot divide by zero"); } else if (left < 0 && right < 0) { // both operands are negative return switch (operationType) { @@ -540,7 +540,7 @@ private static Pair getLimitsForBinDivisor(long left, long right, Fi case LTEQ: yield new Pair<>(1L, left / right); default: - throw new ParseException("OperationType not supported for division: " + operationType); + throw new DslParseException("OperationType not supported for division: " + operationType); }; } else if (left > 0 && right < 0) { // left positive, right negative @@ -552,7 +552,7 @@ private static Pair getLimitsForBinDivisor(long left, long right, Fi case LTEQ: yield new Pair<>(left / right, -1L); default: - throw new ParseException("OperationType not supported for division: " + operationType); + throw new DslParseException("OperationType not supported for division: " + operationType); }; } else if (right > 0 && left < 0) { // right positive, left negative @@ -564,10 +564,10 @@ private static Pair getLimitsForBinDivisor(long left, long right, Fi case LT, LTEQ: yield new Pair<>(null, null); default: - throw new ParseException("OperationType not supported for division: " + operationType); + throw new DslParseException("OperationType not supported for division: " + operationType); }; } else if (left != 0) { - throw new ParseException("Division by zero is not allowed"); + throw new DslParseException("Division by zero is not allowed"); } else { return new Pair<>(null, null); } @@ -581,14 +581,14 @@ private static Pair getLimitsForBinDivisor(long left, long right, Fi * A {@code null} value in the pair indicates no bound on that side * @param type The type of the filter operation * @return A {@link Filter} representing the condition - * @throws ParseException if the operation type is not supported for generating a filter + * @throws DslParseException if the operation type is not supported for generating a filter */ 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 ParseException("OperationType not supported for division: " + type); + default -> throw new DslParseException("OperationType not supported for division: " + type); }; } @@ -627,7 +627,7 @@ private static Filter getFilter(BinPart bin, AbstractPart operand, FilterOperati * @param type The type of the filter operation (must be {@link FilterOperationType#EQ}) * @return An Aerospike {@link Filter} for the string or blob comparison * @throws NoApplicableFilterException if the filter operation type is not equality - * @throws ParseException if type validation fails or base64 decoding fails + * @throws DslParseException if type validation fails or base64 decoding fails */ private static Filter handleStringOperand(BinPart bin, String binName, StringOperand operand, FilterOperationType type) { @@ -654,7 +654,7 @@ private static Filter handleStringOperand(BinPart bin, String binName, StringOpe * @param right The right operand * @param type The filter operation type * @return The appropriate Filter, or null if no filter can be created - * @throws ParseException if operands are invalid + * @throws DslParseException if operands are invalid */ private static Filter getFilterOrFail(AbstractPart left, AbstractPart right, FilterOperationType type) { validateOperands(left, right); @@ -689,7 +689,7 @@ private static Filter getFilterOrFail(AbstractPart left, AbstractPart right, Fil * @param otherOperand The other operand in the filter condition * @param type The type of the filter operation * @return A {@link Filter} if one can be generated from the nested expression, otherwise {@code null} - * @throws ParseException if operands within the nested expression are null + * @throws DslParseException if operands within the nested expression are null * @throws NoApplicableFilterException if the nested expression structure is not supported for filtering */ private static Filter handleExpressionOperand(ExpressionContainer expr, AbstractPart otherOperand, @@ -755,7 +755,7 @@ private static Filter getFilterFromExpressionOrFail(AbstractPart exprLeft, Abstr * @param binOnLeft {@code true} if the bin is on the left side of the arithmetic operation, {@code false} otherwise * @return A {@link Filter} for the arithmetic condition * @throws NoApplicableFilterException if operands are not integers or if the operation is not supported - * @throws ParseException if type validation fails + * @throws DslParseException if type validation fails */ private static Filter handleBinArithmeticExpression(BinPart bin, AbstractPart operand, AbstractPart externalOperand, @@ -783,14 +783,14 @@ private static Filter handleBinArithmeticExpression(BinPart bin, AbstractPart op * * @param left The left {@link AbstractPart} * @param right The right {@link AbstractPart} - * @throws ParseException if either the left or right operand is null + * @throws DslParseException if either the left or right operand is null */ private static void validateOperands(AbstractPart left, AbstractPart right) { if (left == null) { - throw new ParseException("Left operand cannot be null"); + throw new DslParseException("Left operand cannot be null"); } if (right == null) { - throw new ParseException("Right operand cannot be null"); + throw new DslParseException("Right operand cannot be null"); } } @@ -807,7 +807,7 @@ private static void validateOperands(AbstractPart left, AbstractPart right) { * @return A secondary index {@link Filter} * @throws NoApplicableFilterException if the operation is not supported by secondary index filters, * division by zero occurs, or the calculated range is invalid - * @throws ParseException if undefined division (0/0) occurs or other issues arise + * @throws DslParseException if undefined division (0/0) occurs or other issues arise */ private static Filter applyFilterOperator(String binName, IntOperand leftOperand, IntOperand rightOperand, ExprPartsOperation operationType, FilterOperationType type, @@ -1023,7 +1023,7 @@ private static Exp exclStructureToExp(ExpressionContainer expr) { * * @param expr The expression to process * @return The processed Exp - * @throws ParseException if left or right operands are null in a binary expression + * @throws DslParseException if left or right operands are null in a binary expression */ private static Exp processExpression(ExpressionContainer expr) { // For unary expressions @@ -1039,10 +1039,10 @@ private static Exp processExpression(ExpressionContainer expr) { AbstractPart left = expr.getLeft(); AbstractPart right = expr.getRight(); if (left == null) { - throw new ParseException("Unable to parse left operand"); + throw new DslParseException("Unable to parse left operand"); } if (right == null) { - throw new ParseException("Unable to parse right operand"); + throw new DslParseException("Unable to parse right operand"); } // Process operands diff --git a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java index 1b54719..4e45846 100644 --- a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; @@ -118,7 +118,7 @@ void intRShift() { @Test void negativeArithmetic() { assertThatThrownBy(() -> parseExp("($.apples.get(type: STRING) + 5) > 10")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessageContaining("Cannot compare STRING to INT"); // TODO: should throw an exception (cannot use arithmetic operations on Strings) diff --git a/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java index 83dd8c2..6cf2708 100644 --- a/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; @@ -59,7 +59,7 @@ void binNotEquals() { @Test void negativeStringBinEquals() { assertThatThrownBy(() -> parseExp("$.strBin == yes")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Unable to parse right operand"); } diff --git a/src/test/java/com/aerospike/dsl/expression/CastingTests.java b/src/test/java/com/aerospike/dsl/expression/CastingTests.java index 418c27e..be88196 100644 --- a/src/test/java/com/aerospike/dsl/expression/CastingTests.java +++ b/src/test/java/com/aerospike/dsl/expression/CastingTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; @@ -27,7 +27,7 @@ void intToFloatComparison() { @Test void negativeInvalidTypesComparison() { assertThatThrownBy(() -> parseExp("$.stringBin1.get(type: STRING) > $.intBin2.asFloat()")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessageContaining("Cannot compare STRING to FLOAT"); } } diff --git a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java index cc1e3ee..e04a31e 100644 --- a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import org.junit.jupiter.api.Test; import java.util.Base64; @@ -45,7 +45,7 @@ void stringComparisonNegativeTest() { // A String constant must be quoted assertThatThrownBy(() -> parseExpAndCompare("$.stringBin1.get(type: STRING) == yes", Exp.eq(Exp.stringBin("stringBin1"), Exp.val("yes")))) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Unable to parse right operand"); } @@ -82,7 +82,7 @@ void booleanComparison() { @Test void negativeBooleanComparison() { assertThatThrownBy(() -> parseExp("$.boolBin1.get(type: BOOL) == 5")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessageContaining("Cannot compare BOOL to INT"); } @@ -122,7 +122,7 @@ void listComparison_constantOnRightSide_NegativeTest() { parseExpAndCompare("$.listBin1.get(type: LIST) == [yes, of course]", Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of("yes", "of course")))) ) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Unable to parse list operand"); } @@ -162,7 +162,7 @@ void listComparison_constantOnLeftSide_NegativeTest() { parseExpAndCompare("[yes, of course] == $.listBin1.get(type: LIST)", Exp.eq(Exp.val(List.of("yes", "of course")), Exp.listBin("listBin1"))) ) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Could not parse given input, wrong syntax"); } @@ -228,14 +228,14 @@ void mapComparison_constantOnRightSide_NegativeTest() { parseExpAndCompare("$.mapBin1.get(type: MAP) == {yes, of course}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("yes", "of course")))) ) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Unable to parse map operand"); assertThatThrownBy(() -> parseExpAndCompare("$.mapBin1.get(type: MAP) == ['yes', 'of course']", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(List.of("yes", "of course")))) ) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Cannot compare MAP to LIST"); // Map key can only be Integer or String @@ -243,7 +243,7 @@ void mapComparison_constantOnRightSide_NegativeTest() { parseExpAndCompare("$.mapBin1.get(type: MAP) == {[100]:[100]}", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(List.of("yes", "of course")))) ) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Unable to parse map operand"); } @@ -293,14 +293,14 @@ void mapComparison_constantOnLeftSide_NegativeTest() { parseExpAndCompare("{yes, of course} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("of course", "yes")))) ) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Could not parse given input, wrong syntax"); assertThatThrownBy(() -> parseExpAndCompare("['yes', 'of course'] == $.mapBin1.get(type: MAP)", // incorrect: must be {} Exp.eq(Exp.val(List.of("yes", "of course")), Exp.mapBin("mapBin1"))) ) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Cannot compare MAP to LIST"); // Map key can only be Integer or String @@ -308,7 +308,7 @@ void mapComparison_constantOnLeftSide_NegativeTest() { parseExpAndCompare("{[100]:[100]} == $.mapBin1.get(type: MAP)", Exp.eq(Exp.val(List.of("yes", "of course")), Exp.mapBin("mapBin1"))) ) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Could not parse given input, wrong syntax"); } @@ -339,7 +339,7 @@ void twoBlobBinsComparison() { @Test void negativeTwoDifferentBinTypesComparison() { assertThatThrownBy(() -> parseExp("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessageContaining("Cannot compare STRING to FLOAT"); } diff --git a/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java index 8fc9c66..62fd77d 100644 --- a/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java @@ -4,7 +4,7 @@ import com.aerospike.client.cdt.ListReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import org.junit.jupiter.api.Test; import java.util.List; @@ -231,7 +231,7 @@ void listBinElementCount() { void negativeSyntaxList() { // TODO: throw meaningful exception (by ANTLR?) assertThatThrownBy(() -> parseExp("$.listBin1.[stringValue] == 100")) - .isInstanceOf(ParseException.class); + .isInstanceOf(DslParseException.class); } //@Test diff --git a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java index 7a2f400..c4e4c2f 100644 --- a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; @@ -82,19 +82,19 @@ void flatHierarchyAnd() { @Test void negativeSyntaxLogicalOperators() { assertThatThrownBy(() -> parseExp("($.intBin1 > 100 and ($.intBin2 > 100) or")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessageContaining("Could not parse given input"); assertThatThrownBy(() -> parseExp("and ($.intBin1 > 100 and ($.intBin2 > 100)")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessageContaining("Could not parse given input"); assertThatThrownBy(() -> parseExp("($.intBin1 > 100 and ($.intBin2 > 100) not")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessageContaining("Could not parse given input"); assertThatThrownBy(() -> parseExp("($.intBin1 > 100 and ($.intBin2 > 100) exclusive")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessageContaining("Could not parse given input"); } @@ -103,7 +103,7 @@ void negativeBinLogicalExclusiveWithOneParam() { assertThatThrownBy(() -> parseExpAndCompare("exclusive($.hand == \"hook\")", Exp.exclusive( Exp.eq(Exp.stringBin("hand"), Exp.val("hook"))))) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Exclusive logical operator requires 2 or more expressions"); } } diff --git a/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java index c9ca08b..f888a8f 100644 --- a/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java +++ b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; @@ -128,7 +128,7 @@ void ttl() { void negativeTtlAsDifferentType() { // TODO: should be supported when adding operator + metadata validations (requires a refactor) assertThatThrownBy(() -> parseExp("$.ttl() == true")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessageContaining("Expecting non-bin operand, got BOOL_OPERAND"); } diff --git a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java index f9c7868..f613026 100644 --- a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java @@ -4,7 +4,7 @@ import com.aerospike.client.query.IndexType; import com.aerospike.dsl.Index; import com.aerospike.dsl.IndexContext; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import org.junit.jupiter.api.Test; import java.util.Collection; @@ -49,7 +49,7 @@ void add() { assertThat(parseFilter("(5.2 + $.bananas) > 10.2")).isNull(); // not supported by secondary index filter assertThatThrownBy(() -> parseFilter("($.apples + $.bananas + 5) > 10")) - .isInstanceOf(ParseException.class) // not supported by the current grammar + .isInstanceOf(DslParseException.class) // not supported by the current grammar .hasMessageContaining("Could not parse given input, wrong syntax"); } @@ -86,7 +86,7 @@ void sub() { assertThat(parseFilter("($.apples - $.bananas) > 10")).isNull(); // not supported by secondary index filter assertThatThrownBy(() -> parseFilter("($.apples - $.bananas - 5) > 10")) - .isInstanceOf(ParseException.class) // not supported by the current grammar + .isInstanceOf(DslParseException.class) // not supported by the current grammar .hasMessageContaining("Could not parse given input, wrong syntax"); } @@ -127,7 +127,7 @@ void mul() { Filter.range("bananas", 0 / 9 + 1, Long.MAX_VALUE)); assertThatThrownBy(() -> parseFilter("($.apples * $.bananas - 5) > 10")) - .isInstanceOf(ParseException.class) // not supported by the current grammar + .isInstanceOf(DslParseException.class) // not supported by the current grammar .hasMessageContaining("Could not parse given input, wrong syntax"); } diff --git a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java index 7246be6..ee7cedb 100644 --- a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java @@ -4,7 +4,7 @@ import com.aerospike.client.query.IndexType; import com.aerospike.dsl.Index; import com.aerospike.dsl.IndexContext; -import com.aerospike.dsl.exceptions.ParseException; +import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.util.TestUtils; import org.junit.jupiter.api.Test; @@ -56,7 +56,7 @@ void stringComparison() { void stringComparisonNegativeTest() { // A String constant must be quoted assertThatThrownBy(() -> parseFilter("$.stringBin1.get(type: STRING) == yes")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Unable to parse right operand"); } @@ -89,7 +89,7 @@ void booleanComparison() { @Test void negativeBooleanComparison() { assertThatThrownBy(() -> parseFilter("$.boolBin1.get(type: BOOL) == 5")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Cannot compare BOOL to INT"); } @@ -102,7 +102,7 @@ void listComparison_constantOnRightSide() { @Test void listComparison_constantOnRightSide_NegativeTest() { assertThatThrownBy(() -> parseFilter("$.listBin1.get(type: LIST) == [yes, of course]")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Unable to parse list operand"); } @@ -114,7 +114,7 @@ void listComparison_constantOnLeftSide() { @Test void listComparison_constantOnLeftSide_NegativeTest() { assertThatThrownBy(() -> parseFilter("[yes, of course] == $.listBin1.get(type: LIST)")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Could not parse given input, wrong syntax"); } @@ -126,7 +126,7 @@ void mapComparison_constantOnRightSide() { @Test void mapComparison_constantOnRightSide_NegativeTest() { assertThatThrownBy(() -> parseFilter("$.mapBin1.get(type: MAP) == {yes, of course}")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Unable to parse map operand"); } @@ -138,7 +138,7 @@ void mapComparison_constantOnLeftSide() { @Test void mapComparison_constantOnLeftSide_NegativeTest() { assertThatThrownBy(() -> parseFilter("{yes, of course} == $.mapBin1.get(type: MAP)")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Could not parse given input, wrong syntax"); } @@ -165,7 +165,7 @@ void twoBlobBinsComparison() { @Test void negativeTwoDifferentBinTypesComparison() { assertThatThrownBy(() -> parseFilter("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)")) - .isInstanceOf(ParseException.class) + .isInstanceOf(DslParseException.class) .hasMessage("Cannot compare STRING to FLOAT"); } } diff --git a/src/test/java/com/aerospike/dsl/util/TestUtils.java b/src/test/java/com/aerospike/dsl/util/TestUtils.java index c5b95ed..75fd3e1 100644 --- a/src/test/java/com/aerospike/dsl/util/TestUtils.java +++ b/src/test/java/com/aerospike/dsl/util/TestUtils.java @@ -29,8 +29,8 @@ public static Filter parseFilter(String input) { return parser.parseExpression(input).getResult().getFilter(); } - public static Filter parseFilter(String input, IndexContext indexFilterInput) { - return parser.parseExpression(input, indexFilterInput).getResult().getFilter(); + public static Filter parseFilter(String input, IndexContext indexContext) { + return parser.parseExpression(input, indexContext).getResult().getFilter(); } public static void parseFilterAndCompare(String input, Filter expected) { @@ -38,8 +38,8 @@ public static void parseFilterAndCompare(String input, Filter expected) { assertEquals(actualFilter, expected); } - public static void parseFilterAndCompare(String input, IndexContext indexFilterInput, Filter expected) { - Filter actualFilter = parseFilter(input, indexFilterInput); + public static void parseFilterAndCompare(String input, IndexContext indexContext, Filter expected) { + Filter actualFilter = parseFilter(input, indexContext); assertEquals(actualFilter, expected); } @@ -50,8 +50,8 @@ public static void parseExpressionAndCompare(String input, Filter filter, Exp ex assertEquals(actualExp == null ? null : Exp.build(actualExp), exp == null ? null : Exp.build(exp)); } - public static void parseExpressionAndCompare(String input, Filter filter, Exp exp, IndexContext indexFilterInput) { - ParsedExpression actualExpression = parser.parseExpression(input, indexFilterInput); + public static void parseExpressionAndCompare(String input, Filter filter, Exp exp, IndexContext indexContext) { + ParsedExpression actualExpression = parser.parseExpression(input, indexContext); assertEquals(actualExpression.getResult().getFilter(), filter); Exp actualExp = actualExpression.getResult().getExp(); assertEquals(actualExp == null ? null : Exp.build(actualExp), exp == null ? null : Exp.build(exp)); From 2f71677e85fbf6a37b6823a691ac23c1a2a45e75 Mon Sep 17 00:00:00 2001 From: agrgr Date: Mon, 5 May 2025 21:26:00 +0300 Subject: [PATCH 17/20] refactor getParsedExpression() --- .../java/com/aerospike/dsl/DSLParserImpl.java | 48 ++++++++----------- .../dsl/expression/ExplicitTypesTests.java | 6 +-- .../expression/LogicalExpressionsTests.java | 8 ++-- .../dsl/filter/ArithmeticFiltersTests.java | 6 +-- .../dsl/filter/ExplicitTypesFiltersTests.java | 4 +- 5 files changed, 31 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/aerospike/dsl/DSLParserImpl.java b/src/main/java/com/aerospike/dsl/DSLParserImpl.java index 86c3bf1..19c51dc 100644 --- a/src/main/java/com/aerospike/dsl/DSLParserImpl.java +++ b/src/main/java/com/aerospike/dsl/DSLParserImpl.java @@ -9,11 +9,12 @@ import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTree; -import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; public class DSLParserImpl implements DSLParser { @@ -36,41 +37,30 @@ private ParseTree getParseTree(String input) { } private ParsedExpression getParsedExpression(ParseTree parseTree, IndexContext indexContext) { - String namespace; - Collection indexes; - if (indexContext != null) { - namespace = indexContext.getNamespace(); - indexes = indexContext.getIndexes(); - } else { - namespace = null; - indexes = null; - } + final String namespace = Optional.ofNullable(indexContext) + .map(IndexContext::getNamespace) + .orElse(null); + final Collection indexes = Optional.ofNullable(indexContext) + .map(IndexContext::getIndexes) + .orElse(Collections.emptyList()); - boolean hasFilterParsingError = false; - AbstractPart resultingPart = null; - Map> indexesMap = new HashMap<>(); + Map> indexesMap = indexes.stream() + // Filtering the indexes with the given namespace + .filter(idx -> idx.getNamespace() != null && idx.getNamespace().equals(namespace)) + // Group the indexes by bin name + .collect(Collectors.groupingBy(Index::getBin)); - if (indexes != null && !indexes.isEmpty()) { - indexes.forEach(idx -> { - // Filtering the indexes with the given namespace - if (idx.getNamespace() != null && idx.getNamespace().equals(namespace)) { - // Group the indexes by bin name - indexesMap.computeIfAbsent(idx.getBin(), k -> new ArrayList<>()).add(idx); - } - } - ); - } + AbstractPart resultingPart = null; try { resultingPart = new ExpressionConditionVisitor().visit(parseTree); - } catch (NoApplicableFilterException e) { - hasFilterParsingError = true; + } catch (NoApplicableFilterException ignored) { } // When we can't identify a specific case of syntax error, we throw a generic DSL syntax error - if (!hasFilterParsingError && resultingPart == null) { - throw new DslParseException("Could not parse given input, wrong syntax"); + if (resultingPart == null) { + throw new DslParseException("Could not parse given DSL expression input"); } - // Transfer the parsed tree along with namespace and indexes Map + // Return the parsed tree along with indexes Map return new ParsedExpression(resultingPart, indexesMap); } } diff --git a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java index e04a31e..1d7eaf7 100644 --- a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java @@ -163,7 +163,7 @@ void listComparison_constantOnLeftSide_NegativeTest() { Exp.eq(Exp.val(List.of("yes", "of course")), Exp.listBin("listBin1"))) ) .isInstanceOf(DslParseException.class) - .hasMessage("Could not parse given input, wrong syntax"); + .hasMessage("Could not parse given DSL expression input"); } @SuppressWarnings("unchecked") @@ -294,7 +294,7 @@ void mapComparison_constantOnLeftSide_NegativeTest() { Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("of course", "yes")))) ) .isInstanceOf(DslParseException.class) - .hasMessage("Could not parse given input, wrong syntax"); + .hasMessage("Could not parse given DSL expression input"); assertThatThrownBy(() -> parseExpAndCompare("['yes', 'of course'] == $.mapBin1.get(type: MAP)", // incorrect: must be {} @@ -309,7 +309,7 @@ void mapComparison_constantOnLeftSide_NegativeTest() { Exp.eq(Exp.val(List.of("yes", "of course")), Exp.mapBin("mapBin1"))) ) .isInstanceOf(DslParseException.class) - .hasMessage("Could not parse given input, wrong syntax"); + .hasMessage("Could not parse given DSL expression input"); } @Test diff --git a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java index c4e4c2f..1391579 100644 --- a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java @@ -83,19 +83,19 @@ void flatHierarchyAnd() { void negativeSyntaxLogicalOperators() { assertThatThrownBy(() -> parseExp("($.intBin1 > 100 and ($.intBin2 > 100) or")) .isInstanceOf(DslParseException.class) - .hasMessageContaining("Could not parse given input"); + .hasMessageContaining("Could not parse given DSL expression input"); assertThatThrownBy(() -> parseExp("and ($.intBin1 > 100 and ($.intBin2 > 100)")) .isInstanceOf(DslParseException.class) - .hasMessageContaining("Could not parse given input"); + .hasMessageContaining("Could not parse given DSL expression input"); assertThatThrownBy(() -> parseExp("($.intBin1 > 100 and ($.intBin2 > 100) not")) .isInstanceOf(DslParseException.class) - .hasMessageContaining("Could not parse given input"); + .hasMessageContaining("Could not parse given DSL expression input"); assertThatThrownBy(() -> parseExp("($.intBin1 > 100 and ($.intBin2 > 100) exclusive")) .isInstanceOf(DslParseException.class) - .hasMessageContaining("Could not parse given input"); + .hasMessageContaining("Could not parse given DSL expression input"); } @Test diff --git a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java index f613026..87b722a 100644 --- a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java @@ -50,7 +50,7 @@ void add() { assertThat(parseFilter("(5.2 + $.bananas) > 10.2")).isNull(); // not supported by secondary index filter assertThatThrownBy(() -> parseFilter("($.apples + $.bananas + 5) > 10")) .isInstanceOf(DslParseException.class) // not supported by the current grammar - .hasMessageContaining("Could not parse given input, wrong syntax"); + .hasMessageContaining("Could not parse given DSL expression input"); } @Test @@ -87,7 +87,7 @@ void sub() { assertThat(parseFilter("($.apples - $.bananas) > 10")).isNull(); // not supported by secondary index filter assertThatThrownBy(() -> parseFilter("($.apples - $.bananas - 5) > 10")) .isInstanceOf(DslParseException.class) // not supported by the current grammar - .hasMessageContaining("Could not parse given input, wrong syntax"); + .hasMessageContaining("Could not parse given DSL expression input"); } @Test @@ -128,7 +128,7 @@ void mul() { assertThatThrownBy(() -> parseFilter("($.apples * $.bananas - 5) > 10")) .isInstanceOf(DslParseException.class) // not supported by the current grammar - .hasMessageContaining("Could not parse given input, wrong syntax"); + .hasMessageContaining("Could not parse given DSL expression input"); } @Test diff --git a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java index ee7cedb..a2ce87f 100644 --- a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java @@ -115,7 +115,7 @@ void listComparison_constantOnLeftSide() { void listComparison_constantOnLeftSide_NegativeTest() { assertThatThrownBy(() -> parseFilter("[yes, of course] == $.listBin1.get(type: LIST)")) .isInstanceOf(DslParseException.class) - .hasMessage("Could not parse given input, wrong syntax"); + .hasMessage("Could not parse given DSL expression input"); } @Test @@ -139,7 +139,7 @@ void mapComparison_constantOnLeftSide() { void mapComparison_constantOnLeftSide_NegativeTest() { assertThatThrownBy(() -> parseFilter("{yes, of course} == $.mapBin1.get(type: MAP)")) .isInstanceOf(DslParseException.class) - .hasMessage("Could not parse given input, wrong syntax"); + .hasMessage("Could not parse given DSL expression input"); } @Test From a6ef29d8957b409ca6c8c6ab9cd7608dad091771 Mon Sep 17 00:00:00 2001 From: agrgr Date: Tue, 6 May 2025 18:57:28 +0300 Subject: [PATCH 18/20] make NoApplicableFilterException package-private, move exception classes --- src/main/java/com/aerospike/dsl/DSLParser.java | 1 - .../java/com/aerospike/dsl/DSLParserImpl.java | 8 +------- .../dsl/{exceptions => }/DslParseException.java | 2 +- .../java/com/aerospike/dsl/ParsedExpression.java | 1 - .../com/aerospike/dsl/parts/cdt/CdtPart.java | 2 +- .../dsl/parts/cdt/list/ListIndexRange.java | 2 +- .../aerospike/dsl/parts/cdt/list/ListPart.java | 2 +- .../dsl/parts/cdt/list/ListRankRange.java | 2 +- .../parts/cdt/list/ListRankRangeRelative.java | 2 +- .../dsl/parts/cdt/list/ListValueList.java | 2 +- .../dsl/parts/cdt/list/ListValueRange.java | 2 +- .../dsl/parts/cdt/map/MapIndexRange.java | 2 +- .../dsl/parts/cdt/map/MapIndexRangeRelative.java | 2 +- .../com/aerospike/dsl/parts/cdt/map/MapKey.java | 2 +- .../aerospike/dsl/parts/cdt/map/MapKeyList.java | 2 +- .../aerospike/dsl/parts/cdt/map/MapKeyRange.java | 2 +- .../dsl/parts/cdt/map/MapRankRange.java | 2 +- .../dsl/parts/cdt/map/MapRankRangeRelative.java | 2 +- .../dsl/parts/cdt/map/MapValueList.java | 2 +- .../dsl/parts/cdt/map/MapValueRange.java | 2 +- .../com/aerospike/dsl/util/ParsingUtils.java | 2 +- .../com/aerospike/dsl/util/ValidationUtils.java | 2 +- .../dsl/visitor/ExpressionConditionVisitor.java | 2 +- .../NoApplicableFilterException.java | 8 ++++---- .../com/aerospike/dsl/visitor/VisitorUtils.java | 16 +++++++--------- .../expression/ArithmeticExpressionsTests.java | 2 +- .../dsl/expression/BinExpressionsTests.java | 2 +- .../aerospike/dsl/expression/CastingTests.java | 2 +- .../dsl/expression/ExplicitTypesTests.java | 2 +- .../dsl/expression/ListExpressionsTests.java | 2 +- .../dsl/expression/LogicalExpressionsTests.java | 2 +- .../dsl/expression/RecordMetadataTests.java | 2 +- .../dsl/filter/ArithmeticFiltersTests.java | 2 +- .../dsl/filter/ExplicitTypesFiltersTests.java | 2 +- 34 files changed, 41 insertions(+), 51 deletions(-) rename src/main/java/com/aerospike/dsl/{exceptions => }/DslParseException.java (91%) rename src/main/java/com/aerospike/dsl/{exceptions => visitor}/NoApplicableFilterException.java (74%) diff --git a/src/main/java/com/aerospike/dsl/DSLParser.java b/src/main/java/com/aerospike/dsl/DSLParser.java index 0cb4419..98a87a6 100644 --- a/src/main/java/com/aerospike/dsl/DSLParser.java +++ b/src/main/java/com/aerospike/dsl/DSLParser.java @@ -1,7 +1,6 @@ package com.aerospike.dsl; import com.aerospike.client.query.Filter; -import com.aerospike.dsl.exceptions.DslParseException; /** * Contains API to convert dot separated String path into an Aerospike filter - diff --git a/src/main/java/com/aerospike/dsl/DSLParserImpl.java b/src/main/java/com/aerospike/dsl/DSLParserImpl.java index 19c51dc..7253ca0 100644 --- a/src/main/java/com/aerospike/dsl/DSLParserImpl.java +++ b/src/main/java/com/aerospike/dsl/DSLParserImpl.java @@ -1,8 +1,6 @@ package com.aerospike.dsl; import com.aerospike.dsl.annotation.Beta; -import com.aerospike.dsl.exceptions.DslParseException; -import com.aerospike.dsl.exceptions.NoApplicableFilterException; import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.visitor.ExpressionConditionVisitor; import org.antlr.v4.runtime.CharStreams; @@ -50,11 +48,7 @@ private ParsedExpression getParsedExpression(ParseTree parseTree, IndexContext i // Group the indexes by bin name .collect(Collectors.groupingBy(Index::getBin)); - AbstractPart resultingPart = null; - try { - resultingPart = new ExpressionConditionVisitor().visit(parseTree); - } catch (NoApplicableFilterException ignored) { - } + AbstractPart resultingPart = new ExpressionConditionVisitor().visit(parseTree); // When we can't identify a specific case of syntax error, we throw a generic DSL syntax error if (resultingPart == null) { diff --git a/src/main/java/com/aerospike/dsl/exceptions/DslParseException.java b/src/main/java/com/aerospike/dsl/DslParseException.java similarity index 91% rename from src/main/java/com/aerospike/dsl/exceptions/DslParseException.java rename to src/main/java/com/aerospike/dsl/DslParseException.java index 3c4eed2..0668285 100644 --- a/src/main/java/com/aerospike/dsl/exceptions/DslParseException.java +++ b/src/main/java/com/aerospike/dsl/DslParseException.java @@ -1,4 +1,4 @@ -package com.aerospike.dsl.exceptions; +package com.aerospike.dsl; /** * Represents a general processing exception that can occur during DSL expression parsing. diff --git a/src/main/java/com/aerospike/dsl/ParsedExpression.java b/src/main/java/com/aerospike/dsl/ParsedExpression.java index 06c77c9..a01ffb0 100644 --- a/src/main/java/com/aerospike/dsl/ParsedExpression.java +++ b/src/main/java/com/aerospike/dsl/ParsedExpression.java @@ -3,7 +3,6 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.query.Filter; import com.aerospike.dsl.annotation.Beta; -import com.aerospike.dsl.exceptions.DslParseException; import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.parts.ExpressionContainer; import lombok.Getter; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java b/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java index e226681..4e14758 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/CdtPart.java @@ -2,7 +2,7 @@ import com.aerospike.client.cdt.CTX; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.parts.path.BasePath; import com.aerospike.dsl.parts.path.PathFunction; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java index 0c02060..1b4d24f 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListIndexRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java index f9bad98..fa9911e 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListPart.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.parts.cdt.list; import com.aerospike.client.cdt.ListReturnType; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.PathFunction; import com.aerospike.dsl.parts.cdt.CdtPart; import lombok.Getter; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java index 4cf34e8..5e3c14d 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java index d5beeac..297a5dd 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java index b9355f7..a1a3cc4 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueList.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java index ab9e6c7..51254f0 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListValueRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; public class ListValueRange extends ListPart { diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java index 7a2b985..4015869 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java index 914a3bf..b33628f 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapIndexRangeRelative.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java index ba636fd..2f4b0ba 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKey.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java index f89eda1..3b43e6b 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyList.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java index 3e22d60..11dbc98 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapKeyRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import java.util.Optional; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java index d236e27..ab6f81c 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.subtractNullable; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java index 75f6796..e703569 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapRankRangeRelative.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import static com.aerospike.dsl.util.ParsingUtils.unquote; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java index afb183c..da3cdfd 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueList.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; import java.util.List; diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java index b300eec..8cf5031 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/map/MapValueRange.java @@ -5,7 +5,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.MapExp; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.path.BasePath; public class MapValueRange extends MapPart { diff --git a/src/main/java/com/aerospike/dsl/util/ParsingUtils.java b/src/main/java/com/aerospike/dsl/util/ParsingUtils.java index 6b7c9f9..949384b 100644 --- a/src/main/java/com/aerospike/dsl/util/ParsingUtils.java +++ b/src/main/java/com/aerospike/dsl/util/ParsingUtils.java @@ -1,6 +1,6 @@ package com.aerospike.dsl.util; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import lombok.NonNull; import lombok.experimental.UtilityClass; diff --git a/src/main/java/com/aerospike/dsl/util/ValidationUtils.java b/src/main/java/com/aerospike/dsl/util/ValidationUtils.java index 3867a31..f707b9c 100644 --- a/src/main/java/com/aerospike/dsl/util/ValidationUtils.java +++ b/src/main/java/com/aerospike/dsl/util/ValidationUtils.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.util; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import lombok.experimental.UtilityClass; @UtilityClass diff --git a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java index 1f76337..a7506b4 100644 --- a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java +++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java @@ -3,7 +3,7 @@ import com.aerospike.client.exp.Exp; import com.aerospike.dsl.ConditionBaseVisitor; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.*; import com.aerospike.dsl.parts.cdt.list.ListIndex; import com.aerospike.dsl.parts.cdt.list.ListIndexRange; diff --git a/src/main/java/com/aerospike/dsl/exceptions/NoApplicableFilterException.java b/src/main/java/com/aerospike/dsl/visitor/NoApplicableFilterException.java similarity index 74% rename from src/main/java/com/aerospike/dsl/exceptions/NoApplicableFilterException.java rename to src/main/java/com/aerospike/dsl/visitor/NoApplicableFilterException.java index 58a734a..4b6813e 100644 --- a/src/main/java/com/aerospike/dsl/exceptions/NoApplicableFilterException.java +++ b/src/main/java/com/aerospike/dsl/visitor/NoApplicableFilterException.java @@ -1,9 +1,9 @@ -package com.aerospike.dsl.exceptions; +package com.aerospike.dsl.visitor; import com.aerospike.client.query.Filter; /** - * Indicates that no applicable {@link Filter} could be generated for a given DSL expression. + * Indicates that no applicable {@link Filter} could be generated for a given DSL expression. For internal use. * *

This exception is typically thrown when attempting to create a Filter for a DSL expression * but the structure or types of the expression do not match any supported filtering patterns @@ -11,9 +11,9 @@ * It signifies that while the expression might be valid in a broader context, it cannot be represented with a * secondary index Filter. */ -public class NoApplicableFilterException extends RuntimeException { +class NoApplicableFilterException extends RuntimeException { - public NoApplicableFilterException(String description) { + NoApplicableFilterException(String description) { super(description); } } diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index 0c6ebc7..4f4c2f4 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -5,8 +5,7 @@ import com.aerospike.client.query.IndexType; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.Index; -import com.aerospike.dsl.exceptions.DslParseException; -import com.aerospike.dsl.exceptions.NoApplicableFilterException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.parts.ExpressionContainer; import com.aerospike.dsl.parts.ExpressionContainer.ExprPartsOperation; @@ -299,8 +298,7 @@ private static Exp getExpBinComparison(BinPart binPart, AbstractPart otherPart, validateComparableTypes(binPart.getExpType(), Exp.Type.MAP); yield otherPart.getExp(); } - default -> - throw new DslParseException("Operand type not supported: %s".formatted(otherPart.getPartType())); + default -> throw new DslParseException("Operand type not supported: %s".formatted(otherPart.getPartType())); }; return binIsLeft ? operator.apply(binExp, otherExp) : operator.apply(otherExp, binExp); @@ -405,7 +403,7 @@ private static ArithmeticTermType getFilterTermType(ExprPartsOperation operation * @return A {@link Pair} representing the lower and upper bounds of the range for the bin. * A {@code null} value in the pair indicates no bound on that side * @throws NoApplicableFilterException if division by zero occurs or the term type is unsupported - * @throws DslParseException if undefined division (0/0) occurs + * @throws DslParseException if undefined division (0/0) occurs */ private static Pair getLimitsForDivisionForFilter(long left, long right, FilterOperationType type, ArithmeticTermType termType) { @@ -627,7 +625,7 @@ private static Filter getFilter(BinPart bin, AbstractPart operand, FilterOperati * @param type The type of the filter operation (must be {@link FilterOperationType#EQ}) * @return An Aerospike {@link Filter} for the string or blob comparison * @throws NoApplicableFilterException if the filter operation type is not equality - * @throws DslParseException if type validation fails or base64 decoding fails + * @throws DslParseException if type validation fails or base64 decoding fails */ private static Filter handleStringOperand(BinPart bin, String binName, StringOperand operand, FilterOperationType type) { @@ -689,7 +687,7 @@ private static Filter getFilterOrFail(AbstractPart left, AbstractPart right, Fil * @param otherOperand The other operand in the filter condition * @param type The type of the filter operation * @return A {@link Filter} if one can be generated from the nested expression, otherwise {@code null} - * @throws DslParseException if operands within the nested expression are null + * @throws DslParseException if operands within the nested expression are null * @throws NoApplicableFilterException if the nested expression structure is not supported for filtering */ private static Filter handleExpressionOperand(ExpressionContainer expr, AbstractPart otherOperand, @@ -755,7 +753,7 @@ private static Filter getFilterFromExpressionOrFail(AbstractPart exprLeft, Abstr * @param binOnLeft {@code true} if the bin is on the left side of the arithmetic operation, {@code false} otherwise * @return A {@link Filter} for the arithmetic condition * @throws NoApplicableFilterException if operands are not integers or if the operation is not supported - * @throws DslParseException if type validation fails + * @throws DslParseException if type validation fails */ private static Filter handleBinArithmeticExpression(BinPart bin, AbstractPart operand, AbstractPart externalOperand, @@ -807,7 +805,7 @@ private static void validateOperands(AbstractPart left, AbstractPart right) { * @return A secondary index {@link Filter} * @throws NoApplicableFilterException if the operation is not supported by secondary index filters, * division by zero occurs, or the calculated range is invalid - * @throws DslParseException if undefined division (0/0) occurs or other issues arise + * @throws DslParseException if undefined division (0/0) occurs or other issues arise */ private static Filter applyFilterOperator(String binName, IntOperand leftOperand, IntOperand rightOperand, ExprPartsOperation operationType, FilterOperationType type, diff --git a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java index 4e45846..ec13080 100644 --- a/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; diff --git a/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java index 6cf2708..1342b8b 100644 --- a/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; diff --git a/src/test/java/com/aerospike/dsl/expression/CastingTests.java b/src/test/java/com/aerospike/dsl/expression/CastingTests.java index be88196..398664e 100644 --- a/src/test/java/com/aerospike/dsl/expression/CastingTests.java +++ b/src/test/java/com/aerospike/dsl/expression/CastingTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; diff --git a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java index 1d7eaf7..d74a480 100644 --- a/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import org.junit.jupiter.api.Test; import java.util.Base64; diff --git a/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java index 62fd77d..1f5d96f 100644 --- a/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java @@ -4,7 +4,7 @@ import com.aerospike.client.cdt.ListReturnType; import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import org.junit.jupiter.api.Test; import java.util.List; diff --git a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java index 1391579..ff6c344 100644 --- a/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java +++ b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; diff --git a/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java index f888a8f..5f7557e 100644 --- a/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java +++ b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java @@ -1,7 +1,7 @@ package com.aerospike.dsl.expression; import com.aerospike.client.exp.Exp; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import org.junit.jupiter.api.Test; import static com.aerospike.dsl.util.TestUtils.parseExp; diff --git a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java index 87b722a..f2aa56d 100644 --- a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java @@ -4,7 +4,7 @@ import com.aerospike.client.query.IndexType; import com.aerospike.dsl.Index; import com.aerospike.dsl.IndexContext; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import org.junit.jupiter.api.Test; import java.util.Collection; diff --git a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java index a2ce87f..f46d98e 100644 --- a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java +++ b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java @@ -4,7 +4,7 @@ import com.aerospike.client.query.IndexType; import com.aerospike.dsl.Index; import com.aerospike.dsl.IndexContext; -import com.aerospike.dsl.exceptions.DslParseException; +import com.aerospike.dsl.DslParseException; import com.aerospike.dsl.util.TestUtils; import org.junit.jupiter.api.Test; From e68a057b7d5d454d242d14dd9add822f65a17fc3 Mon Sep 17 00:00:00 2001 From: agrgr Date: Wed, 7 May 2025 17:28:10 +0300 Subject: [PATCH 19/20] rename variables, clean up Javadoc --- src/main/java/com/aerospike/dsl/DSLParser.java | 2 +- .../com/aerospike/dsl/parts/ExpressionContainer.java | 2 +- .../java/com/aerospike/dsl/visitor/VisitorUtils.java | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/aerospike/dsl/DSLParser.java b/src/main/java/com/aerospike/dsl/DSLParser.java index 98a87a6..6f48081 100644 --- a/src/main/java/com/aerospike/dsl/DSLParser.java +++ b/src/main/java/com/aerospike/dsl/DSLParser.java @@ -158,7 +158,7 @@ public interface DSLParser { * @param indexContext Class containing namespace and collection of {@link Index} objects that represent * existing secondary indexes. Required for creating {@link Filter}. Can be null * @return {@link ParsedExpression} object - * @throws DslParseException in case of or invalid syntax + * @throws DslParseException in case of invalid syntax */ ParsedExpression parseExpression(String dslString, IndexContext indexContext); } diff --git a/src/main/java/com/aerospike/dsl/parts/ExpressionContainer.java b/src/main/java/com/aerospike/dsl/parts/ExpressionContainer.java index 92e0a5c..d5ba17e 100644 --- a/src/main/java/com/aerospike/dsl/parts/ExpressionContainer.java +++ b/src/main/java/com/aerospike/dsl/parts/ExpressionContainer.java @@ -13,7 +13,7 @@ public class ExpressionContainer extends AbstractPart { private final ExprPartsOperation operationType; @Setter() @Accessors(fluent = true) - private boolean hasSIndexFilter; + private boolean hasSecondaryIndexFilter; public ExpressionContainer() { super(PartType.EXPRESSION_CONTAINER); diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index 4f4c2f4..260ddf9 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -931,12 +931,12 @@ private static FilterOperationType invertType(FilterOperationType type) { */ public static AbstractPart buildExpr(ExpressionContainer expr, Map> indexes) { Exp exp; - Filter sIndexFilter = null; + Filter secondaryIndexFilter = null; try { - sIndexFilter = getSIFilter(expr, indexes); + secondaryIndexFilter = getSIFilter(expr, indexes); } catch (NoApplicableFilterException ignored) { } - expr.setFilter(sIndexFilter); + expr.setFilter(secondaryIndexFilter); exp = getFilterExp(expr); expr.setExp(exp); @@ -952,7 +952,7 @@ public static AbstractPart buildExpr(ExpressionContainer expr, Map withStructureToExp(expr); @@ -1165,12 +1165,12 @@ private static ExpressionContainer chooseExprForFilter(ExpressionContainer exprC chosenExpr = largestCardinalityExprs.stream() .min(Comparator.comparing(expr -> getBinPart(expr, 1).getBinName())) .orElse(null); - chosenExpr.hasSIndexFilter(true); + chosenExpr.hasSecondaryIndexFilter(true); return chosenExpr; } // There is only one expression with the largest cardinality chosenExpr = largestCardinalityExprs.get(0); - chosenExpr.hasSIndexFilter(true); + chosenExpr.hasSecondaryIndexFilter(true); return chosenExpr; } From 21447c56ccab71e89faafff754dee0ac9f1b3b2d Mon Sep 17 00:00:00 2001 From: yrizhkov Date: Thu, 8 May 2025 12:03:19 +0300 Subject: [PATCH 20/20] refactor code --- .../com/aerospike/dsl/ParsedExpression.java | 4 +- .../parts/cdt/list/ListRankRangeRelative.java | 1 + .../dsl/parts/operand/BooleanOperand.java | 1 + .../dsl/parts/operand/FloatOperand.java | 1 + .../dsl/parts/operand/IntOperand.java | 1 + .../dsl/parts/operand/ListOperand.java | 1 + .../dsl/parts/operand/MapOperand.java | 7 +- .../dsl/parts/operand/MetadataOperand.java | 1 + .../dsl/parts/operand/StringOperand.java | 1 + .../dsl/parts/operand/VariableOperand.java | 1 + .../com/aerospike/dsl/parts/path/BinPart.java | 1 + .../com/aerospike/dsl/parts/path/Path.java | 6 +- .../visitor/ExpressionConditionVisitor.java | 48 ++++---- .../aerospike/dsl/visitor/VisitorUtils.java | 114 ++++++++++-------- 14 files changed, 107 insertions(+), 81 deletions(-) diff --git a/src/main/java/com/aerospike/dsl/ParsedExpression.java b/src/main/java/com/aerospike/dsl/ParsedExpression.java index a01ffb0..eb4f845 100644 --- a/src/main/java/com/aerospike/dsl/ParsedExpression.java +++ b/src/main/java/com/aerospike/dsl/ParsedExpression.java @@ -46,8 +46,8 @@ public ParseResult getResult() { private ParseResult getParseResult() { if (expressionTree != null) { if (expressionTree.getPartType() == EXPRESSION_CONTAINER) { - AbstractPart result = buildExpr((ExpressionContainer) expressionTree, indexesMap); - return new ParseResult(result.getFilter(), result.getExp()); + AbstractPart resultPart = buildExpr((ExpressionContainer) expressionTree, indexesMap); + return new ParseResult(resultPart.getFilter(), resultPart.getExp()); } else { Filter filter = expressionTree.getFilter(); Exp exp = expressionTree.getExp(); diff --git a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java index 297a5dd..98ac1dc 100644 --- a/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java +++ b/src/main/java/com/aerospike/dsl/parts/cdt/list/ListRankRangeRelative.java @@ -81,6 +81,7 @@ public Exp constructExp(BasePath basePath, Exp.Type valueType, int cdtReturnType Exp.bin(basePath.getBinPart().getBinName(), basePath.getBinType()), context); } + return ListExp.getByValueRelativeRankRange(cdtReturnType, startExp, relativeExp, Exp.val(count), Exp.bin(basePath.getBinPart().getBinName(), basePath.getBinType()), context); diff --git a/src/main/java/com/aerospike/dsl/parts/operand/BooleanOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/BooleanOperand.java index b98dc1c..18ea4fc 100644 --- a/src/main/java/com/aerospike/dsl/parts/operand/BooleanOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/BooleanOperand.java @@ -14,6 +14,7 @@ public BooleanOperand(Boolean value) { this.value = value; } + @Override public Exp getExp() { return Exp.val(value); } diff --git a/src/main/java/com/aerospike/dsl/parts/operand/FloatOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/FloatOperand.java index f2a98a0..5c843c6 100644 --- a/src/main/java/com/aerospike/dsl/parts/operand/FloatOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/FloatOperand.java @@ -14,6 +14,7 @@ public FloatOperand(Double value) { this.value = value; } + @Override public Exp getExp() { return Exp.val(value); } diff --git a/src/main/java/com/aerospike/dsl/parts/operand/IntOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/IntOperand.java index 2ed5cdc..e8405f6 100644 --- a/src/main/java/com/aerospike/dsl/parts/operand/IntOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/IntOperand.java @@ -14,6 +14,7 @@ public IntOperand(Long value) { this.value = value; } + @Override public Exp getExp() { return Exp.val(value); } diff --git a/src/main/java/com/aerospike/dsl/parts/operand/ListOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/ListOperand.java index fb7c859..afc5b3e 100644 --- a/src/main/java/com/aerospike/dsl/parts/operand/ListOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/ListOperand.java @@ -16,6 +16,7 @@ public ListOperand(List list) { this.value = list; } + @Override public Exp getExp() { return Exp.val(value); } diff --git a/src/main/java/com/aerospike/dsl/parts/operand/MapOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/MapOperand.java index aa640a8..4a6efd9 100644 --- a/src/main/java/com/aerospike/dsl/parts/operand/MapOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/MapOperand.java @@ -4,18 +4,19 @@ import com.aerospike.dsl.parts.AbstractPart; import lombok.Getter; -import java.util.TreeMap; +import java.util.SortedMap; @Getter public class MapOperand extends AbstractPart implements ParsedValueOperand { - private final TreeMap value; + private final SortedMap value; - public MapOperand(TreeMap map) { + public MapOperand(SortedMap map) { super(PartType.MAP_OPERAND); this.value = map; } + @Override public Exp getExp() { return Exp.val(value); } diff --git a/src/main/java/com/aerospike/dsl/parts/operand/MetadataOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/MetadataOperand.java index ba88c92..3b3c18c 100644 --- a/src/main/java/com/aerospike/dsl/parts/operand/MetadataOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/MetadataOperand.java @@ -41,6 +41,7 @@ private Exp constructMetadataExp(String functionName, Integer parameter) { }; } + @Override public Exp getExp() { return constructMetadataExp(functionName, parameter); } diff --git a/src/main/java/com/aerospike/dsl/parts/operand/StringOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/StringOperand.java index 6ecd067..a33303b 100644 --- a/src/main/java/com/aerospike/dsl/parts/operand/StringOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/StringOperand.java @@ -19,6 +19,7 @@ public StringOperand(String string) { this.value = string; } + @Override public Exp getExp() { if (isBlob) { byte[] byteValue = Base64.getDecoder().decode(value); diff --git a/src/main/java/com/aerospike/dsl/parts/operand/VariableOperand.java b/src/main/java/com/aerospike/dsl/parts/operand/VariableOperand.java index a065422..d15652c 100644 --- a/src/main/java/com/aerospike/dsl/parts/operand/VariableOperand.java +++ b/src/main/java/com/aerospike/dsl/parts/operand/VariableOperand.java @@ -14,6 +14,7 @@ public VariableOperand(String name) { this.value = name; } + @Override public Exp getExp() { return Exp.var(value); } diff --git a/src/main/java/com/aerospike/dsl/parts/path/BinPart.java b/src/main/java/com/aerospike/dsl/parts/path/BinPart.java index 7d78ded..4f0b9cb 100644 --- a/src/main/java/com/aerospike/dsl/parts/path/BinPart.java +++ b/src/main/java/com/aerospike/dsl/parts/path/BinPart.java @@ -20,6 +20,7 @@ public void updateExp(Exp.Type expType) { this.expType = expType; } + @Override public Exp getExp() { return Exp.bin(this.binName, expType); } diff --git a/src/main/java/com/aerospike/dsl/parts/path/Path.java b/src/main/java/com/aerospike/dsl/parts/path/Path.java index 97e6339..328927c 100644 --- a/src/main/java/com/aerospike/dsl/parts/path/Path.java +++ b/src/main/java/com/aerospike/dsl/parts/path/Path.java @@ -33,8 +33,9 @@ public Exp processPath(BasePath basePath, PathFunction pathFunction) { Exp.Type valueType = processValueType(lastPathPart, pathFunction); int cdtReturnType = 0; - if (lastPathPart instanceof CdtPart lastPart) cdtReturnType = - lastPart.getReturnType(pathFunction.getReturnParam()); + if (lastPathPart instanceof CdtPart lastPart) { + cdtReturnType = lastPart.getReturnType(pathFunction.getReturnParam()); + } if (lastPathPart != null) { // only if there are other parts except a bin return switch (pathFunction.getPathFunctionType()) { @@ -46,6 +47,7 @@ public Exp processPath(BasePath basePath, PathFunction pathFunction) { return null; } + @Override public Exp getExp() { return processPath(basePath, pathFunction); } diff --git a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java index a7506b4..3be45a8 100644 --- a/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java +++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java @@ -4,21 +4,14 @@ import com.aerospike.dsl.ConditionBaseVisitor; import com.aerospike.dsl.ConditionParser; import com.aerospike.dsl.DslParseException; -import com.aerospike.dsl.parts.*; -import com.aerospike.dsl.parts.cdt.list.ListIndex; -import com.aerospike.dsl.parts.cdt.list.ListIndexRange; -import com.aerospike.dsl.parts.cdt.list.ListRank; -import com.aerospike.dsl.parts.cdt.list.ListRankRange; -import com.aerospike.dsl.parts.cdt.list.ListRankRangeRelative; -import com.aerospike.dsl.parts.cdt.list.ListTypeDesignator; -import com.aerospike.dsl.parts.cdt.list.ListValue; -import com.aerospike.dsl.parts.cdt.list.ListValueList; -import com.aerospike.dsl.parts.cdt.list.ListValueRange; +import com.aerospike.dsl.parts.AbstractPart; +import com.aerospike.dsl.parts.ExpressionContainer; +import com.aerospike.dsl.parts.cdt.list.*; import com.aerospike.dsl.parts.cdt.map.*; -import com.aerospike.dsl.parts.operand.*; import com.aerospike.dsl.parts.controlstructure.ExclusiveStructure; import com.aerospike.dsl.parts.controlstructure.WhenStructure; import com.aerospike.dsl.parts.controlstructure.WithStructure; +import com.aerospike.dsl.parts.operand.*; import com.aerospike.dsl.parts.path.BasePath; import com.aerospike.dsl.parts.path.BinPart; import com.aerospike.dsl.parts.path.Path; @@ -29,10 +22,20 @@ import java.util.ArrayList; import java.util.List; +import java.util.SortedMap; import java.util.TreeMap; -import static com.aerospike.dsl.util.ParsingUtils.*; -import static com.aerospike.dsl.visitor.VisitorUtils.*; +import static com.aerospike.dsl.util.ParsingUtils.extractFunctionName; +import static com.aerospike.dsl.util.ParsingUtils.extractParameter; +import static com.aerospike.dsl.util.ParsingUtils.extractTypeFromMethod; +import static com.aerospike.dsl.util.ParsingUtils.unquote; +import static com.aerospike.dsl.visitor.VisitorUtils.detectImplicitTypeFromUpperTree; +import static com.aerospike.dsl.visitor.VisitorUtils.extractVariableNameOrFail; +import static com.aerospike.dsl.visitor.VisitorUtils.getPathFunctionParam; +import static com.aerospike.dsl.visitor.VisitorUtils.logicalSetBinAsBooleanExpr; +import static com.aerospike.dsl.visitor.VisitorUtils.logicalSetBinsAsBooleanExpr; +import static com.aerospike.dsl.visitor.VisitorUtils.shouldVisitListElement; +import static com.aerospike.dsl.visitor.VisitorUtils.shouldVisitMapElement; public class ExpressionConditionVisitor extends ConditionBaseVisitor { @@ -331,27 +334,30 @@ public AbstractPart visitOrderedMapConstant(ConditionParser.OrderedMapConstantCo return readChildrenIntoMapOperand(ctx); } - public TreeMap getOrderedMapPair(ParseTree ctx) { + public SortedMap getOrderedMapPair(ParseTree ctx) { if (ctx.getChild(0) == null || ctx.getChild(2) == null) { throw new DslParseException("Unable to parse map operand"); } + Object key = ((ParsedValueOperand) visit(ctx.getChild(0))).getValue(); Object value = ((ParsedValueOperand) visit(ctx.getChild(2))).getValue(); - TreeMap map = new TreeMap<>(); + + SortedMap map = new TreeMap<>(); map.put(key, value); + return map; } public MapOperand readChildrenIntoMapOperand(RuleNode mapNode) { int size = mapNode.getChildCount(); - TreeMap map = new TreeMap<>(); + SortedMap map = new TreeMap<>(); for (int i = 0; i < size; i++) { ParseTree child = mapNode.getChild(i); if (!shouldVisitMapElement(i, size, child)) { continue; } - TreeMap mapOfPair = getOrderedMapPair(child); // delegate to a dedicated visitor + SortedMap mapOfPair = getOrderedMapPair(child); // delegate to a dedicated visitor try { mapOfPair.forEach(map::putIfAbsent); // put contents of the current map pair to the resulting map @@ -434,8 +440,8 @@ private AbstractPart overrideType(AbstractPart part, ParseTree ctx) { if (pathFunction != null) { Exp.Type type = pathFunction.getBinType(); if (type != null) { - if (part instanceof BinPart) { - ((BinPart) part).updateExp(type); + if (part instanceof BinPart binPart) { + binPart.updateExp(type); } else { part.setExpType(type); } @@ -443,11 +449,11 @@ private AbstractPart overrideType(AbstractPart part, ParseTree ctx) { } } else { // Override using Implicit type detection Exp.Type implicitType = detectImplicitTypeFromUpperTree(ctx); - if (part instanceof BinPart) { + if (part instanceof BinPart binPart) { if (implicitType == null) { implicitType = Exp.Type.INT; } - ((BinPart) part).updateExp(implicitType); + binPart.updateExp(implicitType); } else { // ListPart or MapPart if (implicitType == null) { implicitType = TypeUtils.getDefaultType(part); diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java index 260ddf9..a954924 100644 --- a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java +++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java @@ -4,8 +4,8 @@ import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.dsl.ConditionParser; -import com.aerospike.dsl.Index; import com.aerospike.dsl.DslParseException; +import com.aerospike.dsl.Index; import com.aerospike.dsl.parts.AbstractPart; import com.aerospike.dsl.parts.ExpressionContainer; import com.aerospike.dsl.parts.ExpressionContainer.ExprPartsOperation; @@ -21,23 +21,29 @@ import org.antlr.v4.runtime.misc.Pair; import org.antlr.v4.runtime.tree.ParseTree; -import java.util.ArrayList; -import java.util.Base64; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.function.BinaryOperator; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.UnaryOperator; -import static com.aerospike.dsl.parts.AbstractPart.PartType.*; -import static com.aerospike.dsl.parts.ExpressionContainer.ExprPartsOperation.*; +import static com.aerospike.dsl.parts.AbstractPart.PartType.BIN_PART; +import static com.aerospike.dsl.parts.AbstractPart.PartType.EXPRESSION_CONTAINER; +import static com.aerospike.dsl.parts.AbstractPart.PartType.INT_OPERAND; +import static com.aerospike.dsl.parts.ExpressionContainer.ExprPartsOperation.ADD; +import static com.aerospike.dsl.parts.ExpressionContainer.ExprPartsOperation.AND; +import static com.aerospike.dsl.parts.ExpressionContainer.ExprPartsOperation.DIV; +import static com.aerospike.dsl.parts.ExpressionContainer.ExprPartsOperation.MUL; +import static com.aerospike.dsl.parts.ExpressionContainer.ExprPartsOperation.OR; +import static com.aerospike.dsl.parts.ExpressionContainer.ExprPartsOperation.SUB; import static com.aerospike.dsl.util.ValidationUtils.validateComparableTypes; -import static com.aerospike.dsl.visitor.VisitorUtils.ArithmeticTermType.*; +import static com.aerospike.dsl.visitor.VisitorUtils.ArithmeticTermType.ADDEND; +import static com.aerospike.dsl.visitor.VisitorUtils.ArithmeticTermType.DIVIDEND; +import static com.aerospike.dsl.visitor.VisitorUtils.ArithmeticTermType.DIVISOR; +import static com.aerospike.dsl.visitor.VisitorUtils.ArithmeticTermType.MIN; +import static com.aerospike.dsl.visitor.VisitorUtils.ArithmeticTermType.MULTIPLICAND; +import static com.aerospike.dsl.visitor.VisitorUtils.ArithmeticTermType.MULTIPLIER; +import static com.aerospike.dsl.visitor.VisitorUtils.ArithmeticTermType.SUBTR; @UtilityClass public class VisitorUtils { @@ -48,28 +54,6 @@ public class VisitorUtils { Exp.Type.BLOB, IndexType.BLOB ); - protected enum FilterOperationType { - GT, - GTEQ, - LT, - LTEQ, - EQ, - NOTEQ - } - - protected enum ArithmeticTermType { - ADDEND, - SUBTR, - MIN, - DIFFERENCE, - DIVIDEND, - DIVISOR, - QUOTIENT, - MULTIPLICAND, - MULTIPLIER, - PRODUCT - } - /** * Converts an {@link ExprPartsOperation} enum value to its corresponding {@link FilterOperationType}. * @@ -359,12 +343,10 @@ private static Exp getExpRightBinTypeComparison(AbstractPart left, BinPart right * @return The value of the specified parameter if found and matches the name, otherwise {@code null}. */ 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(); + String paramNameText = paramCtx.pathFunctionParamName().getText(); + String paramNameValue = paramCtx.pathFunctionParamValue().getText(); if (paramNameText.equalsIgnoreCase(paramName)) { paramValue = paramNameValue; } @@ -380,8 +362,7 @@ static String getPathFunctionParam(ConditionParser.PathFunctionParamContext para * @return The corresponding {@link ArithmeticTermType} * @throws NoApplicableFilterException if the operation type is not supported for determining arithmetic term type */ - private static ArithmeticTermType getFilterTermType(ExprPartsOperation operationType, - boolean isLeftTerm) { + private static ArithmeticTermType getFilterTermType(ExprPartsOperation operationType, boolean isLeftTerm) { return switch (operationType) { case ADD -> ADDEND; case SUB -> isLeftTerm ? SUBTR : MIN; @@ -430,8 +411,9 @@ private static Pair getLimitsForDivisionForFilter(long left, long ri * A {@code null} value in the pair indicates no bound on that side * @throws DslParseException if undefined division (0/0) occurs or if the operation type is not supported */ - private static Pair LimitsForBinDividend(long left, long right, - FilterOperationType operationType) { + private static Pair LimitsForBinDividend( + long left, long right, FilterOperationType operationType + ) { if (left > 0 && right > 0) { // both operands are positive return getLimitsForBinDividendWithLeftNumberPositive(operationType, left, right); @@ -462,8 +444,9 @@ private static Pair LimitsForBinDividend(long left, long right, * @return A {@link Pair} representing the lower and upper bounds of the range for the bin * @throws DslParseException if the operation type is not supported for division */ - private static Pair getLimitsForBinDividendWithLeftNumberNegative(FilterOperationType operationType, - long left, long right) { + private static Pair getLimitsForBinDividendWithLeftNumberNegative( + FilterOperationType operationType, long left, long right + ) { return switch (operationType) { case GT: yield new Pair<>(Long.MIN_VALUE, left * right - 1); @@ -487,8 +470,9 @@ private static Pair getLimitsForBinDividendWithLeftNumberNegative(Fi * @return A {@link Pair} representing the lower and upper bounds of the range for the bin * @throws DslParseException if the operation type is not supported for division */ - private static Pair getLimitsForBinDividendWithLeftNumberPositive(FilterOperationType operationType, - long left, long right) { + private static Pair getLimitsForBinDividendWithLeftNumberPositive( + FilterOperationType operationType, long left, long right + ) { return switch (operationType) { case GT: yield new Pair<>(left * right + 1, Long.MAX_VALUE); @@ -814,7 +798,7 @@ private static Filter applyFilterOperator(String binName, IntOperand leftOperand long rightValue = rightOperand.getValue(); float value; if (Objects.requireNonNull(operationType) == ADD) { - value = rightValue - leftValue; + value = (float) rightValue - leftValue; } else if (operationType == SUB) { value = switch (termType) { case SUBTR -> rightValue + leftValue; @@ -930,7 +914,6 @@ private static FilterOperationType invertType(FilterOperationType type) { * Either of them can be null if there is no suitable filter */ public static AbstractPart buildExpr(ExpressionContainer expr, Map> indexes) { - Exp exp; Filter secondaryIndexFilter = null; try { secondaryIndexFilter = getSIFilter(expr, indexes); @@ -938,7 +921,7 @@ public static AbstractPart buildExpr(ExpressionContainer expr, Map> getExpressionsPerCardinality(ExpressionContainer exprContainer, - Map> indexes) { + private static Map> getExpressionsPerCardinality( + ExpressionContainer exprContainer, Map> indexes + ) { Map> exprsPerCardinality = new HashMap<>(); final BinPart[] binPartPrev = {null}; Consumer exprsPerCardinalityCollector = part -> { @@ -1215,7 +1200,8 @@ private static Map> getExpressionsPerCardinal * to the {@code exprsPerCardinality} map. * * @param exprsPerCardinality A map where keys are integer ratios (representing index cardinality) - * and values are lists of {@link ExpressionContainer} objects. The map is updated by this method + * and values are lists of {@link ExpressionContainer} objects. + * The map is updated by this method * @param expr The {@link ExpressionContainer} to be added to the appropriate list * within {@code exprsPerCardinality} * @param binPart The {@link BinPart} associated with the expression, used to find @@ -1317,4 +1303,26 @@ public static void traverseTree(AbstractPart part, Consumer visito traverseTree(container.getRight(), visitor, depth - 1, stopCondition); } } + + protected enum FilterOperationType { + GT, + GTEQ, + LT, + LTEQ, + EQ, + NOTEQ + } + + protected enum ArithmeticTermType { + ADDEND, + SUBTR, + MIN, + DIFFERENCE, + DIVIDEND, + DIVISOR, + QUOTIENT, + MULTIPLICAND, + MULTIPLIER, + PRODUCT + } }