Search in sources :

Example 6 with DyadicExpression

use of org.datanucleus.store.query.expression.DyadicExpression in project datanucleus-rdbms by datanucleus.

the class QueryToSQLMapper method processInvokeExpression.

/**
 * Internal method to handle the processing of an InvokeExpression.
 * @param expr The InvokeExpression
 * @param invokedSqlExpr The SQLExpression that we are invoking the method on.
 * @return The resultant SQLExpression
 */
protected SQLExpression processInvokeExpression(InvokeExpression expr, SQLExpression invokedSqlExpr) {
    if (invokedSqlExpr instanceof NullLiteral) {
        // We cannot invoke anything on a null TODO Handle this "NPE"
        NucleusLogger.QUERY.warn("Compilation of InvokeExpression needs to invoke method \"" + expr.getOperation() + "\" on " + invokedSqlExpr + " but not possible");
    }
    String operation = expr.getOperation();
    if (invokedSqlExpr instanceof MapExpression && operation.equals("contains") && compilation.getQueryLanguage().equalsIgnoreCase(Query.LANGUAGE_JPQL)) {
        // JPQL "MEMBER OF" will be passed through from generic compilation as "contains" since we don't know types at that point
        operation = "containsValue";
    }
    // Process the arguments for invoking
    List args = expr.getArguments();
    List sqlExprArgs = null;
    if (args != null) {
        sqlExprArgs = new ArrayList<SQLExpression>();
        Iterator<Expression> iter = args.iterator();
        while (iter.hasNext()) {
            Expression argExpr = iter.next();
            if (argExpr instanceof PrimaryExpression) {
                processPrimaryExpression((PrimaryExpression) argExpr);
                SQLExpression argSqlExpr = stack.pop();
                if (compileComponent == CompilationComponent.RESULT && operation.equalsIgnoreCase("count") && stmt.getNumberOfTableGroups() > 1) {
                    if (argSqlExpr.getSQLTable() == stmt.getPrimaryTable() && argSqlExpr.getJavaTypeMapping() == stmt.getPrimaryTable().getTable().getIdMapping()) {
                        // Result with "count(this)" and joins to other groups, so enforce distinct
                        argSqlExpr.distinct();
                    }
                }
                sqlExprArgs.add(argSqlExpr);
            } else if (argExpr instanceof ParameterExpression) {
                processParameterExpression((ParameterExpression) argExpr);
                sqlExprArgs.add(stack.pop());
            } else if (argExpr instanceof InvokeExpression) {
                processInvokeExpression((InvokeExpression) argExpr);
                sqlExprArgs.add(stack.pop());
            } else if (argExpr instanceof Literal) {
                processLiteral((Literal) argExpr);
                sqlExprArgs.add(stack.pop());
            } else if (argExpr instanceof DyadicExpression) {
                // Evaluate using this evaluator
                argExpr.evaluate(this);
                sqlExprArgs.add(stack.pop());
            } else if (argExpr instanceof VariableExpression) {
                processVariableExpression((VariableExpression) argExpr);
                sqlExprArgs.add(stack.pop());
            } else if (argExpr instanceof CaseExpression) {
                processCaseExpression((CaseExpression) argExpr);
                sqlExprArgs.add(stack.pop());
            } else {
                throw new NucleusException("Dont currently support invoke expression argument " + argExpr);
            }
        }
        if (operation.equals("INDEX")) {
            // Special case of index expression
            List<Expression> indexArgs = expr.getArguments();
            if (indexArgs == null || indexArgs.size() > 1) {
                throw new NucleusException("Can only use INDEX with single argument");
            }
            PrimaryExpression indexExpr = (PrimaryExpression) indexArgs.get(0);
            String joinAlias = indexExpr.getId();
            String collExprName = joinAlias;
            if (explicitJoinPrimaryByAlias != null) {
                collExprName = explicitJoinPrimaryByAlias.get(joinAlias);
                if (collExprName == null) {
                    throw new NucleusException("Unable to locate primary expression for alias " + joinAlias);
                }
            }
            // Find an expression for the collection field
            List<String> tuples = new ArrayList<>();
            StringTokenizer primTokenizer = new StringTokenizer(collExprName, ".");
            while (primTokenizer.hasMoreTokens()) {
                String token = primTokenizer.nextToken();
                tuples.add(token);
            }
            PrimaryExpression collPrimExpr = new PrimaryExpression(tuples);
            processPrimaryExpression(collPrimExpr);
            SQLExpression collSqlExpr = stack.pop();
            sqlExprArgs.add(collSqlExpr);
        }
    }
    // Invoke the method
    SQLExpression sqlExpr = null;
    if (invokedSqlExpr instanceof org.datanucleus.store.rdbms.sql.expression.SubqueryExpression) {
        if (operation.equalsIgnoreCase("isEmpty")) {
            // Special case of {subquery}.isEmpty(), equates to "NOT EXISTS (subquery)"
            org.datanucleus.store.rdbms.sql.expression.SubqueryExpression subquerySqlExpr = (org.datanucleus.store.rdbms.sql.expression.SubqueryExpression) invokedSqlExpr;
            SQLStatement subStmt = subquerySqlExpr.getSubqueryStatement();
            SQLExpression subqueryNotExistsExpr = new BooleanSubqueryExpression(stmt, "EXISTS", subStmt).not();
            stack.push(subqueryNotExistsExpr);
            return subqueryNotExistsExpr;
        } else if (operation.equalsIgnoreCase("size")) {
            // {subquery}.size() should simply be changed to have a subquery of "SELECT COUNT(*) FROM ..."
            throw new NucleusUserException("Attempt to invoke method `" + operation + "` on Subquery. This is not supported. Change the subquery to return COUNT() instead.");
        }
        throw new NucleusUserException("Attempt to invoke method `" + operation + "` on Subquery. This is not supported");
    }
    if (invokedSqlExpr != null) {
        sqlExpr = invokedSqlExpr.invoke(operation, sqlExprArgs);
    } else {
        sqlExpr = exprFactory.invokeMethod(stmt, null, operation, null, sqlExprArgs);
    }
    stack.push(sqlExpr);
    return sqlExpr;
}
Also used : SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) PrimaryExpression(org.datanucleus.store.query.expression.PrimaryExpression) ArrayList(java.util.ArrayList) SQLStatement(org.datanucleus.store.rdbms.sql.SQLStatement) CaseExpression(org.datanucleus.store.query.expression.CaseExpression) BooleanSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.BooleanSubqueryExpression) NumericSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression) StringSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.StringSubqueryExpression) TemporalSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.TemporalSubqueryExpression) SubqueryExpression(org.datanucleus.store.query.expression.SubqueryExpression) TemporalLiteral(org.datanucleus.store.rdbms.sql.expression.TemporalLiteral) Literal(org.datanucleus.store.query.expression.Literal) SQLLiteral(org.datanucleus.store.rdbms.sql.expression.SQLLiteral) ParameterLiteral(org.datanucleus.store.rdbms.sql.expression.ParameterLiteral) CollectionLiteral(org.datanucleus.store.rdbms.sql.expression.CollectionLiteral) BooleanLiteral(org.datanucleus.store.rdbms.sql.expression.BooleanLiteral) IntegerLiteral(org.datanucleus.store.rdbms.sql.expression.IntegerLiteral) NullLiteral(org.datanucleus.store.rdbms.sql.expression.NullLiteral) ArrayList(java.util.ArrayList) List(java.util.List) MapExpression(org.datanucleus.store.rdbms.sql.expression.MapExpression) InvokeExpression(org.datanucleus.store.query.expression.InvokeExpression) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) VariableExpression(org.datanucleus.store.query.expression.VariableExpression) DyadicExpression(org.datanucleus.store.query.expression.DyadicExpression) StringTokenizer(java.util.StringTokenizer) PrimaryExpression(org.datanucleus.store.query.expression.PrimaryExpression) BooleanSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.BooleanSubqueryExpression) TypeConverterExpression(org.datanucleus.store.rdbms.sql.expression.TypeConverterExpression) StringExpression(org.datanucleus.store.rdbms.sql.expression.StringExpression) NumericSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression) StringSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.StringSubqueryExpression) MapExpression(org.datanucleus.store.rdbms.sql.expression.MapExpression) ArrayExpression(org.datanucleus.store.query.expression.ArrayExpression) CaseExpression(org.datanucleus.store.query.expression.CaseExpression) CreatorExpression(org.datanucleus.store.query.expression.CreatorExpression) NewObjectExpression(org.datanucleus.store.rdbms.sql.expression.NewObjectExpression) OrderExpression(org.datanucleus.store.query.expression.OrderExpression) TemporalSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.TemporalSubqueryExpression) ClassExpression(org.datanucleus.store.query.expression.ClassExpression) BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) Expression(org.datanucleus.store.query.expression.Expression) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) ParameterExpression(org.datanucleus.store.query.expression.ParameterExpression) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) TemporalExpression(org.datanucleus.store.rdbms.sql.expression.TemporalExpression) SubqueryExpression(org.datanucleus.store.query.expression.SubqueryExpression) ResultAliasExpression(org.datanucleus.store.rdbms.sql.expression.ResultAliasExpression) VariableExpression(org.datanucleus.store.query.expression.VariableExpression) TypeExpression(org.datanucleus.store.query.expression.TypeExpression) NumericExpression(org.datanucleus.store.rdbms.sql.expression.NumericExpression) CollectionExpression(org.datanucleus.store.rdbms.sql.expression.CollectionExpression) DyadicExpression(org.datanucleus.store.query.expression.DyadicExpression) ColumnExpression(org.datanucleus.store.rdbms.sql.expression.ColumnExpression) JoinExpression(org.datanucleus.store.query.expression.JoinExpression) InvokeExpression(org.datanucleus.store.query.expression.InvokeExpression) BooleanSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.BooleanSubqueryExpression) ParameterExpression(org.datanucleus.store.query.expression.ParameterExpression) NucleusException(org.datanucleus.exceptions.NucleusException) NullLiteral(org.datanucleus.store.rdbms.sql.expression.NullLiteral)

Aggregations

NucleusException (org.datanucleus.exceptions.NucleusException)6 DyadicExpression (org.datanucleus.store.query.expression.DyadicExpression)6 InvokeExpression (org.datanucleus.store.query.expression.InvokeExpression)6 Literal (org.datanucleus.store.query.expression.Literal)6 ParameterExpression (org.datanucleus.store.query.expression.ParameterExpression)6 PrimaryExpression (org.datanucleus.store.query.expression.PrimaryExpression)6 VariableExpression (org.datanucleus.store.query.expression.VariableExpression)6 BooleanExpression (org.datanucleus.store.rdbms.sql.expression.BooleanExpression)6 BooleanLiteral (org.datanucleus.store.rdbms.sql.expression.BooleanLiteral)6 CollectionLiteral (org.datanucleus.store.rdbms.sql.expression.CollectionLiteral)6 IntegerLiteral (org.datanucleus.store.rdbms.sql.expression.IntegerLiteral)6 MapExpression (org.datanucleus.store.rdbms.sql.expression.MapExpression)6 NullLiteral (org.datanucleus.store.rdbms.sql.expression.NullLiteral)6 ParameterLiteral (org.datanucleus.store.rdbms.sql.expression.ParameterLiteral)6 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)6 SQLLiteral (org.datanucleus.store.rdbms.sql.expression.SQLLiteral)6 TemporalLiteral (org.datanucleus.store.rdbms.sql.expression.TemporalLiteral)6 UnboundExpression (org.datanucleus.store.rdbms.sql.expression.UnboundExpression)6 ArrayExpression (org.datanucleus.store.query.expression.ArrayExpression)5 CaseExpression (org.datanucleus.store.query.expression.CaseExpression)5