Search in sources :

Example 1 with ArrayLiteral

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

the class ArrayContainsMethod 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() != 1) {
        throw new NucleusException("Incorrect arguments for Array.contains(SQLExpression)");
    }
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    ArrayExpression arrExpr = (ArrayExpression) expr;
    SQLExpression elemExpr = args.get(0);
    if (elemExpr.isParameter()) {
        // Element is a parameter so make sure its type is set
        AbstractMemberMetaData mmd = arrExpr.getJavaTypeMapping().getMemberMetaData();
        if (mmd != null) {
            stmt.getQueryGenerator().bindParameter(elemExpr.getParameterName(), mmd.getType().getComponentType());
        }
    }
    if (expr instanceof ArrayLiteral) {
        if (elemExpr instanceof UnboundExpression) {
            Class elemCls = clr.classForName(arrExpr.getJavaTypeMapping().getType()).getComponentType();
            elemExpr = stmt.getQueryGenerator().bindVariable((UnboundExpression) elemExpr, elemCls);
        }
        ArrayLiteral lit = (ArrayLiteral) expr;
        Object array = lit.getValue();
        JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
        if (array == null || Array.getLength(array) == 0) {
            return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
        }
        if (arrExpr.isParameter()) {
            stmt.getQueryGenerator().useParameterExpressionAsLiteral((ArrayLiteral) arrExpr);
        }
        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);
        }
        // TODO If elemExpr is a parameter and collExpr is derived from a parameter ?
        BooleanExpression bExpr = null;
        List<SQLExpression> elementExprs = lit.getElementExpressions();
        for (int i = 0; i < elementExprs.size(); i++) {
            SQLExpression arrElemExpr = elementExprs.get(i);
            if (bExpr == null) {
                bExpr = arrElemExpr.eq(elemExpr);
            } else {
                bExpr = bExpr.ior(arrElemExpr.eq(elemExpr));
            }
        }
        if (bExpr != null) {
            bExpr.encloseInParentheses();
        }
        return bExpr;
    } else if (arrExpr.getElementExpressions() != null) {
        if (elemExpr instanceof UnboundExpression) {
            Class elemCls = clr.classForName(arrExpr.getJavaTypeMapping().getType()).getComponentType();
            elemExpr = stmt.getQueryGenerator().bindVariable((UnboundExpression) elemExpr, elemCls);
        }
        // Array defined in query that has some expressions for elements, so just do OR chain
        BooleanExpression bExpr = null;
        List<SQLExpression> elementExprs = arrExpr.getElementExpressions();
        for (int i = 0; i < elementExprs.size(); i++) {
            SQLExpression arrElemExpr = elementExprs.get(i);
            if (bExpr == null) {
                bExpr = arrElemExpr.eq(elemExpr);
            } else {
                bExpr = bExpr.ior(arrElemExpr.eq(elemExpr));
            }
        }
        if (bExpr != null) {
            bExpr.encloseInParentheses();
        }
        return bExpr;
    } else {
        // TODO Support inner join variant
        return containsAsSubquery(stmt, arrExpr, elemExpr);
    }
}
Also used : TemporalExpression(org.datanucleus.store.rdbms.sql.expression.TemporalExpression) 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) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) NumericExpression(org.datanucleus.store.rdbms.sql.expression.NumericExpression) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) EnumExpression(org.datanucleus.store.rdbms.sql.expression.EnumExpression) ArrayLiteral(org.datanucleus.store.rdbms.sql.expression.ArrayLiteral) CharacterExpression(org.datanucleus.store.rdbms.sql.expression.CharacterExpression) BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) StringExpression(org.datanucleus.store.rdbms.sql.expression.StringExpression) ArrayExpression(org.datanucleus.store.rdbms.sql.expression.ArrayExpression) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) List(java.util.List) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 2 with ArrayLiteral

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

the class ArrayIsEmptyMethod 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) {
        throw new NucleusException(Localiser.msg("060015", "isEmpty", "ArrayExpression"));
    }
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    if (expr instanceof ArrayLiteral) {
        Object arr = ((ArrayLiteral) expr).getValue();
        boolean isEmpty = (arr == null || Array.getLength(arr) == 0);
        JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, false);
        return new BooleanLiteral(stmt, m, isEmpty ? Boolean.TRUE : Boolean.FALSE);
    }
    SQLExpression sizeExpr = exprFactory.invokeMethod(stmt, "ARRAY", "size", expr, args);
    JavaTypeMapping mapping = exprFactory.getMappingForType(Integer.class, true);
    SQLExpression zeroExpr = exprFactory.newLiteral(stmt, mapping, 0);
    return sizeExpr.eq(zeroExpr);
}
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) BooleanLiteral(org.datanucleus.store.rdbms.sql.expression.BooleanLiteral) NucleusException(org.datanucleus.exceptions.NucleusException) ArrayLiteral(org.datanucleus.store.rdbms.sql.expression.ArrayLiteral)

Example 3 with ArrayLiteral

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

the class ArraySizeMethod 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) {
        throw new NucleusException(Localiser.msg("060015", "size/length", "ArrayExpression"));
    }
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    if (expr instanceof ArrayLiteral) {
        // Just return the array length since we have the value
        return exprFactory.newLiteral(stmt, exprFactory.getMappingForType(int.class, false), Integer.valueOf(Array.getLength(((ArrayLiteral) expr).getValue())));
    }
    AbstractMemberMetaData ownerMmd = expr.getJavaTypeMapping().getMemberMetaData();
    String elementType = ownerMmd.getArray().getElementType();
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    // TODO Allow for interface elements, etc
    JavaTypeMapping ownerMapping = null;
    Table arrayTbl = null;
    if (ownerMmd.getMappedBy() != null) {
        // Bidirectional
        AbstractMemberMetaData elementMmd = ownerMmd.getRelatedMemberMetaData(clr)[0];
        if (ownerMmd.getJoinMetaData() != null || elementMmd.getJoinMetaData() != null) {
            // JoinTable
            arrayTbl = storeMgr.getTable(ownerMmd);
            ownerMapping = ((JoinTable) arrayTbl).getOwnerMapping();
        } else {
            // ForeignKey
            arrayTbl = storeMgr.getDatastoreClass(elementType, clr);
            ownerMapping = arrayTbl.getMemberMapping(elementMmd);
        }
    } else {
        // Unidirectional
        if (ownerMmd.getJoinMetaData() != null) {
            // JoinTable
            arrayTbl = storeMgr.getTable(ownerMmd);
            ownerMapping = ((JoinTable) arrayTbl).getOwnerMapping();
        } else {
            // ForeignKey
            arrayTbl = storeMgr.getDatastoreClass(elementType, clr);
            ownerMapping = ((DatastoreClass) arrayTbl).getExternalMapping(ownerMmd, MappingType.EXTERNAL_FK);
        }
    }
    SelectStatement subStmt = new SelectStatement(stmt, storeMgr, arrayTbl, null, null);
    subStmt.setClassLoaderResolver(clr);
    JavaTypeMapping mapping = storeMgr.getMappingManager().getMappingWithDatastoreMapping(String.class, false, false, clr);
    SQLExpression countExpr = exprFactory.newLiteral(subStmt, mapping, "COUNT(*)");
    ((StringLiteral) countExpr).generateStatementWithoutQuotes();
    subStmt.select(countExpr, null);
    SQLExpression elementOwnerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
    SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, expr.getSQLTable(), expr.getSQLTable().getTable().getIdMapping());
    subStmt.whereAnd(elementOwnerExpr.eq(ownerIdExpr), true);
    JavaTypeMapping subqMapping = exprFactory.getMappingForType(Integer.class, false);
    SQLExpression subqExpr = new NumericSubqueryExpression(stmt, subStmt);
    subqExpr.setJavaTypeMapping(subqMapping);
    return subqExpr;
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) Table(org.datanucleus.store.rdbms.table.Table) JoinTable(org.datanucleus.store.rdbms.table.JoinTable) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) ArrayLiteral(org.datanucleus.store.rdbms.sql.expression.ArrayLiteral) NumericSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) StringLiteral(org.datanucleus.store.rdbms.sql.expression.StringLiteral) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

NucleusException (org.datanucleus.exceptions.NucleusException)3 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)3 ArrayLiteral (org.datanucleus.store.rdbms.sql.expression.ArrayLiteral)3 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)3 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)3 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)2 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)2 List (java.util.List)1 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)1 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)1 ArrayExpression (org.datanucleus.store.rdbms.sql.expression.ArrayExpression)1 BooleanExpression (org.datanucleus.store.rdbms.sql.expression.BooleanExpression)1 BooleanLiteral (org.datanucleus.store.rdbms.sql.expression.BooleanLiteral)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 NumericExpression (org.datanucleus.store.rdbms.sql.expression.NumericExpression)1 NumericSubqueryExpression (org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression)1 StringExpression (org.datanucleus.store.rdbms.sql.expression.StringExpression)1 StringLiteral (org.datanucleus.store.rdbms.sql.expression.StringLiteral)1