use of org.datanucleus.query.compiler.Node in project datanucleus-core by datanucleus.
the class ExpressionCompiler method compileFromExpression.
/**
* Primary entry point for compiling a node for the from clause.
* @param node The node
* @param classIsExpression whether the class of the from node is an expression relating to the outer query
* @return Its compiled expression
*/
public Expression compileFromExpression(Node node, boolean classIsExpression) {
if (node.getNodeType() == NodeType.CLASS) {
Node aliasNode = node.getFirstChild();
ClassExpression clsExpr = new ClassExpression((String) aliasNode.getNodeValue());
if (classIsExpression) {
clsExpr.setCandidateExpression((String) node.getNodeValue());
}
// Process any joins, chained down off the ClassExpression
// So you can do clsExpr.getRight() to get the JoinExpression
// then joinExpr.getRight() to get the next JoinExpression (if any)
JoinExpression currentJoinExpr = null;
Iterator childIter = node.getChildNodes().iterator();
while (childIter.hasNext()) {
Node childNode = (Node) childIter.next();
if (childNode.getNodeType() == NodeType.OPERATOR) {
String joinType = (String) childNode.getNodeValue();
JoinType joinTypeId = JoinType.JOIN_INNER;
if (joinType.equals(JavaQueryCompiler.JOIN_INNER_FETCH)) {
joinTypeId = JoinType.JOIN_INNER_FETCH;
} else if (joinType.equals(JavaQueryCompiler.JOIN_OUTER_FETCH)) {
joinTypeId = JoinType.JOIN_LEFT_OUTER_FETCH;
} else if (joinType.equals(JavaQueryCompiler.JOIN_OUTER_FETCH_RIGHT)) {
joinTypeId = JoinType.JOIN_RIGHT_OUTER_FETCH;
} else if (joinType.equals(JavaQueryCompiler.JOIN_OUTER)) {
joinTypeId = JoinType.JOIN_LEFT_OUTER;
} else if (joinType.equals(JavaQueryCompiler.JOIN_OUTER_RIGHT)) {
joinTypeId = JoinType.JOIN_RIGHT_OUTER;
}
Node joinedNode = childNode.getFirstChild();
Expression joinedExpr = compilePrimaryExpression(joinedNode);
Node joinedAliasNode = childNode.getNextChild();
JoinExpression joinExpr = new JoinExpression(joinedExpr, (String) joinedAliasNode.getNodeValue(), joinTypeId);
if (currentJoinExpr != null) {
currentJoinExpr.setJoinExpression(joinExpr);
} else {
clsExpr.setJoinExpression(joinExpr);
}
if (childNode.hasNextChild()) {
// JOIN "ON" expression
Node nextNode = childNode.getNextChild();
Expression onExpr = compileExpression(nextNode);
if (onExpr != null) {
joinExpr.setOnExpression(onExpr);
}
}
currentJoinExpr = joinExpr;
}
}
return clsExpr;
}
return null;
}
use of org.datanucleus.query.compiler.Node 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;
}
use of org.datanucleus.query.compiler.Node in project datanucleus-core by datanucleus.
the class ExpressionCompiler method getExpressionsForPropertiesOfNode.
/**
* Convenience method to extract properties for this node and return the associated list of expressions.
* @param node The node
* @return The list of expressions for the properties (or null if no properties)
*/
private List<Expression> getExpressionsForPropertiesOfNode(Node node) {
if (node.hasProperties()) {
List<Expression> parameterExprs = new ArrayList();
List propNodes = node.getProperties();
for (int i = 0; i < propNodes.size(); i++) {
parameterExprs.add(compileExpression((Node) propNodes.get(i)));
}
return parameterExprs;
}
return Collections.EMPTY_LIST;
}
use of org.datanucleus.query.compiler.Node in project datanucleus-core by datanucleus.
the class ExpressionCompiler method compileOrderExpression.
/**
* Primary entry point for compiling a node for the order clause.
* @param node The node
* @return Its compiled expression
*/
public Expression compileOrderExpression(Node node) {
if (isOperator(node, "order")) {
Node nameNode = node.getFirstChild();
if (node.getChildNodes().size() > 1) {
String node1Value = (String) node.getNextChild().getNodeValue();
String node2Value = node.hasNextChild() ? (String) node.getNextChild().getNodeValue() : null;
String ordering = null;
String nullOrdering = null;
if (node1Value.equalsIgnoreCase("ascending") || node1Value.equalsIgnoreCase("descending")) {
ordering = node1Value;
if (node2Value != null) {
nullOrdering = node2Value;
}
} else {
nullOrdering = node1Value;
}
return new OrderExpression(compileExpression(nameNode), ordering, nullOrdering);
}
if (node.getChildNodes().size() == 1) {
return new OrderExpression(compileExpression(nameNode));
}
}
return compileExpression(node.getFirstChild());
}
Aggregations