Search in sources :

Example 61 with DatastoreClass

use of org.datanucleus.store.rdbms.table.DatastoreClass in project datanucleus-rdbms by datanucleus.

the class SQLStatementHelper method selectFetchPlanFieldsOfFKRelatedObject.

/**
 * Convenience method to join to and select all required FP fields of a related object where linked via an FK at this side.
 * @return Whether the caller should select the FK themselves (i.e we haven't selected anything)
 */
private static boolean selectFetchPlanFieldsOfFKRelatedObject(SelectStatement stmt, StatementClassMapping mappingDefinition, FetchPlan fetchPlan, SQLTable sourceSqlTbl, AbstractMemberMetaData mmd, ClassLoaderResolver clr, int maxFetchPlanLimit, JavaTypeMapping m, String tableGroupName, StatementMappingIndex stmtMapping, SQLTable sqlTbl, JoinType inputJoinType) {
    boolean selectFK = true;
    if (mmd.fetchFKOnly()) {
    // Only want FK fetching, and not the fields of the object (so avoid the join)
    } else {
        RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
        Class type = mmd.isSingleCollection() ? clr.classForName(mmd.getCollection().getElementType()) : mmd.getType();
        if (m instanceof ReferenceMapping) {
            ReferenceMapping refMapping = (ReferenceMapping) m;
            if (refMapping.getMappingStrategy() == ReferenceMapping.PER_IMPLEMENTATION_MAPPING && refMapping.getJavaTypeMapping().length == 1) {
                JavaTypeMapping[] subMappings = refMapping.getJavaTypeMapping();
                if (subMappings != null && subMappings.length == 1) {
                    // Special case of reference mapping with single FK implementation
                    type = clr.classForName(refMapping.getJavaTypeMapping()[0].getType());
                }
            }
        }
        // select fetch plan fields of this object
        AbstractClassMetaData relatedCmd = storeMgr.getMetaDataManager().getMetaDataForClass(type, clr);
        if (relatedCmd != null) {
            if (relatedCmd.isEmbeddedOnly()) {
                return true;
            }
            if (relatedCmd.getBaseAbstractClassMetaData().getInheritanceMetaData().getStrategy() == InheritanceStrategy.COMPLETE_TABLE) {
                // Related object uses complete-table
                Collection<String> relSubclassNames = storeMgr.getSubClassesForClass(relatedCmd.getFullClassName(), true, clr);
                if (relatedCmd.isMappedSuperclass() && relSubclassNames.size() > 1) {
                    // Multiple possible related types and we don't have the FK so omit
                    return true;
                } else if (!relatedCmd.isMappedSuperclass() && relSubclassNames.size() > 0) {
                    // Multiple possible related types and we don't have the FK so omit
                    return true;
                }
            // TODO Maybe do a LEFT OUTER JOIN to each possible?
            }
            // Find the table of the related class
            DatastoreClass relatedTbl = storeMgr.getDatastoreClass(relatedCmd.getFullClassName(), clr);
            if (relatedTbl == null) {
                // Class doesn't have its own table (subclass-table) so find where it persists
                AbstractClassMetaData[] ownerParentCmds = storeMgr.getClassesManagingTableForClass(relatedCmd, clr);
                if (ownerParentCmds.length > 1) {
                    NucleusLogger.QUERY.info("Relation (" + mmd.getFullFieldName() + ") with multiple related tables (using subclass-table). Not supported so selecting FK of related object only");
                    return true;
                }
                relatedTbl = storeMgr.getDatastoreClass(ownerParentCmds[0].getFullClassName(), clr);
            }
            String requiredGroupName = null;
            if (sourceSqlTbl.getGroupName() != null) {
                // JPQL will have table groups defined already, named as per "alias.fieldName"
                requiredGroupName = sourceSqlTbl.getGroupName() + "." + mmd.getName();
            }
            SQLTable relatedSqlTbl = stmt.getTable(relatedTbl, requiredGroupName);
            if (relatedSqlTbl == null) {
                // Join the 1-1 relation
                JoinType joinType = getJoinTypeForOneToOneRelationJoin(m, sqlTbl, inputJoinType);
                if (joinType == JoinType.LEFT_OUTER_JOIN || joinType == JoinType.RIGHT_OUTER_JOIN) {
                    inputJoinType = joinType;
                }
                relatedSqlTbl = addJoinForOneToOneRelation(stmt, m, sqlTbl, relatedTbl.getIdMapping(), relatedTbl, null, null, tableGroupName, joinType);
            }
            StatementClassMapping subMappingDefinition = new StatementClassMapping(mmd.getClassName(), mmd.getName());
            selectFetchPlanOfSourceClassInStatement(stmt, subMappingDefinition, fetchPlan, relatedSqlTbl, relatedCmd, maxFetchPlanLimit - 1, inputJoinType);
            if (mappingDefinition != null) {
                if (relatedCmd.getIdentityType() == IdentityType.APPLICATION) {
                    int[] pkFields = relatedCmd.getPKMemberPositions();
                    int[] pkCols = new int[m.getNumberOfDatastoreMappings()];
                    int pkColNo = 0;
                    for (int pkField : pkFields) {
                        StatementMappingIndex pkIdx = subMappingDefinition.getMappingForMemberPosition(pkField);
                        int[] pkColNumbers = pkIdx.getColumnPositions();
                        for (int pkColNumber : pkColNumbers) {
                            pkCols[pkColNo] = pkColNumber;
                            pkColNo++;
                        }
                    }
                    selectFK = false;
                    stmtMapping.setColumnPositions(pkCols);
                } else if (relatedCmd.getIdentityType() == IdentityType.DATASTORE) {
                    StatementMappingIndex pkIdx = subMappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
                    selectFK = false;
                    stmtMapping.setColumnPositions(pkIdx.getColumnPositions());
                }
                mappingDefinition.addMappingDefinitionForMember(mmd.getAbsoluteFieldNumber(), subMappingDefinition);
            }
        } else {
        // TODO 1-1 interface relation
        }
    }
    return selectFK;
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) JoinType(org.datanucleus.store.rdbms.sql.SQLJoin.JoinType) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) SecondaryDatastoreClass(org.datanucleus.store.rdbms.table.SecondaryDatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) SecondaryDatastoreClass(org.datanucleus.store.rdbms.table.SecondaryDatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass)

Example 62 with DatastoreClass

use of org.datanucleus.store.rdbms.table.DatastoreClass in project datanucleus-rdbms by datanucleus.

the class SQLStatementHelper method selectIdentityOfCandidateInStatement.

/**
 * Method to select the identity for the candidate class.
 * The supplied statement and mapping definition are updated during this method.
 * Selects the datastore id (if using datastore id) as "DN_DATASTOREID",
 * the version (if present) as "DN_VERSION", the discriminator (if present) as "DN_DISCRIM",
 * and the application id (if using application id) as "DN_APPID_{i}"
 * @param stmt The statement
 * @param mappingDefinition Mapping definition for result columns
 * @param candidateCmd The candidate class meta-data
 */
public static void selectIdentityOfCandidateInStatement(SelectStatement stmt, StatementClassMapping mappingDefinition, AbstractClassMetaData candidateCmd) {
    DatastoreClass candidateTbl = (DatastoreClass) stmt.getPrimaryTable().getTable();
    if (candidateCmd.getIdentityType() == IdentityType.DATASTORE) {
        // Datastore-identity surrogate column
        JavaTypeMapping idMapping = candidateTbl.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
        int[] colNumbers = stmt.select(stmt.getPrimaryTable(), idMapping, "DN_DATASTOREID", false);
        if (mappingDefinition != null) {
            StatementMappingIndex datastoreIdIdx = new StatementMappingIndex(idMapping);
            datastoreIdIdx.setColumnPositions(colNumbers);
            mappingDefinition.addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), datastoreIdIdx);
        }
    } else if (candidateCmd.getIdentityType() == IdentityType.APPLICATION) {
        // Application-identity column(s)
        int[] pkPositions = candidateCmd.getPKMemberPositions();
        String alias = "DN_APPID";
        for (int i = 0; i < pkPositions.length; i++) {
            AbstractMemberMetaData pkMmd = candidateCmd.getMetaDataForManagedMemberAtAbsolutePosition(pkPositions[i]);
            JavaTypeMapping pkMapping = candidateTbl.getMemberMapping(pkMmd);
            SQLTable sqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, stmt.getPrimaryTable(), pkMapping);
            if (pkPositions.length > 1) {
                alias = "DN_APPID" + i;
            }
            int[] colNumbers = stmt.select(sqlTbl, pkMapping, alias, false);
            if (mappingDefinition != null) {
                StatementMappingIndex appIdIdx = new StatementMappingIndex(pkMapping);
                appIdIdx.setColumnPositions(colNumbers);
                mappingDefinition.addMappingForMember(pkPositions[i], appIdIdx);
            }
        }
    }
    JavaTypeMapping verMapping = candidateTbl.getSurrogateMapping(SurrogateColumnType.VERSION, true);
    if (verMapping != null) {
        // Version surrogate column (adds inner join to any required superclass table)
        SQLTable versionSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, stmt.getPrimaryTable(), verMapping);
        int[] colNumbers = stmt.select(versionSqlTbl, verMapping, "DN_VERSION", false);
        if (mappingDefinition != null) {
            StatementMappingIndex versionIdx = new StatementMappingIndex(verMapping);
            versionIdx.setColumnPositions(colNumbers);
            mappingDefinition.addMappingForMember(SurrogateColumnType.VERSION.getFieldNumber(), versionIdx);
        }
    }
    JavaTypeMapping discrimMapping = candidateTbl.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, true);
    if (discrimMapping != null) {
        // Discriminator surrogate column (adds inner join to any required superclass table)
        SQLTable discrimSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, stmt.getPrimaryTable(), discrimMapping);
        int[] colNumbers = stmt.select(discrimSqlTbl, discrimMapping, "DN_DISCRIM", false);
        if (mappingDefinition != null) {
            StatementMappingIndex discrimIdx = new StatementMappingIndex(discrimMapping);
            discrimIdx.setColumnPositions(colNumbers);
            mappingDefinition.addMappingForMember(SurrogateColumnType.DISCRIMINATOR.getFieldNumber(), discrimIdx);
        }
    }
    List<SelectStatement> unionStmts = stmt.getUnions();
    if (unionStmts != null) {
        Iterator<SelectStatement> iter = unionStmts.iterator();
        while (iter.hasNext()) {
            SelectStatement unionStmt = iter.next();
            selectIdentityOfCandidateInStatement(unionStmt, null, candidateCmd);
        }
    }
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SecondaryDatastoreClass(org.datanucleus.store.rdbms.table.SecondaryDatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 63 with DatastoreClass

use of org.datanucleus.store.rdbms.table.DatastoreClass in project datanucleus-rdbms by datanucleus.

the class SQLStatementHelper method getSQLTableForMappingOfTable.

/**
 * Method to return the SQLTable where the specified mapping (in the same table group as the provided
 * SQLTable) is defined. If the statement doesn't currently join to the required table then a join will
 * be added. If the required table is a superclass table then the join will be INNER. If the required
 * table is a secondary table then the join will be defined by the meta-data for the secondary table.
 * If this table group is NOT the candidate table group then LEFT OUTER JOIN will be used.
 * @param stmt The statement
 * @param sqlTbl SQLTable to start from for the supplied mapping (may be in super-table, or secondary-table of this)
 * @param mapping The mapping
 * @return The SQLTable for this mapping (may have been added to the statement during this method)
 */
public static SQLTable getSQLTableForMappingOfTable(SQLStatement stmt, SQLTable sqlTbl, JavaTypeMapping mapping) {
    Table table = sqlTbl.getTable();
    if (table instanceof SecondaryDatastoreClass || table instanceof JoinTable) {
        // Secondary/join tables have no inheritance so ought to be correct
        if (mapping.getTable() != null) {
            // Check there is no better table already present in the TableGroup for this mapping
            // This can happen when we do a select of a join table and the element table is in the
            // same table group, so hence already is present
            SQLTable mappingSqlTbl = stmt.getTable(mapping.getTable(), sqlTbl.getGroupName());
            if (mappingSqlTbl != null) {
                return mappingSqlTbl;
            }
        }
        return sqlTbl;
    }
    DatastoreClass sourceTbl = (DatastoreClass) sqlTbl.getTable();
    DatastoreClass mappingTbl = null;
    if (mapping.getTable() != null) {
        mappingTbl = (DatastoreClass) mapping.getTable();
    } else {
        mappingTbl = sourceTbl.getBaseDatastoreClassWithMember(mapping.getMemberMetaData());
    }
    if (mappingTbl == sourceTbl) {
        return sqlTbl;
    }
    // Try to find this datastore table in the same table group
    SQLTable mappingSqlTbl = stmt.getTable(mappingTbl, sqlTbl.getGroupName());
    if (mappingSqlTbl == null) {
        boolean forceLeftOuter = false;
        SQLTableGroup tableGrp = stmt.getTableGroup(sqlTbl.getGroupName());
        if (tableGrp.getJoinType() == JoinType.LEFT_OUTER_JOIN) {
            // This group isn't the candidate group, and we joined to the candidate group using
            // a left outer join originally, so use the same type for this table
            forceLeftOuter = true;
        }
        if (mappingTbl instanceof SecondaryDatastoreClass) {
            // Secondary table, so add inner/outer based on metadata
            boolean innerJoin = true;
            JoinMetaData joinmd = ((SecondaryDatastoreClass) mappingTbl).getJoinMetaData();
            if (joinmd != null && joinmd.isOuter() && !forceLeftOuter) {
                innerJoin = false;
            }
            if (innerJoin && !forceLeftOuter) {
                // Add join from {sourceTbl}.ID to {secondaryTbl}.ID
                mappingSqlTbl = stmt.join(JoinType.INNER_JOIN, sqlTbl, sqlTbl.getTable().getIdMapping(), mappingTbl, null, mappingTbl.getIdMapping(), null, sqlTbl.getGroupName());
            } else {
                // Add join from {sourceTbl}.ID to {secondaryTbl}.ID
                mappingSqlTbl = stmt.join(JoinType.LEFT_OUTER_JOIN, sqlTbl, sqlTbl.getTable().getIdMapping(), mappingTbl, null, mappingTbl.getIdMapping(), null, sqlTbl.getGroupName());
            }
        } else {
            if (forceLeftOuter) {
                // Add join from {sourceTbl}.ID to {superclassTbl}.ID
                mappingSqlTbl = stmt.join(JoinType.LEFT_OUTER_JOIN, sqlTbl, sqlTbl.getTable().getIdMapping(), mappingTbl, null, mappingTbl.getIdMapping(), null, sqlTbl.getGroupName());
            } else {
                // Add join from {sourceTbl}.ID to {superclassTbl}.ID
                mappingSqlTbl = stmt.join(JoinType.INNER_JOIN, sqlTbl, sqlTbl.getTable().getIdMapping(), mappingTbl, null, mappingTbl.getIdMapping(), null, sqlTbl.getGroupName());
            }
        }
    }
    return mappingSqlTbl;
}
Also used : PersistableJoinTable(org.datanucleus.store.rdbms.table.PersistableJoinTable) Table(org.datanucleus.store.rdbms.table.Table) JoinTable(org.datanucleus.store.rdbms.table.JoinTable) JoinMetaData(org.datanucleus.metadata.JoinMetaData) SecondaryDatastoreClass(org.datanucleus.store.rdbms.table.SecondaryDatastoreClass) SecondaryDatastoreClass(org.datanucleus.store.rdbms.table.SecondaryDatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) PersistableJoinTable(org.datanucleus.store.rdbms.table.PersistableJoinTable) JoinTable(org.datanucleus.store.rdbms.table.JoinTable)

Example 64 with DatastoreClass

use of org.datanucleus.store.rdbms.table.DatastoreClass in project datanucleus-rdbms by datanucleus.

the class SQLStatementHelper method selectFetchPlanOfSourceClassInStatement.

/**
 * Method to select all fetch plan members for the "source" class.
 * If the passed FetchPlan is null then the default fetch group fields will be selected.
 * The source class is defined by the supplied meta-data, and the SQLTable that we are selecting from.
 * The supplied statement and mapping definition are updated during this method.
 * @param stmt The statement
 * @param mappingDefinition Mapping definition for result columns (populated with column positions
 *                          of any selected mappings if provided as input)
 * @param fetchPlan FetchPlan in use
 * @param sourceSqlTbl SQLTable for the source class that we select from
 * @param sourceCmd Meta-data for the source class
 * @param maxFetchDepth Max fetch depth from this point to select (0 implies no other objects)
 * @param inputJoinType Optional join type to use for subobjects (otherwise decide join type internally)
 */
public static void selectFetchPlanOfSourceClassInStatement(SelectStatement stmt, StatementClassMapping mappingDefinition, FetchPlan fetchPlan, SQLTable sourceSqlTbl, AbstractClassMetaData sourceCmd, int maxFetchDepth, JoinType inputJoinType) {
    DatastoreClass sourceTbl = (DatastoreClass) sourceSqlTbl.getTable();
    int[] fieldNumbers;
    if (fetchPlan != null) {
        // Use FetchPlan fields
        fieldNumbers = fetchPlan.getFetchPlanForClass(sourceCmd).getMemberNumbers();
    } else {
        // Use DFG fields
        fieldNumbers = sourceCmd.getDFGMemberPositions();
    }
    ClassLoaderResolver clr = stmt.getRDBMSManager().getNucleusContext().getClassLoaderResolver(null);
    for (int fieldNumber : fieldNumbers) {
        AbstractMemberMetaData mmd = sourceCmd.getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
        selectMemberOfSourceInStatement(stmt, mappingDefinition, fetchPlan, sourceSqlTbl, mmd, clr, maxFetchDepth, inputJoinType);
    }
    if (sourceCmd.getIdentityType() == IdentityType.DATASTORE) {
        // Datastore-identity surrogate column
        JavaTypeMapping idMapping = sourceTbl.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
        int[] colNumbers = stmt.select(sourceSqlTbl, idMapping, null);
        if (mappingDefinition != null) {
            StatementMappingIndex datastoreIdIdx = new StatementMappingIndex(idMapping);
            datastoreIdIdx.setColumnPositions(colNumbers);
            mappingDefinition.addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), datastoreIdIdx);
        }
    }
    JavaTypeMapping verMapping = sourceTbl.getSurrogateMapping(SurrogateColumnType.VERSION, true);
    if (verMapping != null) {
        // Version surrogate column (adds inner join to any required superclass table)
        SQLTable versionSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, sourceSqlTbl, verMapping);
        int[] colNumbers = stmt.select(versionSqlTbl, verMapping, null);
        if (mappingDefinition != null) {
            StatementMappingIndex versionIdx = new StatementMappingIndex(verMapping);
            versionIdx.setColumnPositions(colNumbers);
            mappingDefinition.addMappingForMember(SurrogateColumnType.VERSION.getFieldNumber(), versionIdx);
        }
    }
    JavaTypeMapping discrimMapping = sourceTbl.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, true);
    if (discrimMapping != null) {
        // Discriminator surrogate column (adds inner join to any required superclass table)
        SQLTable discrimSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, sourceSqlTbl, discrimMapping);
        int[] colNumbers = stmt.select(discrimSqlTbl, discrimMapping, null);
        if (mappingDefinition != null) {
            StatementMappingIndex discrimIdx = new StatementMappingIndex(discrimMapping);
            discrimIdx.setColumnPositions(colNumbers);
            mappingDefinition.addMappingForMember(SurrogateColumnType.DISCRIMINATOR.getFieldNumber(), discrimIdx);
        }
    }
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) SecondaryDatastoreClass(org.datanucleus.store.rdbms.table.SecondaryDatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 65 with DatastoreClass

use of org.datanucleus.store.rdbms.table.DatastoreClass in project datanucleus-rdbms by datanucleus.

the class DeleteRequest method updateOneToOneBidirectionalOwnerObjectForField.

/**
 * Method to update any 1-1 bidir non-owner fields where the foreign-key is stored in the other object.
 * @param op ObjectProvider of this object
 * @param mmd MetaData for field that has related (owner) objects
 */
private void updateOneToOneBidirectionalOwnerObjectForField(ObjectProvider op, AbstractMemberMetaData fmd) {
    if (softDeleteStmt != null) {
        // If we are soft deleting the owner then no need to null the linkage BUT we need to check the soft delete status on retrieval of the owner from related
        return;
    }
    if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
        NucleusLogger.PERSISTENCE.debug(Localiser.msg("052217", op.getObjectAsPrintable(), fmd.getFullFieldName()));
    }
    RDBMSStoreManager storeMgr = table.getStoreManager();
    ExecutionContext ec = op.getExecutionContext();
    ClassLoaderResolver clr = ec.getClassLoaderResolver();
    AbstractMemberMetaData[] relatedMmds = fmd.getRelatedMemberMetaData(clr);
    // Check if we should null here, or leave to the datastore FK handler
    boolean checkFK = true;
    if (ec.getStringProperty(PropertyNames.PROPERTY_DELETION_POLICY).equals("JDO2")) {
        // JDO2 doesn't currently (2.0 spec) take note of foreign-key
        checkFK = false;
    }
    if (checkFK) {
        for (int i = 0; i < relatedMmds.length; i++) {
            ForeignKeyMetaData relFkmd = relatedMmds[i].getForeignKeyMetaData();
            if (relFkmd != null && relFkmd.getDeleteAction() != null) {
                // Field has a FK with a delete-action so leave to the datastore to process the delete
                return;
            }
        }
    }
    // TODO Cater for more than 1 related field
    String fullClassName = ((AbstractClassMetaData) relatedMmds[0].getParent()).getFullClassName();
    // TODO I'm not sure that we need to loop all implementations. will we have the fk set to all tables, if many?
    String[] classes;
    if (((AbstractClassMetaData) relatedMmds[0].getParent()) instanceof InterfaceMetaData) {
        classes = storeMgr.getNucleusContext().getMetaDataManager().getClassesImplementingInterface(fullClassName, clr);
    } else {
        classes = new String[] { fullClassName };
    }
    Set<DatastoreClass> datastoreClasses = new HashSet();
    for (int i = 0; i < classes.length; i++) {
        // just remove duplicates
        datastoreClasses.add(storeMgr.getDatastoreClass(classes[i], clr));
    }
    Iterator<DatastoreClass> it = datastoreClasses.iterator();
    while (it.hasNext()) {
        DatastoreClass refTable = it.next();
        JavaTypeMapping refMapping = refTable.getMemberMapping(fmd.getMappedBy());
        if (// Only clear the references that can be cleared
        refMapping.isNullable()) {
            // Create a statement to clear the link from the previous related object
            StringBuilder clearLinkStmt = new StringBuilder("UPDATE " + refTable.toString() + " SET ");
            for (int j = 0; j < refMapping.getNumberOfDatastoreMappings(); j++) {
                if (j > 0) {
                    clearLinkStmt.append(",");
                }
                clearLinkStmt.append(refMapping.getDatastoreMapping(j).getColumn().getIdentifier());
                clearLinkStmt.append("=NULL");
            }
            clearLinkStmt.append(" WHERE ");
            for (int j = 0; j < refMapping.getNumberOfDatastoreMappings(); j++) {
                if (j > 0) {
                    clearLinkStmt.append(" AND ");
                }
                clearLinkStmt.append(refMapping.getDatastoreMapping(j).getColumn().getIdentifier());
                clearLinkStmt.append("=?");
            }
            try {
                ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
                SQLController sqlControl = storeMgr.getSQLController();
                try {
                    // Null out the relationship to the object being deleted.
                    PreparedStatement ps = null;
                    try {
                        ps = sqlControl.getStatementForUpdate(mconn, clearLinkStmt.toString(), false);
                        refMapping.setObject(ec, ps, MappingHelper.getMappingIndices(1, refMapping), op.getObject());
                        sqlControl.executeStatementUpdate(ec, mconn, clearLinkStmt.toString(), ps, true);
                    } finally {
                        if (ps != null) {
                            sqlControl.closeStatement(mconn, ps);
                        }
                    }
                } finally {
                    mconn.release();
                }
            } catch (Exception e) {
                throw new NucleusDataStoreException("Update request failed", e);
            }
        }
    }
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) PreparedStatement(java.sql.PreparedStatement) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) SQLException(java.sql.SQLException) NucleusException(org.datanucleus.exceptions.NucleusException) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) NucleusOptimisticException(org.datanucleus.exceptions.NucleusOptimisticException) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) SQLController(org.datanucleus.store.rdbms.SQLController) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ExecutionContext(org.datanucleus.ExecutionContext) ForeignKeyMetaData(org.datanucleus.metadata.ForeignKeyMetaData) InterfaceMetaData(org.datanucleus.metadata.InterfaceMetaData) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) HashSet(java.util.HashSet)

Aggregations

DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)87 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)60 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)49 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)48 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)44 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)41 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)35 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)32 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)28 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)26 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)21 MapTable (org.datanucleus.store.rdbms.table.MapTable)19 NucleusException (org.datanucleus.exceptions.NucleusException)18 SecondaryDatastoreClass (org.datanucleus.store.rdbms.table.SecondaryDatastoreClass)15 ArrayList (java.util.ArrayList)14 ExecutionContext (org.datanucleus.ExecutionContext)13 JoinTable (org.datanucleus.store.rdbms.table.JoinTable)13 Table (org.datanucleus.store.rdbms.table.Table)13 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)11 UnboundExpression (org.datanucleus.store.rdbms.sql.expression.UnboundExpression)11