Problem with "IS EMPTY" in JPQL queries


william.martel@...
 

Hi, I believe I have found a bug in the JPQLParser class, but I'm not entirely sure.

Considering a User class, with a nullable 1-1 link to a UserAccount class, and a collection of Contract objects in the UserAccount class, and a JPQL query with the following form:

SELECT u FROM package.to.my.class.User u LEFT JOIN u.userAccount ua WHERE ua.contracts IS EMPTY

The code that parses the "IS EMPTY" clause is as follows (JPQLParser.processRelationalExpression()):

else if (lexer.parseStringIgnoreCase("EMPTY"))
{
// Convert IS EMPTY to a method call of "size()==0" on collection/map
Node sizeNode = new Node(NodeType.INVOKE, "size");
inputNode.insertChildNode(sizeNode);
Node isEmptyNode = new Node(NodeType.OPERATOR, not ? "!=" : "==");
isEmptyNode.appendChildNode(inputNode);
Node zeroNode = new Node(NodeType.LITERAL, 0);
isEmptyNode.appendChildNode(zeroNode);
stack.push(isEmptyNode);
}

Debugging through this code, I find that there is a variable "inputRootNode" which essentially contains ua.contracts, and the variable "inputNode" only contains the last part of this chain, in this case "contracts". However, in the else if statement to handle "EMPTY", the isEmptyNode appends inputNode as a child, instead of inputRootNode, which causes the node structure to end up like this:

[OPERATOR : ==.

    [IDENTIFIER : contracts.

        [INVOKE : size]],

    [LITERAL : 0]]

Notice how we lost the "ua." prefix for contracts. Then, at the end of the query compilation, we get a NucleusUserException, with the message "Class name contracts could not be resolved".

Replacing the line "isEmptyNode.appendChildNode(inputNode)" by "isEmptyNode.appendChildNode(inputRootNode)", similar to the previous if statement that handles the "NULL" case, seems to resolve the problem, but I'm not sure if that would have an impact on different queries or if there's more to it than that, but I thought I'd point it out. Maybe there is something wrong/not supported in the query I'm using?

Join main@datanucleus.groups.io to automatically receive all group messages.