Search in sources :

Example 1 with CollectionExpression

use of org.datanucleus.store.rdbms.sql.expression.CollectionExpression in project datanucleus-rdbms by datanucleus.

the class ListGetMethod method getExpression.

/* (non-Javadoc)
     * @see org.datanucleus.store.rdbms.sql.method.SQLMethod#getExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression, java.util.List)
     */
public SQLExpression getExpression(SQLStatement stmt, SQLExpression expr, List<SQLExpression> args) {
    if (args == null || args.size() == 0 || args.size() > 1) {
        throw new NucleusException(Localiser.msg("060016", "get", "CollectionExpression", 1));
    }
    CollectionExpression listExpr = (CollectionExpression) expr;
    AbstractMemberMetaData mmd = listExpr.getJavaTypeMapping().getMemberMetaData();
    if (!List.class.isAssignableFrom(mmd.getType())) {
        throw new UnsupportedOperationException("Query contains " + expr + ".get(int) yet the field is not a List!");
    } else if (mmd.getOrderMetaData() != null && !mmd.getOrderMetaData().isIndexedList()) {
        throw new UnsupportedOperationException("Query contains " + expr + ".get(int) yet the field is not an 'indexed' List!");
    }
    SQLExpression idxExpr = args.get(0);
    if (idxExpr instanceof SQLLiteral) {
        if (!(((SQLLiteral) idxExpr).getValue() instanceof Number)) {
            throw new UnsupportedOperationException("Query contains " + expr + ".get(int) yet the index is not a numeric literal so not yet supported");
        }
    } else {
        throw new UnsupportedOperationException("Query contains " + expr + ".get(int) yet the index is not a numeric literal so not yet supported");
    }
    if (listExpr instanceof CollectionLiteral && idxExpr instanceof SQLLiteral) {
        CollectionLiteral lit = (CollectionLiteral) expr;
        if (lit.getValue() == null) {
            return new NullLiteral(stmt, null, null, null);
        }
        return lit.invoke("get", args);
    }
    if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.FILTER) {
        return getAsInnerJoin(stmt, listExpr, idxExpr);
    } else if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.ORDERING || stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.RESULT || stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.HAVING) {
        return getAsSubquery(stmt, listExpr, idxExpr);
    }
    throw new NucleusException("List.get() is not supported for " + listExpr + " with argument " + idxExpr + " for query component " + stmt.getQueryGenerator().getCompilationComponent());
}
Also used : CollectionLiteral(org.datanucleus.store.rdbms.sql.expression.CollectionLiteral) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) SQLLiteral(org.datanucleus.store.rdbms.sql.expression.SQLLiteral) List(java.util.List) CollectionExpression(org.datanucleus.store.rdbms.sql.expression.CollectionExpression) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) NullLiteral(org.datanucleus.store.rdbms.sql.expression.NullLiteral)

Example 2 with CollectionExpression

use of org.datanucleus.store.rdbms.sql.expression.CollectionExpression in project datanucleus-rdbms by datanucleus.

the class QueryToSQLMapper method processInExpression.

/* (non-Javadoc)
     * @see org.datanucleus.query.evaluator.AbstractExpressionEvaluator#processInExpression(org.datanucleus.query.expression.Expression)
     */
@Override
protected Object processInExpression(Expression expr) {
    SQLExpression right = stack.pop();
    SQLExpression left = stack.pop();
    if (right instanceof CollectionExpression || right instanceof org.datanucleus.store.rdbms.sql.expression.ArrayExpression) {
        // myElement IN myCollection
        if (right.getParameterName() != null) {
            setNotPrecompilable();
        }
        // Use Collection.contains(element)/Array.contains(element)
        List<SQLExpression> sqlExprArgs = new ArrayList();
        sqlExprArgs.add(left);
        SQLExpression sqlExpr = right.invoke("contains", sqlExprArgs);
        stack.push(sqlExpr);
        return sqlExpr;
    } else if (right.getParameterName() != null || left.getParameterName() != null) {
        // "expr IN (:param)" or ":param IN (expr)" or ":param1 IN (:param2)"
        setNotPrecompilable();
        // Replace parameter(s) with equivalent literal of correct type
        if (right instanceof ParameterLiteral) {
            right = replaceParameterLiteral((ParameterLiteral) right, left.getJavaTypeMapping());
        }
        if (left instanceof ParameterLiteral && !Collection.class.isAssignableFrom(right.getJavaTypeMapping().getJavaType())) {
            left = replaceParameterLiteral((ParameterLiteral) left, right.getJavaTypeMapping());
        }
        // Single valued parameter, so use equality
        SQLExpression inExpr = new BooleanExpression(left, Expression.OP_EQ, right);
        stack.push(inExpr);
        return inExpr;
    }
    SQLExpression inExpr = left.in(right, false);
    stack.push(inExpr);
    return inExpr;
}
Also used : BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) ParameterLiteral(org.datanucleus.store.rdbms.sql.expression.ParameterLiteral) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) ArrayList(java.util.ArrayList) Collection(java.util.Collection) CollectionExpression(org.datanucleus.store.rdbms.sql.expression.CollectionExpression)

Example 3 with CollectionExpression

use of org.datanucleus.store.rdbms.sql.expression.CollectionExpression in project datanucleus-rdbms by datanucleus.

the class QueryToSQLMapper method processNotInExpression.

/* (non-Javadoc)
     * @see org.datanucleus.query.evaluator.AbstractExpressionEvaluator#processNotInExpression(org.datanucleus.query.expression.Expression)
     */
@Override
protected Object processNotInExpression(Expression expr) {
    SQLExpression right = stack.pop();
    SQLExpression left = stack.pop();
    if (right instanceof CollectionExpression) {
        // myElement IN myCollection
        if (right.getParameterName() != null) {
            setNotPrecompilable();
        }
        // Use !Collection.contains(element)
        List<SQLExpression> sqlExprArgs = new ArrayList();
        sqlExprArgs.add(left);
        SQLExpression sqlExpr = right.invoke("contains", sqlExprArgs);
        sqlExpr.not();
        stack.push(sqlExpr);
        return sqlExpr;
    } else if (right.getParameterName() != null) {
        // Single valued parameter, so use equality
        SQLExpression inExpr = new BooleanExpression(left, Expression.OP_NOTEQ, right);
        stack.push(inExpr);
        return inExpr;
    }
    SQLExpression inExpr = left.in(right, true);
    stack.push(inExpr);
    return inExpr;
}
Also used : BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) ArrayList(java.util.ArrayList) CollectionExpression(org.datanucleus.store.rdbms.sql.expression.CollectionExpression)

Example 4 with CollectionExpression

use of org.datanucleus.store.rdbms.sql.expression.CollectionExpression in project datanucleus-rdbms by datanucleus.

the class CollectionContainsMethod method getExpression.

/* (non-Javadoc)
     * @see org.datanucleus.store.rdbms.sql.method.SQLMethod#getExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression, java.util.List)
     */
public SQLExpression getExpression(SQLStatement stmt, SQLExpression expr, List<SQLExpression> args) {
    if (args == null || args.size() == 0 || args.size() > 1) {
        throw new NucleusException(Localiser.msg("060016", "contains", "CollectionExpression", 1));
    }
    CollectionExpression collExpr = (CollectionExpression) expr;
    AbstractMemberMetaData mmd = collExpr.getJavaTypeMapping().getMemberMetaData();
    SQLExpression elemExpr = args.get(0);
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    if (elemExpr.isParameter()) {
        // Element is a parameter so make sure its type is set
        if (mmd != null && mmd.getCollection() != null) {
            Class elementCls = stmt.getQueryGenerator().getClassLoaderResolver().classForName(mmd.getCollection().getElementType());
            stmt.getQueryGenerator().bindParameter(elemExpr.getParameterName(), elementCls);
        }
    }
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    if (collExpr instanceof CollectionLiteral) {
        // Literal collection
        CollectionLiteral lit = (CollectionLiteral) collExpr;
        Collection coll = (Collection) lit.getValue();
        JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
        if (coll == null || coll.isEmpty()) {
            return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
        }
        if (collExpr.isParameter()) {
            stmt.getQueryGenerator().useParameterExpressionAsLiteral((CollectionLiteral) collExpr);
        }
        boolean useInExpression = false;
        List<SQLExpression> collElementExprs = lit.getElementExpressions();
        if (collElementExprs != null && !collElementExprs.isEmpty()) {
            // Make sure the the collection element(s) are compatible with the elemExpr
            boolean incompatible = true;
            Class elemtype = clr.classForName(elemExpr.getJavaTypeMapping().getType());
            Iterator<SQLExpression> collElementExprIter = collElementExprs.iterator();
            while (collElementExprIter.hasNext()) {
                SQLExpression collElementExpr = collElementExprIter.next();
                Class collElemType = clr.classForName(collElementExpr.getJavaTypeMapping().getType());
                if (elementTypeCompatible(elemtype, collElemType)) {
                    incompatible = false;
                    break;
                }
            }
            if (incompatible) {
                // The provided element type isn't assignable to any of the input collection elements!
                return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
            }
            // Check if we should compare using an "IN (...)" expression
            SQLExpression collElementExpr = collElementExprs.get(0);
            if (collElementExpr instanceof StringExpression || collElementExpr instanceof NumericExpression || collElementExpr instanceof TemporalExpression || collElementExpr instanceof CharacterExpression || collElementExpr instanceof EnumExpression) {
                useInExpression = true;
            }
        }
        if (useInExpression) {
            // Return "elem IN (val1, val2, ...)"
            SQLExpression[] exprs = (collElementExprs != null ? collElementExprs.toArray(new SQLExpression[collElementExprs.size()]) : null);
            return new InExpression(elemExpr, exprs);
        }
        // Return "elem == val1 || elem == val2 || elem == val3 ..."
        BooleanExpression bExpr = null;
        if (collElementExprs != null) {
            for (int i = 0; i < collElementExprs.size(); i++) {
                if (bExpr == null) {
                    bExpr = (collElementExprs.get(i)).eq(elemExpr);
                } else {
                    bExpr = bExpr.ior((collElementExprs.get(i)).eq(elemExpr));
                }
            }
        }
        if (bExpr != null) {
            bExpr.encloseInParentheses();
        }
        return bExpr;
    }
    if (mmd == null) {
        throw new NucleusUserException("Cannot perform Collection.contains when the field metadata is not provided");
    }
    if (mmd.isSerialized()) {
        throw new NucleusUserException("Cannot perform Collection.contains when the collection is being serialised");
    }
    ApiAdapter api = stmt.getRDBMSManager().getApiAdapter();
    Class elementType = clr.classForName(mmd.getCollection().getElementType());
    if (!api.isPersistable(elementType) && mmd.getJoinMetaData() == null) {
        throw new NucleusUserException("Cannot perform Collection.contains when the collection<Non-Persistable> is not in a join table");
    }
    if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.FILTER) {
        boolean useSubquery = getNeedsSubquery(stmt, collExpr, elemExpr);
        JoinType joinType = JoinType.INNER_JOIN;
        if (elemExpr instanceof UnboundExpression) {
            // See if the user has defined what should be used
            String varName = ((UnboundExpression) elemExpr).getVariableName();
            String extensionName = "datanucleus.query.jdoql." + varName + ".join";
            String extensionValue = (String) stmt.getQueryGenerator().getValueForExtension(extensionName);
            if (extensionValue != null) {
                if (extensionValue.equalsIgnoreCase("SUBQUERY")) {
                    useSubquery = true;
                } else if (extensionValue.equalsIgnoreCase("INNERJOIN")) {
                    useSubquery = false;
                } else if (extensionValue.equalsIgnoreCase("LEFTOUTERJOIN")) {
                    joinType = JoinType.LEFT_OUTER_JOIN;
                }
            }
        }
        if (useSubquery) {
            return containsAsSubquery(stmt, collExpr, elemExpr);
        }
        return containsAsJoin(stmt, collExpr, elemExpr, joinType);
    }
    return containsAsSubquery(stmt, collExpr, elemExpr);
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) InExpression(org.datanucleus.store.rdbms.sql.expression.InExpression) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) CollectionLiteral(org.datanucleus.store.rdbms.sql.expression.CollectionLiteral) BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) CollectionExpression(org.datanucleus.store.rdbms.sql.expression.CollectionExpression) TemporalExpression(org.datanucleus.store.rdbms.sql.expression.TemporalExpression) ApiAdapter(org.datanucleus.api.ApiAdapter) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) NumericExpression(org.datanucleus.store.rdbms.sql.expression.NumericExpression) JoinType(org.datanucleus.store.rdbms.sql.SQLJoin.JoinType) EnumExpression(org.datanucleus.store.rdbms.sql.expression.EnumExpression) CharacterExpression(org.datanucleus.store.rdbms.sql.expression.CharacterExpression) StringExpression(org.datanucleus.store.rdbms.sql.expression.StringExpression) Collection(java.util.Collection) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

CollectionExpression (org.datanucleus.store.rdbms.sql.expression.CollectionExpression)4 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)4 BooleanExpression (org.datanucleus.store.rdbms.sql.expression.BooleanExpression)3 ArrayList (java.util.ArrayList)2 Collection (java.util.Collection)2 NucleusException (org.datanucleus.exceptions.NucleusException)2 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)2 CollectionLiteral (org.datanucleus.store.rdbms.sql.expression.CollectionLiteral)2 List (java.util.List)1 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)1 ApiAdapter (org.datanucleus.api.ApiAdapter)1 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)1 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)1 JoinType (org.datanucleus.store.rdbms.sql.SQLJoin.JoinType)1 CharacterExpression (org.datanucleus.store.rdbms.sql.expression.CharacterExpression)1 EnumExpression (org.datanucleus.store.rdbms.sql.expression.EnumExpression)1 InExpression (org.datanucleus.store.rdbms.sql.expression.InExpression)1 NullLiteral (org.datanucleus.store.rdbms.sql.expression.NullLiteral)1 NumericExpression (org.datanucleus.store.rdbms.sql.expression.NumericExpression)1 ParameterLiteral (org.datanucleus.store.rdbms.sql.expression.ParameterLiteral)1