Search in sources :

Example 1 with Node

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;
}
Also used : Node(org.datanucleus.query.compiler.Node) ParameterNode(org.datanucleus.query.compiler.ParameterNode) Iterator(java.util.Iterator) JoinType(org.datanucleus.query.expression.JoinExpression.JoinType)

Example 2 with Node

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;
}
Also used : Symbol(org.datanucleus.query.compiler.Symbol) Node(org.datanucleus.query.compiler.Node) ParameterNode(org.datanucleus.query.compiler.ParameterNode) ArrayList(java.util.ArrayList) ParameterNode(org.datanucleus.query.compiler.ParameterNode) QueryCompilerSyntaxException(org.datanucleus.store.query.QueryCompilerSyntaxException) ArrayList(java.util.ArrayList) List(java.util.List)

Example 3 with Node

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;
}
Also used : Node(org.datanucleus.query.compiler.Node) ParameterNode(org.datanucleus.query.compiler.ParameterNode) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List)

Example 4 with Node

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());
}
Also used : Node(org.datanucleus.query.compiler.Node) ParameterNode(org.datanucleus.query.compiler.ParameterNode)

Aggregations

Node (org.datanucleus.query.compiler.Node)4 ParameterNode (org.datanucleus.query.compiler.ParameterNode)4 ArrayList (java.util.ArrayList)2 List (java.util.List)2 Iterator (java.util.Iterator)1 Symbol (org.datanucleus.query.compiler.Symbol)1 JoinType (org.datanucleus.query.expression.JoinExpression.JoinType)1 QueryCompilerSyntaxException (org.datanucleus.store.query.QueryCompilerSyntaxException)1