Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/main/java/com/aerospike/dsl/DslParseException.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ public class DslParseException extends RuntimeException {
public DslParseException(String description) {
super(description);
}

public DslParseException(String description, Throwable cause) {
super(description, cause);
}
}
11 changes: 10 additions & 1 deletion src/main/java/com/aerospike/dsl/Index.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.aerospike.dsl;

import com.aerospike.client.cdt.CTX;
import com.aerospike.client.query.IndexCollectionType;
import com.aerospike.client.query.IndexType;
import lombok.Builder;
import lombok.EqualsAndHashCode;
Expand Down Expand Up @@ -28,7 +30,14 @@ public class Index {
/**
* 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;
/**
* {@link IndexCollectionType} of the index
*/
private IndexCollectionType indexCollectionType;
/**
* Array of {@link CTX} representing context of the index
*/
private CTX[] ctx;
}
4 changes: 1 addition & 3 deletions src/main/java/com/aerospike/dsl/ParsedExpression.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,7 @@ public ParseResult getResult(PlaceholderValues placeholderValues) {
AbstractPart resultPart = buildExpr((ExpressionContainer) expressionTree, placeholderValues, indexesMap);
return new ParseResult(resultPart.getFilter(), resultPart.getExp());
} else {
Filter filter = expressionTree.getFilter();
Exp exp = expressionTree.getExp();
return new ParseResult(filter, exp);
return new ParseResult(expressionTree.getFilter(), expressionTree.getExp());
}
}
return new ParseResult(null, null);
Expand Down
21 changes: 16 additions & 5 deletions src/main/java/com/aerospike/dsl/api/DSLParser.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.aerospike.dsl.api;

import com.aerospike.client.cdt.CTX;
import com.aerospike.client.query.Filter;
import com.aerospike.dsl.DslParseException;
import com.aerospike.dsl.ExpressionContext;
Expand All @@ -22,7 +23,7 @@
public interface DSLParser {

/**
* Parse DSL path into Aerospike filter Expression.
* Parse DSL string into {@link ParsedExpression}.
* <br><br>
* Examples:
* <table border="1">
Expand Down Expand Up @@ -88,14 +89,14 @@ public interface DSLParser {
* </table>
*
* @param input {@link ExpressionContext} containing input string of dot separated elements. If the input string has
* placeholders, matching values must be provided within {@code input} too
* placeholders, matching values must be provided within {@code input} too
* @return {@link ParsedExpression} object
* @throws DslParseException in case of invalid syntax
*/
ParsedExpression parseExpression(ExpressionContext input);

/**
* Parse String DSL path into Aerospike filter Expression.
* Parse DSL string into {@link ParsedExpression}.
* <br><br>
* Examples:
* <table border="1">
Expand Down Expand Up @@ -160,12 +161,22 @@ public interface DSLParser {
* </tr>
* </table>
*
* @param input {@link ExpressionContext} containing input string of dot separated elements. If the input string has
* placeholders, matching values must be provided within {@code input} too
* @param input {@link ExpressionContext} containing input string of dot separated elements. If the input string has
* placeholders, matching values must be provided within {@code input} too
* @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 invalid syntax
*/
ParsedExpression parseExpression(ExpressionContext input, IndexContext indexContext);

/**
* Parse DSL path with CDT context into an array of {@link CTX} objects. The argument must represent a path with context,
* e.g. $.listBinName.[1], $.mapBinName.ab etc.
*
* @param dslPath Input string representing path with CDT context, must not be null
* @return Array of {@link CTX}
* @throws DslParseException in case of invalid syntax
*/
CTX[] parseCTX(String dslPath);
}
20 changes: 20 additions & 0 deletions src/main/java/com/aerospike/dsl/impl/DSLParserImpl.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.aerospike.dsl.impl;

import com.aerospike.client.cdt.CTX;
import com.aerospike.dsl.ConditionLexer;
import com.aerospike.dsl.ConditionParser;
import com.aerospike.dsl.DslParseException;
Expand All @@ -23,20 +24,39 @@
import java.util.Optional;
import java.util.stream.Collectors;

import static com.aerospike.dsl.visitor.VisitorUtils.buildCtx;

public class DSLParserImpl implements DSLParser {

@Override
@Beta
public ParsedExpression parseExpression(ExpressionContext expressionContext) {
ParseTree parseTree = getParseTree(expressionContext.getExpression());
return getParsedExpression(parseTree, expressionContext.getValues(), null);
}

@Override
@Beta
public ParsedExpression parseExpression(ExpressionContext expressionContext, IndexContext indexContext) {
ParseTree parseTree = getParseTree(expressionContext.getExpression());
return getParsedExpression(parseTree, expressionContext.getValues(), indexContext);
}

@Override
@Beta
public CTX[] parseCTX(String pathToCtx) {
if (pathToCtx == null || pathToCtx.isBlank()) {
throw new DslParseException("Path must not be null or empty");
}

ParseTree parseTree = getParseTree(pathToCtx);
try {
return buildCtx(new ExpressionConditionVisitor().visit(parseTree));
} catch (Exception e) {
throw new DslParseException("Could not parse the given DSL path input", e);
}
}

private ParseTree getParseTree(String input) {
ConditionLexer lexer = new ConditionLexer(CharStreams.fromString(input));
ConditionParser parser = new ConditionParser(new CommonTokenStream(lexer));
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/aerospike/dsl/parts/AbstractPart.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.aerospike.dsl.parts;

import com.aerospike.client.cdt.CTX;
import com.aerospike.client.exp.Exp;
import com.aerospike.client.query.Filter;
import lombok.Getter;
Expand All @@ -13,6 +14,7 @@ public abstract class AbstractPart {
protected PartType partType;
protected Exp exp;
protected Filter filter;
protected CTX[] ctx;
protected boolean isPlaceholder;

protected AbstractPart(PartType partType) {
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/aerospike/dsl/parts/path/Path.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.aerospike.dsl.parts.path;

import com.aerospike.client.cdt.CTX;
import com.aerospike.client.exp.Exp;
import com.aerospike.dsl.parts.AbstractPart;
import com.aerospike.dsl.parts.cdt.CdtPart;
Expand Down Expand Up @@ -48,4 +49,9 @@ public Exp processPath(BasePath basePath, PathFunction pathFunction) {
public Exp getExp() {
return processPath(basePath, pathFunction);
}

@Override
public CTX[] getCtx() {
return getContextArray(basePath.getCdtParts(), true);
}
}
25 changes: 11 additions & 14 deletions src/main/java/com/aerospike/dsl/util/PathOperandUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
import com.aerospike.client.exp.ListExp;
import com.aerospike.client.exp.MapExp;
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 com.aerospike.dsl.parts.path.BasePath;
import com.aerospike.dsl.parts.path.BinPart;
import com.aerospike.dsl.parts.path.PathFunction;
import lombok.experimental.UtilityClass;

import java.util.ArrayList;
Expand All @@ -21,9 +21,9 @@

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;
import static com.aerospike.dsl.parts.path.PathFunction.PathFunctionType.*;

@UtilityClass
public class PathOperandUtils {
Expand Down Expand Up @@ -175,13 +175,11 @@ private static boolean isPrevCdtPartAmbiguous(AbstractPart lastPart) {
* @throws UnsupportedOperationException If the path part type is not supported
*/
public static Exp processGet(BasePath basePath, AbstractPart lastPathPart, Exp.Type valueType, int cdtReturnType) {
if (lastPathPart.getPartType() == LIST_PART) {
return doProcessCdtGet(basePath, lastPathPart, valueType, cdtReturnType, (ListPart) lastPathPart);
} else if (lastPathPart.getPartType() == MAP_PART) {
return doProcessCdtGet(basePath, lastPathPart, valueType, cdtReturnType, (MapPart) lastPathPart);
if (lastPathPart.getPartType() != LIST_PART && lastPathPart.getPartType() != MAP_PART) {
throw new UnsupportedOperationException(
String.format("Path part type %s is not supported", lastPathPart.getPartType()));
}
throw new UnsupportedOperationException(
String.format("Path part type %s is not supported", lastPathPart.getPartType()));
return doProcessCdtGet(basePath, lastPathPart, valueType, cdtReturnType);
}

/**
Expand All @@ -193,13 +191,12 @@ public static Exp processGet(BasePath basePath, AbstractPart lastPathPart, Exp.T
* @param lastPathPart The last {@link AbstractPart} in the path
* @param valueType The expected {@link Exp.Type} of the value being retrieved
* @param cdtReturnType The CDT return type
* @param cdtPart The {@link CdtPart} being processed
* @return An {@link Exp} representing the CDT "get" operation
*/
private static Exp doProcessCdtGet(BasePath basePath, AbstractPart lastPathPart, Exp.Type valueType,
int cdtReturnType, CdtPart cdtPart) {
int cdtReturnType) {
// list type designator "[]" can be either after bin name or after path
if (isListTypeDesignator(cdtPart) || isMapTypeDesignator(cdtPart)) {
if (isListTypeDesignator(lastPathPart) || isMapTypeDesignator(lastPathPart)) {
return constructCdtExp(basePath, lastPathPart, valueType, cdtReturnType);
}

Expand Down Expand Up @@ -237,7 +234,7 @@ private static boolean isMapTypeDesignator(AbstractPart cdtPart) {
* @param includeLast A boolean indicating whether the last part should be included in the context array
* @return An array of {@link CTX} objects
*/
private static CTX[] getContextArray(List<AbstractPart> parts, boolean includeLast) {
public static CTX[] getContextArray(List<AbstractPart> parts, boolean includeLast) {
// Nested (Context) map key access
List<CTX> context = new ArrayList<>();

Expand Down
Loading
Loading