Search in sources :

Example 36 with SQLTable

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

the class MapKeyMethod method getAsJoin.

/**
 * Implementation of KEY(mapExpr) using a join to the table representing the map, and returning an expression for the key.
 * @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 key expression
            if (mapmd.getKeyClassMetaData(clr) != null && !mapmd.isEmbeddedKey()) {
                // Persistable key so join to its table (default to "{mapJoinAlias}_KEY")
                DatastoreClass keyTable = storeMgr.getDatastoreClass(mapmd.getKeyType(), clr);
                SQLTable keySqlTbl = stmt.getTable(mapJoinAlias + "_KEY");
                if (keySqlTbl == null) {
                    keySqlTbl = stmt.join(JoinType.INNER_JOIN, joinSqlTbl, joinTbl.getKeyMapping(), keyTable, mapJoinAlias + "_KEY", keyTable.getIdMapping(), null, null);
                }
                return exprFactory.newExpression(stmt, keySqlTbl, keyTable.getIdMapping());
            }
            return exprFactory.newExpression(stmt, joinSqlTbl, joinTbl.getKeyMapping());
        } 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 key expression
            AbstractMemberMetaData valKeyMmd = mapmd.getValueClassMetaData(clr).getMetaDataForMember(mmd.getKeyMetaData().getMappedBy());
            JavaTypeMapping keyMapping = valTable.getMemberMapping(valKeyMmd);
            return exprFactory.newExpression(stmt, valSqlTbl, keyMapping);
        } 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 key expression
            return exprFactory.newExpression(stmt, keySqlTbl, keyTable.getIdMapping());
        }
    }
    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 SQLTable

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

the class CollectionContainsMethod method containsAsJoin.

/**
 * Method to return an expression for Collection.contains using INNER JOIN to the element.
 * This is only for use when there are no "!contains" and no "OR" operations.
 * Creates SQL by adding INNER JOIN to the join table (where it exists), and also to the element table
 * adding an AND condition on the element (with value of the elemExpr).
 * Returns a BooleanExpression "TRUE" (since the INNER JOIN will guarantee if the element is
 * contained of not).
 * @param stmt SQLStatement
 * @param collExpr Collection expression
 * @param elemExpr Expression for the element
 * @param joinType Join type
 * @return Contains expression
 */
protected SQLExpression containsAsJoin(SQLStatement stmt, CollectionExpression collExpr, SQLExpression elemExpr, SQLJoin.JoinType joinType) {
    boolean elemIsUnbound = (elemExpr instanceof UnboundExpression);
    String varName = null;
    String elemAlias = null;
    String elemType = null;
    if (elemIsUnbound) {
        varName = ((UnboundExpression) elemExpr).getVariableName();
        NucleusLogger.QUERY.debug("collection.contains(" + elemExpr + ") binding unbound variable " + varName + " using INNER JOIN");
    } else if (!stmt.getQueryGenerator().hasExplicitJoins()) {
        if (stmt.getJoinTypeForTable(elemExpr.getSQLTable()) == JoinType.CROSS_JOIN) {
            elemAlias = stmt.removeCrossJoin(elemExpr.getSQLTable());
            elemIsUnbound = true;
            elemType = elemExpr.getJavaTypeMapping().getType();
            NucleusLogger.QUERY.debug("collection.contains(" + elemExpr + ") was previously bound as CROSS JOIN but changing to INNER JOIN");
        }
    }
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    AbstractMemberMetaData mmd = collExpr.getJavaTypeMapping().getMemberMetaData();
    AbstractClassMetaData elemCmd = mmd.getCollection().getElementClassMetaData(clr);
    CollectionTable joinTbl = (CollectionTable) storeMgr.getTable(mmd);
    if (elemIsUnbound) {
        Class varType = stmt.getQueryGenerator().getTypeOfVariable(varName);
        if (varType != null) {
            elemType = varType.getName();
            elemCmd = storeMgr.getMetaDataManager().getMetaDataForClass(elemType, clr);
        }
    }
    if (elemType == null) {
        elemType = mmd.getCollection().getElementType();
    }
    if (joinTbl != null) {
        // JoinTable Collection - join from owner to join, then from join to element
        if (elemCmd == null) {
            // Collection<Non-PC>
            SQLTable joinSqlTbl = stmt.join(joinType, collExpr.getSQLTable(), collExpr.getSQLTable().getTable().getIdMapping(), joinTbl, elemAlias, joinTbl.getOwnerMapping(), null, null);
            SQLExpression elemIdExpr = exprFactory.newExpression(stmt, joinSqlTbl, joinTbl.getElementMapping());
            if (elemIsUnbound) {
                // Bind the variable in the QueryGenerator
                stmt.getQueryGenerator().bindVariable(varName, null, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
            } else {
                // Add restrict to element
                addRestrictionOnElement(stmt, elemIdExpr, elemExpr);
            }
        } else {
            // Collection<PC>
            SQLTable joinSqlTbl = stmt.join(joinType, collExpr.getSQLTable(), collExpr.getSQLTable().getTable().getIdMapping(), joinTbl, null, joinTbl.getOwnerMapping(), null, null);
            if (!mmd.getCollection().isEmbeddedElement()) {
                DatastoreClass elemTbl = storeMgr.getDatastoreClass(elemType, clr);
                SQLTable elemSqlTbl = null;
                if (joinTbl.getElementMapping() instanceof ReferenceMapping && ((ReferenceMapping) joinTbl.getElementMapping()).getMappingStrategy() == ReferenceMapping.PER_IMPLEMENTATION_MAPPING) {
                    JavaTypeMapping elemMapping = null;
                    JavaTypeMapping[] elemImplMappings = ((ReferenceMapping) joinTbl.getElementMapping()).getJavaTypeMapping();
                    for (int i = 0; i < elemImplMappings.length; i++) {
                        if (elemImplMappings[i].getType().equals(elemCmd.getFullClassName())) {
                            elemMapping = elemImplMappings[i];
                            break;
                        }
                    }
                    elemSqlTbl = stmt.join(joinType, joinSqlTbl, elemMapping, joinTbl.getElementMapping(), elemTbl, elemAlias, elemTbl.getIdMapping(), null, null, null, true, null);
                } else {
                    elemSqlTbl = stmt.join(joinType, joinSqlTbl, joinTbl.getElementMapping(), elemTbl, elemAlias, elemTbl.getIdMapping(), null, null);
                }
                SQLExpression elemIdExpr = exprFactory.newExpression(stmt, elemSqlTbl, elemTbl.getIdMapping());
                if (elemIsUnbound) {
                    // Bind the variable in the QueryGenerator
                    stmt.getQueryGenerator().bindVariable(varName, elemCmd, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
                } else {
                    // Add restrict to element
                    addRestrictionOnElement(stmt, elemIdExpr, elemExpr);
                }
            } else {
                SQLExpression elemIdExpr = exprFactory.newExpression(stmt, joinSqlTbl, joinTbl.getElementMapping());
                if (elemIsUnbound) {
                    // Bind the variable in the QueryGenerator
                    stmt.getQueryGenerator().bindVariable(varName, elemCmd, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
                } else {
                    // Add restrict to element
                    addRestrictionOnElement(stmt, elemIdExpr, elemExpr);
                }
            }
        }
    } else {
        // FK Collection - join from owner to element
        DatastoreClass elemTbl = storeMgr.getDatastoreClass(mmd.getCollection().getElementType(), clr);
        JavaTypeMapping ownerMapping = null;
        if (mmd.getMappedBy() != null) {
            ownerMapping = elemTbl.getMemberMapping(mmd.getRelatedMemberMetaData(clr)[0]);
        } else {
            ownerMapping = elemTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        SQLTable elemSqlTbl = stmt.join(joinType, collExpr.getSQLTable(), collExpr.getSQLTable().getTable().getIdMapping(), elemTbl, elemAlias, ownerMapping, null, null);
        if (elemIsUnbound) {
            SQLExpression elemIdExpr = null;
            if (!elemType.equals(mmd.getCollection().getElementType())) {
                // Variable is defined as a subclass of the declared type so add extra join to variable type
                DatastoreClass varTbl = storeMgr.getDatastoreClass(elemType, clr);
                SQLTable varSqlTbl = stmt.join(joinType, elemSqlTbl, elemTbl.getIdMapping(), varTbl, null, varTbl.getIdMapping(), null, null);
                elemIdExpr = exprFactory.newExpression(stmt, varSqlTbl, varTbl.getIdMapping());
            } else {
                elemIdExpr = exprFactory.newExpression(stmt, elemSqlTbl, elemTbl.getIdMapping());
            }
            // Bind the variable in the QueryGenerator
            stmt.getQueryGenerator().bindVariable(varName, elemCmd, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
        } else {
            // Add restrict to element
            SQLExpression elemIdExpr = exprFactory.newExpression(stmt, elemSqlTbl, elemTbl.getIdMapping());
            addRestrictionOnElement(stmt, elemIdExpr, elemExpr);
        }
    }
    JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
    return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, true));
}
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) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) CollectionTable(org.datanucleus.store.rdbms.table.CollectionTable) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 38 with SQLTable

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

the class ListGetMethod method getAsInnerJoin.

/**
 * Implementation of List.get() using an inner join to the table representing the list, adding a condition on the index and returning the element.
 * @param stmt SQLStatement
 * @param listExpr The list expression
 * @param idxExpr The index expression
 * @return The element expression
 */
protected SQLExpression getAsInnerJoin(SQLStatement stmt, CollectionExpression listExpr, SQLExpression idxExpr) {
    JavaTypeMapping m = listExpr.getJavaTypeMapping();
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    AbstractMemberMetaData mmd = m.getMemberMetaData();
    AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
    if (mmd.getJoinMetaData() != null || relatedMmds != null && relatedMmds[0].getJoinMetaData() != null) {
        // Join table List
        CollectionTable joinTbl = (CollectionTable) storeMgr.getTable(mmd);
        // Add join to join table
        SQLTable joinSqlTbl = stmt.join(JoinType.INNER_JOIN, listExpr.getSQLTable(), listExpr.getSQLTable().getTable().getIdMapping(), joinTbl, null, joinTbl.getOwnerMapping(), null, null);
        // Add condition on index
        SQLExpression idxSqlExpr = exprFactory.newExpression(stmt, joinSqlTbl, joinTbl.getOrderMapping());
        stmt.whereAnd(idxSqlExpr.eq(idxExpr), true);
        // Return element expression
        SQLExpression valueExpr = exprFactory.newExpression(stmt, joinSqlTbl, joinTbl.getElementMapping());
        return valueExpr;
    }
    // FK List
    DatastoreClass elementTbl = storeMgr.getDatastoreClass(mmd.getCollection().getElementType(), clr);
    // Add join to element table
    JavaTypeMapping targetMapping = null;
    JavaTypeMapping orderMapping = null;
    if (relatedMmds != null) {
        targetMapping = elementTbl.getMemberMapping(relatedMmds[0]);
        orderMapping = elementTbl.getExternalMapping(mmd, MappingType.EXTERNAL_INDEX);
    } else {
        targetMapping = elementTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        orderMapping = elementTbl.getExternalMapping(mmd, MappingType.EXTERNAL_INDEX);
    }
    SQLTable elemSqlTbl = stmt.join(JoinType.INNER_JOIN, listExpr.getSQLTable(), listExpr.getSQLTable().getTable().getIdMapping(), elementTbl, null, targetMapping, null, null);
    // Add condition on index
    SQLExpression idxSqlExpr = exprFactory.newExpression(stmt, elemSqlTbl, orderMapping);
    stmt.whereAnd(idxSqlExpr.eq(idxExpr), true);
    // Return element expression
    return exprFactory.newExpression(stmt, elemSqlTbl, elementTbl.getIdMapping());
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) CollectionTable(org.datanucleus.store.rdbms.table.CollectionTable) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) 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) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager)

Example 39 with SQLTable

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

the class SQLExpressionFactory method newExpression.

/**
 * Factory for an expression representing a mapping on a table.
 * @param stmt The statement
 * @param sqlTbl The table
 * @param mapping The mapping
 * @param parentMapping Optional parent mapping of this mapping (e.g when handling an implementation of an interface)
 * @return The expression
 */
public SQLExpression newExpression(SQLStatement stmt, SQLTable sqlTbl, JavaTypeMapping mapping, JavaTypeMapping parentMapping) {
    // Use "new SQLExpression(SQLStatement, SQLTable, JavaTypeMapping)"
    SQLTable exprSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, sqlTbl, parentMapping == null ? mapping : parentMapping);
    Object[] args = new Object[] { stmt, exprSqlTbl, mapping };
    Class expressionClass = expressionClassByMappingName.get(mapping.getClass().getName());
    if (expressionClass != null) {
        // Use built-in expression class
        return (SQLExpression) ClassUtils.newInstance(expressionClass, EXPR_CREATION_ARG_TYPES, new Object[] { stmt, exprSqlTbl, mapping });
    }
    try {
        // Fallback to the plugin mechanism
        SQLExpression sqlExpr = (SQLExpression) storeMgr.getNucleusContext().getPluginManager().createExecutableExtension("org.datanucleus.store.rdbms.sql_expression", "mapping-class", mapping.getClass().getName(), "expression-class", EXPR_CREATION_ARG_TYPES, args);
        if (sqlExpr == null) {
            throw new NucleusException(Localiser.msg("060004", mapping.getClass().getName()));
        }
        expressionClassByMappingName.put(mapping.getClass().getName(), sqlExpr.getClass());
        return sqlExpr;
    } catch (Exception e) {
        String msg = Localiser.msg("060005", mapping.getClass().getName());
        NucleusLogger.QUERY.error(msg, e);
        throw new NucleusException(msg, e);
    }
}
Also used : SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) NucleusException(org.datanucleus.exceptions.NucleusException) NucleusException(org.datanucleus.exceptions.NucleusException) ClassNotResolvedException(org.datanucleus.exceptions.ClassNotResolvedException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException)

Aggregations

SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)39 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)34 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)31 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)30 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)26 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)20 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)20 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)20 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)19 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)17 NucleusException (org.datanucleus.exceptions.NucleusException)16 StatementClassMapping (org.datanucleus.store.rdbms.query.StatementClassMapping)12 MapTable (org.datanucleus.store.rdbms.table.MapTable)12 UnboundExpression (org.datanucleus.store.rdbms.sql.expression.UnboundExpression)11 DiscriminatorStatementGenerator (org.datanucleus.store.rdbms.sql.DiscriminatorStatementGenerator)10 UnionStatementGenerator (org.datanucleus.store.rdbms.sql.UnionStatementGenerator)10 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)9 ReferenceMapping (org.datanucleus.store.rdbms.mapping.java.ReferenceMapping)8 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)8 CollectionTable (org.datanucleus.store.rdbms.table.CollectionTable)7