Search in sources :

Example 36 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.

the class MapValueMethod method getAsJoin.

/**
 * Implementation of VALUE(map) using a join to the table representing the map, and returning the value.
 * @param stmt SQLStatement
 * @param mapExpr The map expression
 * @return The value expression
 */
protected SQLExpression getAsJoin(SQLStatement stmt, MapExpression mapExpr) {
    JavaTypeMapping m = mapExpr.getJavaTypeMapping();
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    AbstractMemberMetaData mmd = m.getMemberMetaData();
    // Use the statement of the table for this Map expression, since it could be in an outer query
    stmt = mapExpr.getSQLTable().getSQLStatement();
    if (mmd != null) {
        MapMetaData mapmd = mmd.getMap();
        SQLTable mapSqlTbl = mapExpr.getSQLTable();
        // Set alias of "map" table from MapExpression in case it was defined in FROM clause
        String mapJoinAlias = mapExpr.getAliasForMapTable();
        if (mapJoinAlias == null) {
            mapJoinAlias = (mapExpr.getSQLTable().getAlias().toString() + "_" + mmd.getName()).toUpperCase();
        }
        if (mapmd.getMapType() == MapType.MAP_TYPE_JOIN) {
            // Add join to join table
            MapTable joinTbl = (MapTable) storeMgr.getTable(mmd);
            SQLTable joinSqlTbl = stmt.getTable(mapJoinAlias);
            if (joinSqlTbl == null) {
                joinSqlTbl = stmt.join(JoinType.INNER_JOIN, mapSqlTbl, mapSqlTbl.getTable().getIdMapping(), joinTbl, mapJoinAlias, joinTbl.getOwnerMapping(), null, null);
            }
            // Return value expression
            if (mapmd.getValueClassMetaData(clr) != null && !mapmd.isEmbeddedValue()) {
                // Persistable value so join to its table (default to "{mapJoinAlias}_VALUE")
                DatastoreClass valTable = storeMgr.getDatastoreClass(mapmd.getValueType(), clr);
                SQLTable valueSqlTbl = stmt.getTable(mapJoinAlias + "_VALUE");
                if (valueSqlTbl == null) {
                    valueSqlTbl = stmt.join(JoinType.INNER_JOIN, joinSqlTbl, joinTbl.getValueMapping(), valTable, mapJoinAlias + "_VALUE", valTable.getIdMapping(), null, null);
                }
                return exprFactory.newExpression(stmt, valueSqlTbl, valTable.getIdMapping());
            }
            return exprFactory.newExpression(stmt, joinSqlTbl, joinTbl.getValueMapping());
        } else if (mapmd.getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
            // Key stored in value table, so join to value table
            DatastoreClass valTable = storeMgr.getDatastoreClass(mapmd.getValueType(), clr);
            AbstractClassMetaData valCmd = mmd.getMap().getValueClassMetaData(clr);
            JavaTypeMapping mapTblOwnerMapping;
            if (mmd.getMappedBy() != null) {
                mapTblOwnerMapping = valTable.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy()));
            } else {
                mapTblOwnerMapping = valTable.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
            }
            SQLTable valSqlTbl = stmt.join(JoinType.INNER_JOIN, mapSqlTbl, mapSqlTbl.getTable().getIdMapping(), valTable, mapJoinAlias, mapTblOwnerMapping, null, null);
            // Return value expression
            return exprFactory.newExpression(stmt, valSqlTbl, valTable.getIdMapping());
        } else if (mapmd.getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
            // Value stored in key table, so join to key table
            DatastoreClass keyTable = storeMgr.getDatastoreClass(mapmd.getKeyType(), clr);
            AbstractClassMetaData keyCmd = mmd.getMap().getKeyClassMetaData(clr);
            JavaTypeMapping mapTblOwnerMapping;
            if (mmd.getMappedBy() != null) {
                mapTblOwnerMapping = keyTable.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy()));
            } else {
                mapTblOwnerMapping = keyTable.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
            }
            SQLTable keySqlTbl = stmt.join(JoinType.INNER_JOIN, mapSqlTbl, mapSqlTbl.getTable().getIdMapping(), keyTable, mapJoinAlias, mapTblOwnerMapping, null, null);
            // Return value expression
            AbstractMemberMetaData valKeyMmd = mapmd.getKeyClassMetaData(clr).getMetaDataForMember(mmd.getValueMetaData().getMappedBy());
            JavaTypeMapping valueMapping = keyTable.getMemberMapping(valKeyMmd);
            return exprFactory.newExpression(stmt, keySqlTbl, valueMapping);
        }
    }
    throw new NucleusException("KEY(map) for the filter is not supported for " + mapExpr + ". Why not contribute support for it?");
}
Also used : MapTable(org.datanucleus.store.rdbms.table.MapTable) SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) MapMetaData(org.datanucleus.metadata.MapMetaData) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager)

Example 37 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.

the class MapValueMethod method getAsSubquery.

/**
 * Implementation of VALUE(map) using a subquery on the table representing the map, returning the value.
 * @param stmt SQLStatement
 * @param mapExpr The map expression
 * @return The value expression
 */
protected SQLExpression getAsSubquery(SQLStatement stmt, MapExpression mapExpr) {
    AbstractMemberMetaData mmd = mapExpr.getJavaTypeMapping().getMemberMetaData();
    MapMetaData mapmd = mmd.getMap();
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    JavaTypeMapping ownerMapping = null;
    JavaTypeMapping valMapping = null;
    Table mapTbl = null;
    if (mapmd.getMapType() == MapType.MAP_TYPE_JOIN) {
        // JoinTable
        mapTbl = storeMgr.getTable(mmd);
        ownerMapping = ((MapTable) mapTbl).getOwnerMapping();
        valMapping = ((MapTable) mapTbl).getValueMapping();
    } else if (mapmd.getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
        // ForeignKey from value table to key
        AbstractClassMetaData valCmd = mapmd.getValueClassMetaData(clr);
        mapTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr);
        if (mmd.getMappedBy() != null) {
            ownerMapping = mapTbl.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy()));
        } else {
            ownerMapping = ((DatastoreClass) mapTbl).getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        valMapping = mapTbl.getIdMapping();
    } else if (mapmd.getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
        // ForeignKey from key table to value
        AbstractClassMetaData keyCmd = mapmd.getKeyClassMetaData(clr);
        mapTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
        if (mmd.getMappedBy() != null) {
            ownerMapping = mapTbl.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy()));
        } else {
            ownerMapping = ((DatastoreClass) mapTbl).getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        String valFieldName = mmd.getValueMetaData().getMappedBy();
        AbstractMemberMetaData keyValMmd = keyCmd.getMetaDataForMember(valFieldName);
        valMapping = mapTbl.getMemberMapping(keyValMmd);
    } else {
        throw new NucleusException("Invalid map for " + mapExpr + " in get() call");
    }
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    SelectStatement subStmt = new SelectStatement(stmt, storeMgr, mapTbl, null, null);
    subStmt.setClassLoaderResolver(clr);
    SQLExpression valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valMapping);
    subStmt.select(valExpr, null);
    // Link to primary statement
    SQLExpression elementOwnerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
    SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
    subStmt.whereAnd(elementOwnerExpr.eq(ownerIdExpr), true);
    SubqueryExpression subExpr = new SubqueryExpression(stmt, subStmt);
    subExpr.setJavaTypeMapping(valMapping);
    return subExpr;
}
Also used : Table(org.datanucleus.store.rdbms.table.Table) MapTable(org.datanucleus.store.rdbms.table.MapTable) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) MapMetaData(org.datanucleus.metadata.MapMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) SubqueryExpression(org.datanucleus.store.rdbms.sql.expression.SubqueryExpression) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 38 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData 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 39 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.

the class ArrayContainsMethod method containsAsSubquery.

/**
 * Method to return an expression for Collection.contains using a subquery "EXISTS".
 * This is for use when there are "!contains" or "OR" operations in the filter.
 * Creates the following SQL,
 * <ul>
 * <li><b>Collection of NonPC using join table</b>
 * <pre>
 * SELECT 1 FROM JOIN_TBL A0_SUB
 * WHERE A0_SUB.JOIN_OWN_ID = A0.ID AND A0_SUB.JOIN_ELEM_ID = {elemExpr}
 * </pre>
 * </li>
 * <li><b>Collection of PC using join table</b>
 * <pre>
 * SELECT 1 FROM ELEM_TABLE A0_SUB INNER JOIN JOIN_TBL B0 ON ...
 * WHERE B0.JOIN_OWN_ID = A0.ID AND A0_SUB.ID = {elemExpr}
 * </pre>
 * </li>
 * </ul>
 * and returns a BooleanSubqueryExpression ("EXISTS (subquery)")
 * @param stmt SQLStatement
 * @param arrExpr Collection expression
 * @param elemExpr Expression for the element
 * @return Contains expression
 */
protected SQLExpression containsAsSubquery(SQLStatement stmt, ArrayExpression arrExpr, SQLExpression elemExpr) {
    boolean elemIsUnbound = (elemExpr instanceof UnboundExpression);
    String varName = null;
    if (elemIsUnbound) {
        varName = ((UnboundExpression) elemExpr).getVariableName();
        NucleusLogger.QUERY.debug(">> Array.contains binding unbound variable " + varName + " using SUBQUERY");
    }
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    AbstractMemberMetaData mmd = arrExpr.getJavaTypeMapping().getMemberMetaData();
    AbstractClassMetaData elemCmd = mmd.getArray().getElementClassMetaData(clr);
    ArrayTable joinTbl = (ArrayTable) storeMgr.getTable(mmd);
    SelectStatement subStmt = null;
    if (joinTbl != null) {
        // JoinTable array
        if (elemCmd == null) {
            // Array<Non-PC>
            subStmt = new SelectStatement(stmt, storeMgr, joinTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Restrict to array owner
            JavaTypeMapping ownerMapping = ((JoinTable) joinTbl).getOwnerMapping();
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, arrExpr.getSQLTable(), arrExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            SQLExpression elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), joinTbl.getElementMapping());
            if (elemIsUnbound) {
                // Bind the variable in the QueryGenerator
                stmt.getQueryGenerator().bindVariable(varName, null, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
            } else {
                // Add restrict to element
                subStmt.whereAnd(elemIdExpr.eq(elemExpr), true);
            }
        } else {
            // Array<PC>
            DatastoreClass elemTbl = storeMgr.getDatastoreClass(mmd.getArray().getElementType(), clr);
            subStmt = new SelectStatement(stmt, storeMgr, elemTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Join to join table
            SQLTable joinSqlTbl = subStmt.join(JoinType.INNER_JOIN, subStmt.getPrimaryTable(), elemTbl.getIdMapping(), null, joinTbl, null, joinTbl.getElementMapping(), null, null, null, true, null);
            // Restrict to array owner
            JavaTypeMapping ownerMapping = ((JoinTable) joinTbl).getOwnerMapping();
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, joinSqlTbl, ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, arrExpr.getSQLTable(), arrExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            SQLExpression elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), elemTbl.getIdMapping());
            if (elemIsUnbound) {
                // Bind the variable in the QueryGenerator
                stmt.getQueryGenerator().bindVariable(varName, elemCmd, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
            } else {
                // Add restrict to element
                subStmt.whereAnd(elemIdExpr.eq(elemExpr), true);
            }
        }
    } else {
        // TODO Support FK array ?
        throw new NucleusException("Dont support evaluation of ARRAY.contains when no join table is used");
    }
    return new BooleanSubqueryExpression(stmt, "EXISTS", subStmt);
}
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) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) BooleanSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.BooleanSubqueryExpression) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) ArrayTable(org.datanucleus.store.rdbms.table.ArrayTable) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) JoinTable(org.datanucleus.store.rdbms.table.JoinTable)

Example 40 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData 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

AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)267 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)89 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)84 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)82 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)59 ClassMetaData (org.datanucleus.metadata.ClassMetaData)55 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)50 NucleusException (org.datanucleus.exceptions.NucleusException)41 MetaDataManager (org.datanucleus.metadata.MetaDataManager)40 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)38 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)35 RelationType (org.datanucleus.metadata.RelationType)33 NucleusContext (org.datanucleus.NucleusContext)32 PersistenceNucleusContextImpl (org.datanucleus.PersistenceNucleusContextImpl)32 JPAMetaDataManager (org.datanucleus.api.jpa.metadata.JPAMetaDataManager)29 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)28 ColumnMetaData (org.datanucleus.metadata.ColumnMetaData)27 ExecutionContext (org.datanucleus.ExecutionContext)26 ObjectProvider (org.datanucleus.state.ObjectProvider)25 ArrayList (java.util.ArrayList)24