use of org.datanucleus.store.query.QueryCompilerSyntaxException in project datanucleus-core by datanucleus.
the class JavaQueryCompiler method compileFrom.
/**
* Method to compile the "from" clause (if present for the query language).
* @return The compiled from expression(s)
*/
protected Expression[] compileFrom() {
if (from == null) {
return null;
}
Node[] node = parser.parseFrom(from);
Expression[] expr = new Expression[node.length];
for (int i = 0; i < node.length; i++) {
String className = (String) node[i].getNodeValue();
String classAlias = null;
Class cls = null;
if (parentCompiler != null) {
cls = getClassForSubqueryClassExpression(className);
} else {
cls = resolveClass(className);
}
List<Node> children = node[i].getChildNodes();
for (Node child : children) {
if (// Alias - maybe should assume it is the first child
child.getNodeType() == NodeType.NAME) {
classAlias = (String) child.getNodeValue();
}
}
if (i == 0 && classAlias == null) {
throw new QueryCompilerSyntaxException("FROM clause of query has class " + cls.getName() + " but no alias");
}
if (classAlias != null) {
if (i == 0) {
// First expression so set up candidateClass/alias
candidateClass = cls;
if (parentCompiler != null && parentCompiler.candidateAlias.equals(classAlias)) {
// The defined alias is the same as the parent query, so rename
candidateAliasOrig = classAlias;
candidateAlias = "sub_" + candidateAlias;
classAlias = candidateAlias;
swapCandidateAliasNodeName(node[i].getChildNode(0));
} else {
candidateAlias = classAlias;
}
}
if (symtbl.getSymbol(classAlias) == null) {
// Add symbol for this candidate under its alias
symtbl.addSymbol(new PropertySymbol(classAlias, cls));
}
}
for (Node childNode : children) {
// Add entries in symbol table for any joined aliases
if (childNode.getNodeType() == NodeType.OPERATOR) {
Node joinedNode = childNode.getFirstChild();
// Extract alias node
Node aliasNode = childNode.getNextChild();
// Extract ON node (if present)
Node onExprNode = null;
if (childNode.hasNextChild()) {
onExprNode = childNode.getNextChild();
}
String joinedAlias = (String) joinedNode.getNodeValue();
boolean rootNode = false;
Symbol joinedSym = caseSensitiveAliases ? symtbl.getSymbol(joinedAlias) : symtbl.getSymbolIgnoreCase(joinedAlias);
if (joinedSym == null) {
// DN Extension : Check for FROM clause including join to a new root
if (aliasNode != null) {
joinedAlias = (String) aliasNode.getNodeValue();
cls = resolveClass((String) joinedNode.getNodeValue());
if (symtbl.getSymbol(joinedAlias) == null) {
// Add symbol for this candidate under its alias
symtbl.addSymbol(new PropertySymbol(joinedAlias, cls));
rootNode = true;
NucleusLogger.QUERY.debug("Found suspected ROOT node joined to in FROM clause : attempting to process as alias=" + joinedAlias);
}
joinedSym = caseSensitiveAliases ? symtbl.getSymbol(joinedAlias) : symtbl.getSymbolIgnoreCase(joinedAlias);
}
if (joinedSym == null) {
throw new QueryCompilerSyntaxException("FROM clause has identifier " + joinedNode.getNodeValue() + " but this is unknown");
}
}
if (!rootNode) {
AbstractClassMetaData joinedCmd = metaDataManager.getMetaDataForClass(joinedSym.getValueType(), clr);
Class joinedCls = joinedSym.getValueType();
AbstractMemberMetaData joinedMmd = null;
while (joinedNode.getFirstChild() != null) {
joinedNode = joinedNode.getFirstChild();
String joinedMember = (String) joinedNode.getNodeValue();
if (joinedNode.getNodeType() == NodeType.CAST) {
// JOIN to "TREAT(identifier AS subcls)"
String castTypeName = (String) joinedNode.getNodeValue();
if (castTypeName.indexOf('.') < 0) {
// Fully-qualify with the current class name?
castTypeName = ClassUtils.createFullClassName(joinedCmd.getPackageName(), castTypeName);
}
joinedCls = clr.classForName(castTypeName);
// Update cast type now that we have resolved it
joinedNode.setNodeValue(castTypeName);
} else {
// Allow for multi-field joins
String[] joinedMembers = joinedMember.contains(".") ? StringUtils.split(joinedMember, ".") : new String[] { joinedMember };
for (int k = 0; k < joinedMembers.length; k++) {
String memberName = joinedMembers[k];
if (joinedCmd == null) {
throw new NucleusUserException("Query has JOIN to " + memberName + " but previous element (" + joinedCls.getName() + ") has no metadata");
}
if (memberName.endsWith("#KEY")) {
memberName = memberName.substring(0, memberName.length() - 4);
} else if (memberName.endsWith("#VALUE")) {
memberName = memberName.substring(0, memberName.length() - 6);
}
AbstractMemberMetaData mmd = joinedCmd.getMetaDataForMember(memberName);
if (mmd == null) {
if (childNode.getNodeValue().equals(JOIN_OUTER) || childNode.getNodeValue().equals(JOIN_OUTER_FETCH)) {
// Polymorphic join, where the field exists in a subclass (doable since we have outer join)
String[] subclasses = metaDataManager.getSubclassesForClass(joinedCmd.getFullClassName(), true);
if (subclasses != null) {
for (int l = 0; l < subclasses.length; l++) {
AbstractClassMetaData subCmd = metaDataManager.getMetaDataForClass(subclasses[l], clr);
if (subCmd != null) {
mmd = subCmd.getMetaDataForMember(memberName);
if (mmd != null) {
NucleusLogger.QUERY.debug("Polymorphic join found at " + memberName + " of " + subCmd.getFullClassName());
joinedCmd = subCmd;
break;
}
}
}
}
}
if (mmd == null) {
throw new QueryCompilerSyntaxException("FROM clause has reference to " + joinedCmd.getFullClassName() + "." + joinedMembers[k] + " but it doesn't exist!");
}
}
RelationType relationType = mmd.getRelationType(clr);
joinedMmd = mmd;
if (RelationType.isRelationSingleValued(relationType)) {
joinedCls = mmd.getType();
joinedCmd = metaDataManager.getMetaDataForClass(joinedCls, clr);
} else if (RelationType.isRelationMultiValued(relationType)) {
if (mmd.hasCollection()) {
// TODO Don't currently allow interface field navigation
joinedCmd = mmd.getCollection().getElementClassMetaData(clr);
if (joinedCmd != null) {
joinedCls = clr.classForName(joinedCmd.getFullClassName());
} else {
joinedCls = clr.classForName(mmd.getCollection().getElementType());
}
} else if (mmd.hasMap()) {
if (joinedMembers[k].endsWith("#KEY")) {
joinedCmd = mmd.getMap().getKeyClassMetaData(clr);
// TODO Set joinedCls
} else {
joinedCmd = mmd.getMap().getValueClassMetaData(clr);
if (joinedCmd != null) {
// JPA assumption that the value is an entity ... but it may not be!
joinedCls = clr.classForName(joinedCmd.getFullClassName());
} else {
joinedCls = clr.classForName(mmd.getMap().getValueType());
}
}
} else if (mmd.hasArray()) {
// TODO Don't currently allow interface field navigation
joinedCmd = mmd.getArray().getElementClassMetaData(clr);
if (joinedCmd != null) {
joinedCls = clr.classForName(joinedCmd.getFullClassName());
} else {
joinedCls = clr.classForName(mmd.getArray().getElementType());
}
}
}
}
}
}
if (aliasNode != null && aliasNode.getNodeType() == NodeType.NAME) {
// Add JOIN alias to symbol table
String alias = (String) aliasNode.getNodeValue();
symtbl.addSymbol(new PropertySymbol(alias, joinedCls));
if (joinedMmd != null && joinedMmd.hasMap()) {
Class keyCls = clr.classForName(joinedMmd.getMap().getKeyType());
// Add the KEY so that we can have joins to the key from the value alias
symtbl.addSymbol(new PropertySymbol(alias + "#KEY", keyCls));
Class valueCls = clr.classForName(joinedMmd.getMap().getValueType());
// Add the VALUE so that we can have joins to the value from the key alias
symtbl.addSymbol(new PropertySymbol(alias + "#VALUE", valueCls));
}
}
}
if (onExprNode != null) {
// ON condition
ExpressionCompiler comp = new ExpressionCompiler();
comp.setSymbolTable(symtbl);
comp.setMethodAliases(queryMgr.getQueryMethodAliasesByPrefix());
Expression nextExpr = comp.compileExpression(onExprNode);
nextExpr.bind(symtbl);
}
}
}
boolean classIsExpression = false;
String[] tokens = StringUtils.split(className, ".");
if (symtbl.getParentSymbolTable() != null) {
if (symtbl.getParentSymbolTable().hasSymbol(tokens[0])) {
classIsExpression = true;
}
}
ExpressionCompiler comp = new ExpressionCompiler();
comp.setSymbolTable(symtbl);
comp.setMethodAliases(queryMgr.getQueryMethodAliasesByPrefix());
expr[i] = comp.compileFromExpression(node[i], classIsExpression);
if (expr[i] != null) {
expr[i].bind(symtbl);
}
}
return expr;
}
use of org.datanucleus.store.query.QueryCompilerSyntaxException in project datanucleus-core by datanucleus.
the class JDOQLParser method processPrimary.
/**
* Parses the primary. First look for a literal (e.g. "text"), then
* an identifier(e.g. variable) In the next step, call a function, if
* executing a function, on the literal or the identifier found.
*/
protected void processPrimary() {
if (lexer.parseString("DISTINCT ") || lexer.parseString("distinct")) {
// Aggregates can have "count(DISTINCT field1)"
Node distinctNode = new Node(NodeType.OPERATOR, "DISTINCT");
processExpression();
Node identifierNode = stack.pop();
distinctNode.appendChildNode(identifierNode);
stack.push(distinctNode);
return;
}
// Find any cast first, and remove from top of stack since we put after the cast component
Node castNode = null;
if (processCast()) {
castNode = stack.pop();
}
if (lexer.peekString("IF(") || lexer.peekString("if(") || lexer.peekString("IF (") || lexer.peekString("if (")) {
processIfElseExpression();
return;
}
if (processCreator()) {
// "new MyClass(...)", allow chain of method invocations
boolean endOfChain = false;
while (!endOfChain) {
if (lexer.parseChar('.')) {
if (processMethod()) {
// Add method invocation as a child node of what it is invoked on
Node invokeNode = stack.pop();
Node invokedNode = stack.peek();
invokedNode.appendChildNode(invokeNode);
}
} else {
endOfChain = true;
}
}
if (castNode != null) {
// TODO Add cast of creator expression
throw new NucleusException("Dont currently support compile of cast of creator expression");
}
return;
} else if (processLiteral()) {
// Literal, allow chain of method invocations
boolean endOfChain = false;
while (!endOfChain) {
if (lexer.parseChar('.')) {
if (processMethod()) {
// Add method invocation as a child node of what it is invoked on
Node invokeNode = stack.pop();
Node invokedNode = stack.peek();
invokedNode.appendChildNode(invokeNode);
}
} else {
endOfChain = true;
}
}
if (castNode != null) {
throw new NucleusException("Dont currently support compile of cast of literal expression");
// TODO Add cast of literal
}
return;
} else if (processMethod()) {
// Static method call
if (castNode != null) {
throw new NucleusException("Dont currently support compile of cast of static method call");
// TODO Add cast of static method call
}
return;
} else if (processArray()) {
// Array, allow chain of method invocations
boolean endOfChain = false;
while (!endOfChain) {
if (lexer.parseChar('.')) {
if (processMethod()) {
// Add method invocation as a child node of what it is invoked on
Node invokeNode = stack.pop();
Node invokedNode = stack.peek();
invokedNode.appendChildNode(invokeNode);
}
} else {
endOfChain = true;
}
}
if (castNode != null) {
throw new NucleusException("Dont currently support compile of cast of array expression");
// TODO Add cast of array
}
return;
}
int sizeBeforeBraceProcessing = stack.size();
boolean braceProcessing = false;
if (lexer.parseChar('(')) {
// "({expr1})"
processExpression();
if (!lexer.parseChar(')')) {
throw new QueryCompilerSyntaxException("expected ')'", lexer.getIndex(), lexer.getInput());
}
if (!lexer.parseChar('.')) {
// TODO If we have a cast, then apply to the current node (with the brackets)
return;
}
// Has follow on expression "({expr1}).{expr2}" so continue
braceProcessing = true;
}
// We will have an identifier (variable, parameter, or field of candidate class)
if (processMethod()) {
} else if (processIdentifier()) {
} else {
throw new QueryCompilerSyntaxException("Method/Identifier expected", lexer.getIndex(), lexer.getInput());
}
// Save the stack size just before this component for use later in squashing all nodes
// down to a single Node in the stack with all others chained off from it
int size = stack.size();
if (braceProcessing) {
size = sizeBeforeBraceProcessing + 1;
}
while (lexer.parseChar('.')) {
if (processMethod()) {
// "a.method(...)"
} else if (processIdentifier()) {
// "a.field"
} else {
throw new QueryCompilerSyntaxException("Identifier expected", lexer.getIndex(), lexer.getInput());
}
}
// -> node (IDENTIFIER) with child (IDENTIFIER), with child (IDENTIFIER), with child (IDENTIFIER)
if (castNode != null) {
// Put the CAST as a child of the Node being cast
stack.peek().appendChildNode(castNode);
}
// ((B)a).c being compiled to "Node[IDENTIFIER, a] -> Node[CAST, B] -> Node[IDENTIFIER, c]"
while (stack.size() > size) {
Node top = stack.pop();
Node peek = stack.peek();
Node lastDescendant = getLastDescendantNodeForNode(peek);
if (lastDescendant != null) {
lastDescendant.appendChildNode(top);
} else {
// The peek node has multiple children, so cannot just put the top Node after the last child
Node primNode = new Node(NodeType.PRIMARY);
primNode.appendChildNode(peek);
primNode.appendChildNode(top);
// Remove "peek" node and replace with primNode
stack.pop();
stack.push(primNode);
}
}
}
use of org.datanucleus.store.query.QueryCompilerSyntaxException 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.store.query.QueryCompilerSyntaxException in project datanucleus-rdbms by datanucleus.
the class QueryToSQLMapper method compile.
/**
* Method to update the supplied SQLStatement with the components of the specified query.
* During the compilation process this updates the SQLStatement "compileComponent" to the
* component of the query being compiled.
*/
public void compile() {
if (NucleusLogger.QUERY.isDebugEnabled() && parentMapper == null) {
// Give debug output of compilation
StringBuilder str = new StringBuilder("JoinType : navigation(default=");
str.append(defaultJoinType != null ? defaultJoinType : "(using nullability)");
str.append(", filter=");
str.append(defaultJoinTypeFilter != null ? defaultJoinTypeFilter : "(using nullability)");
str.append(")");
if (extensionsByName != null) {
Iterator<Map.Entry<String, Object>> extensionsIter = extensionsByName.entrySet().iterator();
while (extensionsIter.hasNext()) {
Map.Entry<String, Object> entry = extensionsIter.next();
String key = entry.getKey();
if (key.startsWith("datanucleus.query.jdoql.") && key.endsWith(".join")) {
// Alias join definition
String alias = key.substring("datanucleus.query.jdoql.".length(), key.lastIndexOf(".join"));
str.append(", ").append(alias).append("=").append(entry.getValue());
}
}
}
NucleusLogger.QUERY.debug("Compile of " + compilation.getQueryLanguage() + " into SQL - " + str);
}
compileFrom();
compileFilter();
if (stmt instanceof UpdateStatement) {
compileUpdate((UpdateStatement) stmt);
} else if (stmt instanceof SelectStatement) {
SelectStatement selectStmt = (SelectStatement) stmt;
// the datastore doesn't allow select of some field types when used with DISTINCT
if (compilation.getResultDistinct()) {
selectStmt.setDistinct(true);
} else if (!options.contains(OPTION_EXPLICIT_JOINS) && compilation.getExprResult() == null) {
// Joins are made implicitly and no result so set distinct based on whether joining to other table groups
if (selectStmt.getNumberOfTableGroups() > 1) {
// Queries against an extent always consider only distinct candidate instances, regardless of whether distinct is specified (JDO spec)
if (!options.contains(OPTION_NON_DISTINCT_IMPLICIT_JOINS)) {
// If user can guarantee distinct w/ query no reason to take performance hit of distinct clause
selectStmt.setDistinct(true);
}
}
}
compileResult(selectStmt);
compileGrouping(selectStmt);
compileHaving(selectStmt);
compileOrdering(selectStmt);
}
// Check for variables that haven't been bound to the query (declared but not used)
for (String symbol : compilation.getSymbolTable().getSymbolNames()) {
Symbol sym = compilation.getSymbolTable().getSymbol(symbol);
if (sym.getType() == Symbol.VARIABLE) {
if (compilation.getCompilationForSubquery(sym.getQualifiedName()) == null && !hasSQLTableMappingForAlias(sym.getQualifiedName())) {
// Variable not a subquery, nor had its table allocated
throw new QueryCompilerSyntaxException("Query has variable \"" + sym.getQualifiedName() + "\" which is not bound to the query");
}
}
}
}
use of org.datanucleus.store.query.QueryCompilerSyntaxException in project datanucleus-core by datanucleus.
the class JDOQLParser method parseVariables.
/* (non-Javadoc)
* @see org.datanucleus.query.compiler.Parser#parseVariables(java.lang.String)
*/
public Node[][] parseVariables(String expression) {
lexer = new Lexer(expression, paramPrefixes, true);
List nodes = new ArrayList();
do {
if (StringUtils.isWhitespace(lexer.remaining())) {
break;
}
processPrimary();
if (stack.isEmpty()) {
throw new QueryCompilerSyntaxException("Parsing variable list and expected variable type", lexer.getIndex(), lexer.getInput());
}
if (!processIdentifier()) {
throw new QueryCompilerSyntaxException("Parsing variable list and expected variable name", lexer.getIndex(), lexer.getInput());
}
Node nodeVariable = stack.pop();
String varName = (String) nodeVariable.getNodeValue();
if (!JDOQLQueryHelper.isValidJavaIdentifierForJDOQL(varName)) {
throw new NucleusUserException(Localiser.msg("021105", varName));
}
Node nodeType = stack.pop();
nodes.add(new Node[] { nodeType, nodeVariable });
} while (lexer.parseString(";"));
return (Node[][]) nodes.toArray(new Node[nodes.size()][2]);
}
Aggregations