use of org.datanucleus.query.compiler.Symbol in project tests by datanucleus.
the class JDOQLCompilerTest method testFilterCollectionContainsVariable.
/**
* Tests for collection.contains(element).
*/
public void testFilterCollectionContainsVariable() {
JavaQueryCompiler compiler = null;
QueryCompilation compilation = null;
try {
compiler = new JDOQLCompiler(nucCtx, nucCtx.getClassLoaderResolver(null), null, Inventory.class, null, "products.contains(element) && element.price < 200", null, null, null, null, null, null, Product.class.getName() + " element", null);
compilation = compiler.compile(new HashMap(), null);
} catch (NucleusException ne) {
NucleusLogger.QUERY.error("Exception thrown during compilation", ne);
fail("compilation of filter with valid field threw exception : " + ne.getMessage());
}
Expression expr = compilation.getExprFilter();
assertTrue("Compiled expression should have been DyadicExpression but wasnt", expr instanceof DyadicExpression);
DyadicExpression dyExpr = (DyadicExpression) expr;
// product.contains(element)
assertTrue("Left expression should have been InvokeExpression but wasnt", dyExpr.getLeft() instanceof InvokeExpression);
InvokeExpression leftExpr = (InvokeExpression) dyExpr.getLeft();
assertTrue("InvokeExpression should have been invoked on PrimaryExpression but wasnt", leftExpr.getLeft() instanceof PrimaryExpression);
assertEquals("Left expression : Name of field upon which we invoke the method was wrong", "products", ((PrimaryExpression) leftExpr.getLeft()).getId());
assertEquals("Left expression : Name of invoked method was wrong", "contains", leftExpr.getOperation());
assertEquals("Left expression : Number of parameters to contains() is wrong", 1, leftExpr.getArguments().size());
Object param1 = leftExpr.getArguments().get(0);
assertTrue("Left expression : Parameter1 to contains() is of wrong type", param1 instanceof VariableExpression);
VariableExpression vrExpr = (VariableExpression) param1;
assertEquals("Left expression : Name of variable to contains() is incorrect", "element", vrExpr.getId());
// element.price < 200
assertTrue("Right expression should have been DyadicExpression but wasnt", dyExpr.getRight() instanceof DyadicExpression);
DyadicExpression rightExpr = (DyadicExpression) dyExpr.getRight();
assertTrue("Right expression (left) should have been PrimaryExpression but wasnt", rightExpr.getLeft() instanceof PrimaryExpression);
PrimaryExpression rightExprLeft = (PrimaryExpression) rightExpr.getLeft();
assertTrue("Right expression (left).left is of incorrect type", rightExprLeft.getLeft() instanceof VariableExpression);
VariableExpression rightExprLeftLeft = (VariableExpression) rightExprLeft.getLeft();
assertTrue("Right expression (left).left is of incorrect type", rightExprLeft.getLeft() instanceof VariableExpression);
assertEquals("Right expression (left) part1 is incorrect", "element", rightExprLeftLeft.getId());
assertEquals("Right expression (left) has incorrect number of tuples", 1, rightExprLeft.getTuples().size());
assertEquals("Right expression (left) part2 is incorrect", "price", rightExprLeft.getTuples().get(0));
assertEquals("Right expression : Operator between left and right is incorrect", Expression.OP_LT, rightExpr.getOperator());
assertTrue("Right expression (right) should have been Literal but wasnt", rightExpr.getRight() instanceof Literal);
Literal rightExprRight = (Literal) rightExpr.getRight();
assertEquals("Right expression (right) literal has incorrect value", 200, ((Long) rightExprRight.getLiteral()).longValue());
// Check symbols
SymbolTable symbols = compilation.getSymbolTable();
assertTrue("Symbol table doesnt have entry for 'element'", symbols.hasSymbol("element"));
assertTrue("Symbol table doesnt have entry for 'this'", symbols.hasSymbol("this"));
Symbol sy1 = symbols.getSymbol("element");
assertEquals("Type of symbol for 'element' is wrong", Product.class, sy1.getValueType());
Symbol sy2 = symbols.getSymbol("this");
assertEquals("Type of symbol for 'this' is wrong", Inventory.class, sy2.getValueType());
}
use of org.datanucleus.query.compiler.Symbol in project datanucleus-core by datanucleus.
the class Query method checkForMissingParameters.
/**
* Method to check for any missing parameters that the query compilation is expecting but which aren't
* supplied to execute().
* @param parameterValues The input parameter values keyed by their name (or position)
*/
protected void checkForMissingParameters(Map parameterValues) {
if (compilation == null) {
return;
} else if (parameterValues == null) {
parameterValues = new HashMap();
}
boolean namedParametersSupplied = true;
if (!parameterValues.isEmpty()) {
Object key = parameterValues.keySet().iterator().next();
if (!(key instanceof String)) {
namedParametersSupplied = false;
}
}
if (namedParametersSupplied) {
// Check for missing named parameters
SymbolTable symtbl = compilation.getSymbolTable();
Collection<String> symNames = symtbl.getSymbolNames();
if (symNames != null && !symNames.isEmpty()) {
for (String symName : symNames) {
Symbol sym = symtbl.getSymbol(symName);
if (sym.getType() == Symbol.PARAMETER) {
if (!parameterValues.containsKey(symName)) {
throw new QueryInvalidParametersException(Localiser.msg("021119", symName));
}
}
}
}
}
}
use of org.datanucleus.query.compiler.Symbol in project datanucleus-core by datanucleus.
the class Query method checkParameterTypesAgainstCompilation.
/**
* Method to do checks of the input parameters with respect to their types being consistent
* with the types of the parameters in the compilation.
* Checks for unused input parameters. Doesn't check for missing parameters.
* @param parameterValues The input parameter values keyed by their name (or position)
*/
protected void checkParameterTypesAgainstCompilation(Map parameterValues) {
if (compilation == null) {
return;
} else if (parameterValues == null || parameterValues.isEmpty()) {
return;
}
// Check for unused parameters
boolean checkUnusedParams = checkUnusedParameters();
Iterator it = parameterValues.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
Object paramKey = entry.getKey();
Symbol sym = null;
// Find the symbol for the parameter in the compilation (or subquery compilations)
sym = deepFindSymbolForParameterInCompilation(compilation, paramKey);
if (sym != null) {
Class expectedValueType = sym.getValueType();
if (entry.getValue() != null && expectedValueType != null && !QueryUtils.queryParameterTypesAreCompatible(expectedValueType, entry.getValue().getClass())) {
// Supplied parameter value is of inconsistent type
throw new NucleusUserException("Parameter \"" + paramKey + "\" was specified as " + entry.getValue().getClass().getName() + " but should have been " + expectedValueType.getName());
}
} else // TODO Also do this for positional params if not found ?
if (paramKey instanceof String) {
if ((fromInclParam == null && toExclParam == null) || (!paramKey.equals(fromInclParam) && !paramKey.equals(toExclParam))) {
if (checkUnusedParams) {
throw new QueryInvalidParametersException(Localiser.msg("021116", paramKey));
}
}
}
}
}
use of org.datanucleus.query.compiler.Symbol in project datanucleus-core by datanucleus.
the class DyadicExpression method bind.
/**
* Method to bind the expression to the symbol table as appropriate.
* @param symtbl Symbol table
* @return The symbol for this expression
*/
public Symbol bind(SymbolTable symtbl) {
if (left != null) {
try {
left.bind(symtbl);
} catch (PrimaryExpressionIsClassLiteralException peil) {
// PrimaryExpression should be swapped for a class Literal
left = peil.getLiteral();
left.bind(symtbl);
} catch (PrimaryExpressionIsClassStaticFieldException peil) {
// PrimaryExpression should be swapped for a static field Literal
Field fld = peil.getLiteralField();
try {
// Get the value of the static field
Object value = fld.get(null);
left = new Literal(value);
left.bind(symtbl);
} catch (Exception e) {
throw new NucleusUserException("Error processing static field " + fld.getName(), e);
}
} catch (PrimaryExpressionIsVariableException pive) {
// PrimaryExpression should be swapped for a VariableExpression
left = pive.getVariableExpression();
left.bind(symtbl);
} catch (PrimaryExpressionIsInvokeException piie) {
// PrimaryExpression should be swapped for a InvokeExpression
left = piie.getInvokeExpression();
left.bind(symtbl);
}
}
if (right != null) {
try {
right.bind(symtbl);
} catch (PrimaryExpressionIsClassLiteralException peil) {
// PrimaryExpression should be swapped for a class Literal
right = peil.getLiteral();
right.bind(symtbl);
} catch (PrimaryExpressionIsClassStaticFieldException peil) {
// PrimaryExpression should be swapped for a static field Literal
Field fld = peil.getLiteralField();
try {
// Get the value of the static field
Object value = fld.get(null);
right = new Literal(value);
right.bind(symtbl);
} catch (Exception e) {
throw new NucleusUserException("Error processing static field " + fld.getName(), e);
}
} catch (PrimaryExpressionIsVariableException pive) {
// PrimaryExpression should be swapped for a VariableExpression
right = pive.getVariableExpression();
right.bind(symtbl);
} catch (PrimaryExpressionIsInvokeException piie) {
// PrimaryExpression should be swapped for a InvokeExpression
right = piie.getInvokeExpression();
right.bind(symtbl);
}
}
if (left != null && left instanceof VariableExpression) {
Symbol leftSym = left.getSymbol();
if (leftSym != null && leftSym.getValueType() == null) {
// Set type of implicit variable
if (right instanceof Literal && ((Literal) right).getLiteral() != null) {
leftSym.setValueType(((Literal) right).getLiteral().getClass());
}
}
}
if (right != null) {
Symbol rightSym = right.getSymbol();
if (rightSym != null && rightSym.getValueType() == null) {
// Set type of implicit variable
if (left instanceof Literal && ((Literal) left).getLiteral() != null) {
rightSym.setValueType(((Literal) left).getLiteral().getClass());
}
}
}
// Interpret types of parameters etc when used in comparison operator
if (op == Expression.OP_EQ || op == Expression.OP_NOTEQ || op == Expression.OP_GT || op == Expression.OP_GTEQ || op == Expression.OP_LT || op == Expression.OP_LTEQ) {
Class leftType = (left != null && left.getSymbol() != null) ? left.getSymbol().getValueType() : null;
Class rightType = (right != null && right.getSymbol() != null) ? right.getSymbol().getValueType() : null;
if (left instanceof ParameterExpression && leftType == null && rightType != null) {
// parameter {op} primary
left.getSymbol().setValueType(rightType);
} else if (right instanceof ParameterExpression && rightType == null && leftType != null) {
// primary {op} parameter
right.getSymbol().setValueType(leftType);
}
leftType = (left != null && left.getSymbol() != null) ? left.getSymbol().getValueType() : null;
rightType = (right != null && right.getSymbol() != null) ? right.getSymbol().getValueType() : null;
}
return null;
}
use of org.datanucleus.query.compiler.Symbol in project datanucleus-core by datanucleus.
the class ExpressionCompiler method compilePrimaryExpression.
private Expression compilePrimaryExpression(Node node) {
if (node.getNodeType() == NodeType.PRIMARY) {
Node currentNode = node.getFirstChild();
Node invokeNode = node.getNextChild();
if (invokeNode.getNodeType() != NodeType.INVOKE) {
// TODO Support more combinations
throw new QueryCompilerSyntaxException("Dont support compilation of " + node);
}
Expression currentExpr = compileExpression(currentNode);
String methodName = (String) invokeNode.getNodeValue();
List<Expression> parameterExprs = getExpressionsForPropertiesOfNode(invokeNode);
Expression invokeExpr = new InvokeExpression(currentExpr, methodName, parameterExprs);
return invokeExpr;
} else if (node.getNodeType() == NodeType.IDENTIFIER) {
Node currentNode = node;
List tupple = new ArrayList();
Expression currentExpr = null;
while (currentNode != null) {
tupple.add(currentNode.getNodeValue());
if (currentNode.getNodeType() == NodeType.INVOKE) {
if (currentExpr == null && tupple.size() > 1) {
// Check for starting with parameter/variable
String first = (String) tupple.get(0);
Symbol firstSym = symtbl.getSymbol(first);
if (firstSym != null) {
if (firstSym.getType() == Symbol.PARAMETER) {
currentExpr = new ParameterExpression(first, -1);
if (tupple.size() > 2) {
currentExpr = new PrimaryExpression(currentExpr, tupple.subList(1, tupple.size() - 1));
}
} else if (firstSym.getType() == Symbol.VARIABLE) {
currentExpr = new VariableExpression(first);
if (tupple.size() > 2) {
currentExpr = new PrimaryExpression(currentExpr, tupple.subList(1, tupple.size() - 1));
}
}
}
if (currentExpr == null) {
currentExpr = new PrimaryExpression(tupple.subList(0, tupple.size() - 1));
}
} else if (currentExpr != null && tupple.size() > 1) {
currentExpr = new PrimaryExpression(currentExpr, tupple.subList(0, tupple.size() - 1));
}
String methodName = (String) tupple.get(tupple.size() - 1);
if (currentExpr instanceof PrimaryExpression) {
// Check if this is a defined method prefix, and if so use the alias
String id = ((PrimaryExpression) currentExpr).getId();
if (aliasByPrefix != null && aliasByPrefix.containsKey(id)) {
String alias = aliasByPrefix.get(id);
methodName = alias + "." + methodName;
currentExpr = null;
}
}
List<Expression> parameterExprs = getExpressionsForPropertiesOfNode(currentNode);
currentExpr = new InvokeExpression(currentExpr, methodName, parameterExprs);
currentNode = currentNode.getFirstChild();
tupple = new ArrayList();
} else if (currentNode.getNodeType() == NodeType.CAST) {
if (currentExpr == null && tupple.size() > 1) {
// Start from PrimaryExpression and invoke on that
currentExpr = new PrimaryExpression(tupple.subList(0, tupple.size() - 1));
PrimaryExpression primExpr = (PrimaryExpression) currentExpr;
if (primExpr.tuples.size() == 1) {
Symbol sym = symtbl.getSymbol(primExpr.getId());
if (sym != null) {
if (sym.getType() == Symbol.PARAMETER) {
// Parameter symbol registered for this identifier so use ParameterExpression
currentExpr = new ParameterExpression(primExpr.getId(), -1);
} else if (sym.getType() == Symbol.VARIABLE) {
// Variable symbol registered for this identifier so use VariableExpression
currentExpr = new VariableExpression(primExpr.getId());
}
}
}
}
String className = (String) tupple.get(tupple.size() - 1);
currentExpr = new DyadicExpression(currentExpr, Expression.OP_CAST, new Literal(className));
currentNode = currentNode.getFirstChild();
tupple = new ArrayList();
} else {
// Part of identifier chain
currentNode = currentNode.getFirstChild();
}
}
if (currentExpr != null && !tupple.isEmpty()) {
// We have a trailing identifier expression e.g "((B)a).c" where we have a CastExpression and trailing "c"
currentExpr = new PrimaryExpression(currentExpr, tupple);
}
if (currentExpr == null) {
// Find type of first of tupples
String first = (String) tupple.get(0);
Symbol firstSym = symtbl.getSymbol(first);
if (firstSym != null) {
// TODO If the user has a field in the candidate the same name as a parameter and they just put the name (rather than "this.{name}") then it interprets as parameter
if (firstSym.getType() == Symbol.PARAMETER) {
ParameterExpression paramExpr = new ParameterExpression(first, -1);
if (tupple.size() > 1) {
currentExpr = new PrimaryExpression(paramExpr, tupple.subList(1, tupple.size()));
} else {
currentExpr = paramExpr;
}
} else if (firstSym.getType() == Symbol.VARIABLE) {
VariableExpression varExpr = new VariableExpression(first);
if (tupple.size() > 1) {
currentExpr = new PrimaryExpression(varExpr, tupple.subList(1, tupple.size()));
} else {
currentExpr = varExpr;
}
} else {
currentExpr = new PrimaryExpression(tupple);
}
} else {
currentExpr = new PrimaryExpression(tupple);
}
}
return currentExpr;
} else if (node.getNodeType() == NodeType.PARAMETER) {
// "{paramExpr}", "{paramExpr}.invoke(...)", "{paramExpr}.invoke(...).invoke(...)"
Object val = node.getNodeValue();
Expression currentExpr = null;
if (val instanceof Integer) {
// Positional parameter TODO Store as Integer to avoid confusion
currentExpr = new ParameterExpression("" + node.getNodeValue(), ((ParameterNode) node).getPosition());
} else {
// Named parameter
currentExpr = new ParameterExpression((String) node.getNodeValue(), ((ParameterNode) node).getPosition());
}
Node childNode = node.getFirstChild();
while (childNode != null) {
if (childNode.getNodeType() == NodeType.INVOKE) {
String methodName = (String) childNode.getNodeValue();
List<Expression> parameterExprs = getExpressionsForPropertiesOfNode(childNode);
currentExpr = new InvokeExpression(currentExpr, methodName, parameterExprs);
} else if (childNode.getNodeType() == NodeType.IDENTIFIER) {
String identifier = childNode.getNodeId();
List tuples = new ArrayList();
tuples.add(identifier);
boolean moreIdentifierNodes = true;
while (moreIdentifierNodes) {
Node currentNode = childNode;
childNode = childNode.getFirstChild();
if (childNode == null || childNode.getNodeType() != NodeType.IDENTIFIER) {
moreIdentifierNodes = false;
childNode = currentNode;
} else {
// Add as a component of the primary
tuples.add(childNode.getNodeId());
}
}
currentExpr = new PrimaryExpression(currentExpr, tuples);
} else {
throw new QueryCompilerSyntaxException("Dont support compilation of " + node);
}
childNode = childNode.getFirstChild();
}
return currentExpr;
} else if (node.getNodeType() == NodeType.INVOKE) {
Node currentNode = node;
List tupple = new ArrayList();
Expression currentExpr = null;
while (currentNode != null) {
tupple.add(currentNode.getNodeValue());
if (currentNode.getNodeType() == NodeType.INVOKE) {
String methodName = (String) tupple.get(tupple.size() - 1);
List<Expression> parameterExprs = getExpressionsForPropertiesOfNode(currentNode);
currentExpr = new InvokeExpression(currentExpr, methodName, parameterExprs);
currentNode = currentNode.getFirstChild();
if (currentNode != null) {
// Continue on along the chain
tupple = new ArrayList();
// Start from this expression
tupple.add(currentExpr);
}
} else {
// TODO What node type is this that comes after an INVOKE?
currentNode = currentNode.getFirstChild();
}
}
return currentExpr;
} else if (node.getNodeType() == NodeType.CREATOR) {
Node currentNode = node.getFirstChild();
List tupple = new ArrayList();
boolean method = false;
while (currentNode != null) {
tupple.add(currentNode.getNodeValue());
if (currentNode.getNodeType() == NodeType.INVOKE) {
method = true;
break;
}
currentNode = currentNode.getFirstChild();
}
List<Expression> parameterExprs = null;
if (method) {
parameterExprs = getExpressionsForPropertiesOfNode(currentNode);
} else {
parameterExprs = new ArrayList();
}
return new CreatorExpression(tupple, parameterExprs);
} else if (node.getNodeType() == NodeType.LITERAL) {
Node currentNode = node;
List tupple = new ArrayList();
Expression currentExpr = null;
while (currentNode != null) {
tupple.add(currentNode.getNodeValue());
if (currentNode.getNodeType() == NodeType.INVOKE) {
if (currentExpr == null && tupple.size() > 1) {
// Start from Literal and invoke on that
currentExpr = new Literal(node.getNodeValue());
}
String methodName = (String) tupple.get(tupple.size() - 1);
List<Expression> parameterExprs = getExpressionsForPropertiesOfNode(currentNode);
currentExpr = new InvokeExpression(currentExpr, methodName, parameterExprs);
currentNode = currentNode.getFirstChild();
tupple = new ArrayList();
} else {
currentNode = currentNode.getFirstChild();
}
}
if (currentExpr == null) {
currentExpr = new Literal(node.getNodeValue());
}
return currentExpr;
} else if (node.getNodeType() == NodeType.ARRAY) {
Node currentNode = node;
List<Node> arrayElements = (List<Node>) node.getNodeValue();
// Check if this is an array literal
boolean literal = true;
Class type = null;
Iterator<Node> iter = arrayElements.iterator();
while (iter.hasNext()) {
Node element = iter.next();
if (type == null) {
type = element.getNodeValue().getClass();
}
if (element.getNodeType() == NodeType.IDENTIFIER) {
literal = false;
break;
}
}
Expression currentExpr = null;
if (literal) {
Object array = Array.newInstance(type, arrayElements.size());
iter = arrayElements.iterator();
int index = 0;
while (iter.hasNext()) {
Node element = iter.next();
Array.set(array, index++, element.getNodeValue());
}
currentExpr = new Literal(array);
} else {
Expression[] arrayElementExprs = new Expression[arrayElements.size()];
for (int i = 0; i < arrayElementExprs.length; i++) {
arrayElementExprs[i] = compilePrimaryExpression(arrayElements.get(i));
}
currentExpr = new ArrayExpression(arrayElementExprs);
}
currentNode = currentNode.getFirstChild();
List tupple = new ArrayList();
while (currentNode != null) {
tupple.add(currentNode.getNodeValue());
if (currentNode.getNodeType() == NodeType.INVOKE) {
if (tupple.size() > 1) {
// Start from Literal and invoke on that
currentExpr = new Literal(node.getNodeValue());
}
String methodName = (String) tupple.get(tupple.size() - 1);
List<Expression> parameterExprs = getExpressionsForPropertiesOfNode(currentNode);
currentExpr = new InvokeExpression(currentExpr, methodName, parameterExprs);
currentNode = currentNode.getFirstChild();
tupple = new ArrayList();
} else {
currentNode = currentNode.getFirstChild();
}
}
return currentExpr;
} else if (node.getNodeType() == NodeType.SUBQUERY) {
List children = node.getChildNodes();
if (children.size() != 1) {
throw new QueryCompilerSyntaxException("Invalid number of children for SUBQUERY node : " + node);
}
Node varNode = (Node) children.get(0);
VariableExpression subqueryExpr = new VariableExpression(varNode.getNodeId());
Expression currentExpr = new SubqueryExpression((String) node.getNodeValue(), subqueryExpr);
return currentExpr;
} else if (node.getNodeType() == NodeType.CASE) {
// Node with children in the order "when", "action"[, "when", "action"], "else"
List<Node> children = node.getChildNodes();
if ((children.size() % 2) == 0) {
throw new QueryCompilerSyntaxException("Invalid number of children for CASE node (should be odd). Have you omitted the ELSE clause? : " + node);
}
Node elseNode = children.get(children.size() - 1);
Expression elseExpr = compileExpression(elseNode);
CaseExpression caseExpr = new CaseExpression();
Iterator<Node> childIter = children.iterator();
while (childIter.hasNext()) {
Node whenNode = childIter.next();
if (childIter.hasNext()) {
Node actionNode = childIter.next();
Expression whenExpr = compileExpression(whenNode);
Expression actionExpr = compileExpression(actionNode);
caseExpr.addCondition(whenExpr, actionExpr);
}
}
caseExpr.setElseExpression(elseExpr);
return caseExpr;
} else if (node.getNodeType() == NodeType.TYPE) {
List<Node> children = node.getChildNodes();
Expression containedExpr = compileExpression(children.get(0));
TypeExpression typeExpr = new TypeExpression(containedExpr);
return typeExpr;
} else {
NucleusLogger.QUERY.warn("ExpressionCompiler.compilePrimaryExpression node=" + node + " ignored by ExpressionCompiler since not of a supported type");
}
return null;
}
Aggregations