Search in sources :

Example 21 with ReferenceMapping

use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.

the class MapTable method initialize.

/**
 * Method to initialise the table definition.
 * @param clr The ClassLoaderResolver
 */
@Override
public void initialize(ClassLoaderResolver clr) {
    assertIsUninitialized();
    MapMetaData mapmd = mmd.getMap();
    if (mapmd == null) {
        throw new NucleusUserException(Localiser.msg("057017", mmd));
    }
    PrimaryKeyMetaData pkmd = (mmd.getJoinMetaData() != null ? mmd.getJoinMetaData().getPrimaryKeyMetaData() : null);
    boolean pkColsSpecified = (pkmd != null && pkmd.getColumnMetaData() != null);
    boolean pkRequired = requiresPrimaryKey();
    // Add owner mapping
    ColumnMetaData[] ownerColmd = null;
    if (mmd.getJoinMetaData() != null && mmd.getJoinMetaData().getColumnMetaData() != null && mmd.getJoinMetaData().getColumnMetaData().length > 0) {
        // Column mappings defined at this side (1-N, M-N)
        // When specified at this side they use the <join> tag
        ownerColmd = mmd.getJoinMetaData().getColumnMetaData();
    }
    ownerMapping = ColumnCreator.createColumnsForJoinTables(clr.classForName(ownerType), mmd, ownerColmd, storeMgr, this, pkRequired, false, FieldRole.ROLE_OWNER, clr, null);
    if (NucleusLogger.DATASTORE.isDebugEnabled()) {
        logMapping(mmd.getFullFieldName() + ".[OWNER]", ownerMapping);
    }
    String keyValueFieldName = (mmd.getKeyMetaData() != null ? mmd.getKeyMetaData().getMappedBy() : null);
    String valueKeyFieldName = (mmd.getValueMetaData() != null ? mmd.getValueMetaData().getMappedBy() : null);
    // Add key mapping
    boolean keyPC = (mmd.hasMap() && mmd.getMap().keyIsPersistent());
    Class keyCls = clr.classForName(mapmd.getKeyType());
    if (keyValueFieldName != null && isEmbeddedValuePC()) {
    // Added in value code
    } else if (isSerialisedKey() || isEmbeddedKeyPC() || (isEmbeddedKey() && !keyPC) || ClassUtils.isReferenceType(keyCls)) {
        // Key = PC(embedded), PC(serialised), Non-PC(serialised), Non-PC(embedded), Reference
        keyMapping = storeMgr.getMappingManager().getMapping(this, mmd, clr, FieldRole.ROLE_MAP_KEY);
        if (Boolean.TRUE.equals(mmd.getContainer().allowNulls())) {
            // Make all key col(s) nullable so we can store null elements
            for (int i = 0; i < keyMapping.getNumberOfColumnMappings(); i++) {
                Column elementCol = keyMapping.getColumnMapping(i).getColumn();
                elementCol.setNullable(true);
            }
        }
        if (NucleusLogger.DATASTORE.isDebugEnabled()) {
            logMapping(mmd.getFullFieldName() + ".[KEY]", keyMapping);
        }
        if (valueKeyFieldName != null && isEmbeddedKeyPC()) {
            // Key (PC) is embedded and value is a field of the key
            EmbeddedKeyPCMapping embMapping = (EmbeddedKeyPCMapping) keyMapping;
            valueMapping = embMapping.getJavaTypeMapping(valueKeyFieldName);
        }
    } else {
        // Key = PC
        ColumnMetaData[] keyColmd = null;
        KeyMetaData keymd = mmd.getKeyMetaData();
        if (keymd != null && keymd.getColumnMetaData() != null && keymd.getColumnMetaData().length > 0) {
            // Column mappings defined at this side (1-N, M-N)
            keyColmd = keymd.getColumnMetaData();
        }
        keyMapping = ColumnCreator.createColumnsForJoinTables(keyCls, mmd, keyColmd, storeMgr, this, false, false, FieldRole.ROLE_MAP_KEY, clr, null);
        if (mmd.getContainer().allowNulls() == Boolean.TRUE) {
            // Make all key col(s) nullable so we can store null elements
            for (int i = 0; i < keyMapping.getNumberOfColumnMappings(); i++) {
                Column elementCol = keyMapping.getColumnMapping(i).getColumn();
                elementCol.setNullable(true);
            }
        }
        if (NucleusLogger.DATASTORE.isDebugEnabled()) {
            logMapping(mmd.getFullFieldName() + ".[KEY]", keyMapping);
        }
    }
    // Add value mapping
    boolean valuePC = (mmd.hasMap() && mmd.getMap().valueIsPersistent());
    Class valueCls = clr.classForName(mapmd.getValueType());
    if (valueKeyFieldName != null && isEmbeddedKeyPC()) {
    // Added in key code
    } else if (isSerialisedValue() || isEmbeddedValuePC() || (isEmbeddedValue() && !valuePC) || ClassUtils.isReferenceType(valueCls)) {
        // Value = PC(embedded), PC(serialised), Non-PC(serialised), Non-PC(embedded), Reference
        valueMapping = storeMgr.getMappingManager().getMapping(this, mmd, clr, FieldRole.ROLE_MAP_VALUE);
        if (mmd.getContainer().allowNulls() == Boolean.TRUE) {
            // Make all value col(s) nullable so we can store null elements
            for (int i = 0; i < valueMapping.getNumberOfColumnMappings(); i++) {
                Column elementCol = valueMapping.getColumnMapping(i).getColumn();
                elementCol.setNullable(true);
            }
        }
        if (NucleusLogger.DATASTORE.isDebugEnabled()) {
            logMapping(mmd.getFullFieldName() + ".[VALUE]", valueMapping);
        }
        if (keyValueFieldName != null && isEmbeddedValuePC()) {
            // Value (PC) is embedded and key is a field of the value
            EmbeddedValuePCMapping embMapping = (EmbeddedValuePCMapping) valueMapping;
            keyMapping = embMapping.getJavaTypeMapping(keyValueFieldName);
        }
    } else {
        // Value = PC
        ColumnMetaData[] valueColmd = null;
        ValueMetaData valuemd = mmd.getValueMetaData();
        if (valuemd != null && valuemd.getColumnMetaData() != null && valuemd.getColumnMetaData().length > 0) {
            // Column mappings defined at this side (1-N, M-N)
            valueColmd = valuemd.getColumnMetaData();
        }
        valueMapping = ColumnCreator.createColumnsForJoinTables(clr.classForName(mapmd.getValueType()), mmd, valueColmd, storeMgr, this, false, true, FieldRole.ROLE_MAP_VALUE, clr, null);
        if (mmd.getContainer().allowNulls() == Boolean.TRUE) {
            // Make all value col(s) nullable so we can store null elements
            for (int i = 0; i < valueMapping.getNumberOfColumnMappings(); i++) {
                Column elementCol = valueMapping.getColumnMapping(i).getColumn();
                elementCol.setNullable(true);
            }
        }
        if (NucleusLogger.DATASTORE.isDebugEnabled()) {
            logMapping(mmd.getFullFieldName() + ".[VALUE]", valueMapping);
        }
    }
    // Add order mapping if required
    boolean orderRequired = false;
    if (mmd.getOrderMetaData() != null) {
        // User requested order column so add one
        orderRequired = true;
    } else if (requiresPrimaryKey() && !pkColsSpecified) {
        // PK is required so maybe need to add an index to form the PK
        if (isEmbeddedKeyPC()) {
            if (mmd.hasExtension("surrogate-pk-column") && mmd.getValueForExtension("surrogate-pk-column").equalsIgnoreCase("true")) {
                // Allow user to request surrogate pk column be added (for use with JPA)
                orderRequired = true;
            } else if (storeMgr.getApiAdapter().getName().equalsIgnoreCase("JDO") && mmd.getMap().getKeyClassMetaData(clr).getIdentityType() != IdentityType.APPLICATION) {
                // Embedded key PC with datastore id so we need an index to form the PK TODO It is arguable that we can just use all embedded key fields as part of PK here always
                orderRequired = true;
            }
        } else if (isSerialisedKey()) {
            // Serialised key, so need an index to form the PK
            orderRequired = true;
        } else if (keyMapping instanceof ReferenceMapping) {
            // ReferenceMapping, so have order if more than 1 implementation
            ReferenceMapping refMapping = (ReferenceMapping) keyMapping;
            if (refMapping.getJavaTypeMapping().length > 1) {
                orderRequired = true;
            }
        } else if (!(keyMapping instanceof PersistableMapping)) {
            // Non-PC, so depends if the key column can be used as part of a PK
            // TODO This assumes the keyMapping has a single column but what if it is Color with 4 cols?
            Column elementCol = keyMapping.getColumnMapping(0).getColumn();
            if (!storeMgr.getDatastoreAdapter().isValidPrimaryKeyType(elementCol.getJdbcType())) {
                // Not possible to use this Non-PC type as part of the PK
                orderRequired = true;
            }
        }
    }
    if (orderRequired) {
        // Order/Adapter (index) column is required (integer based)
        ColumnMetaData orderColmd = null;
        if (mmd.getOrderMetaData() != null && mmd.getOrderMetaData().getColumnMetaData() != null && mmd.getOrderMetaData().getColumnMetaData().length > 0) {
            // Specified "order" column info
            orderColmd = mmd.getOrderMetaData().getColumnMetaData()[0];
            if (orderColmd.getName() == null) {
                // No column name so use default
                orderColmd = new ColumnMetaData(orderColmd);
                DatastoreIdentifier id = storeMgr.getIdentifierFactory().newIndexFieldIdentifier(mmd);
                orderColmd.setName(id.getName());
            }
        } else {
            // No column name so use default
            DatastoreIdentifier id = storeMgr.getIdentifierFactory().newIndexFieldIdentifier(mmd);
            orderColmd = new ColumnMetaData();
            orderColmd.setName(id.getName());
        }
        // JDO2 spec [18.5] order column is assumed to be "int"
        orderMapping = storeMgr.getMappingManager().getMapping(int.class);
        ColumnCreator.createIndexColumn(orderMapping, storeMgr, clr, this, orderColmd, pkRequired && !pkColsSpecified);
        if (NucleusLogger.DATASTORE.isDebugEnabled()) {
            logMapping(mmd.getFullFieldName() + ".[ORDER]", orderMapping);
        }
    }
    // Define primary key of the join table (if any)
    if (pkRequired) {
        if (pkColsSpecified) {
            // Apply the users PK specification
            applyUserPrimaryKeySpecification(pkmd);
        } else {
            // Define PK using internal rules
            if (orderRequired) {
                // Order column specified so owner+order are the PK
                orderMapping.getColumnMapping(0).getColumn().setPrimaryKey();
            } else {
                // No order column specified so owner+key are the PK
                for (int i = 0; i < keyMapping.getNumberOfColumnMappings(); i++) {
                    keyMapping.getColumnMapping(i).getColumn().setPrimaryKey();
                }
            }
        }
    }
    if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled()) {
        NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("057023", this));
    }
    storeMgr.registerTableInitialized(this);
    state = TABLE_STATE_INITIALIZED;
}
Also used : KeyMetaData(org.datanucleus.metadata.KeyMetaData) PrimaryKeyMetaData(org.datanucleus.metadata.PrimaryKeyMetaData) ForeignKeyMetaData(org.datanucleus.metadata.ForeignKeyMetaData) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) EmbeddedValuePCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedValuePCMapping) MapMetaData(org.datanucleus.metadata.MapMetaData) PrimaryKeyMetaData(org.datanucleus.metadata.PrimaryKeyMetaData) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) DatastoreIdentifier(org.datanucleus.store.rdbms.identifier.DatastoreIdentifier) ValueMetaData(org.datanucleus.metadata.ValueMetaData) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) EmbeddedKeyPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedKeyPCMapping)

Example 22 with ReferenceMapping

use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.

the class ElementContainerTable method getExpectedForeignKeys.

/**
 * Accessor for the expected foreign keys for this table.
 * @param clr The ClassLoaderResolver
 * @return The expected foreign keys.
 */
@Override
public List<ForeignKey> getExpectedForeignKeys(ClassLoaderResolver clr) {
    assertIsInitialized();
    // Find the mode that we're operating in for FK addition
    boolean autoMode = false;
    if (storeMgr.getStringProperty(RDBMSPropertyNames.PROPERTY_RDBMS_CONSTRAINT_CREATE_MODE).equals("DataNucleus")) {
        autoMode = true;
    }
    List<ForeignKey> foreignKeys = new ArrayList();
    try {
        // FK from join table to owner table
        DatastoreClass referencedTable = storeMgr.getDatastoreClass(ownerType, clr);
        if (referencedTable != null) {
            // Single owner table, so add a single FK to the owner as appropriate
            ForeignKey fk = getForeignKeyToOwner(referencedTable, autoMode);
            if (fk != null) {
                foreignKeys.add(fk);
            }
        } else {
        // No single owner so we don't bother with the FK since referential integrity by FK cannot work
        // if we don't have a single owner at the other end of the FK(s).
        }
        // FK from join table to element table(s)
        if (elementMapping instanceof SerialisedPCMapping) {
        // Do nothing since no element table
        } else if (elementMapping instanceof EmbeddedElementPCMapping) {
            // Add any FKs for the fields of the (embedded) element
            EmbeddedElementPCMapping embMapping = (EmbeddedElementPCMapping) elementMapping;
            for (int i = 0; i < embMapping.getNumberOfJavaTypeMappings(); i++) {
                JavaTypeMapping embFieldMapping = embMapping.getJavaTypeMapping(i);
                AbstractMemberMetaData embFmd = embFieldMapping.getMemberMetaData();
                if (ClassUtils.isReferenceType(embFmd.getType()) && embFieldMapping instanceof ReferenceMapping) {
                    // Field is a reference type, so add a FK to the table of the PC for each PC implementation
                    Collection fks = TableUtils.getForeignKeysForReferenceField(embFieldMapping, embFmd, autoMode, storeMgr, clr);
                    foreignKeys.addAll(fks);
                } else if (storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(embFmd.getType(), clr) != null && embFieldMapping.getNumberOfColumnMappings() > 0 && embFieldMapping instanceof PersistableMapping) {
                    // Field is for a PC class with the FK at this side, so add a FK to the table of this PC
                    ForeignKey fk = TableUtils.getForeignKeyForPCField(embFieldMapping, embFmd, autoMode, storeMgr, clr);
                    if (fk != null) {
                        foreignKeys.add(fk);
                    }
                }
            }
        } else if (elementMapping instanceof ReferenceMapping) {
            JavaTypeMapping[] implJavaTypeMappings = ((ReferenceMapping) elementMapping).getJavaTypeMapping();
            for (int i = 0; i < implJavaTypeMappings.length; i++) {
                JavaTypeMapping implMapping = implJavaTypeMappings[i];
                if (storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(implMapping.getType(), clr) != null && implMapping.getNumberOfColumnMappings() > 0) {
                    referencedTable = storeMgr.getDatastoreClass(implMapping.getType(), clr);
                    if (referencedTable != null) {
                        ForeignKey fk = getForeignKeyToElement(referencedTable, autoMode, implMapping);
                        if (fk != null) {
                            foreignKeys.add(fk);
                        }
                    }
                }
            }
        } else {
            referencedTable = storeMgr.getDatastoreClass(getElementType(), clr);
            if (referencedTable != null) {
                ForeignKey fk = getForeignKeyToElement(referencedTable, autoMode, elementMapping);
                if (fk != null) {
                    foreignKeys.add(fk);
                }
            } else {
            // Either no element table or multiple (where the user has element with "subclass-table" strategy, or using "complete-table")
            // so do nothing since referential integrity will not allow multiple FKs.
            }
        }
    } catch (NoTableManagedException e) {
    // expected when no table exists
    }
    return foreignKeys;
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ArrayList(java.util.ArrayList) ForeignKey(org.datanucleus.store.rdbms.key.ForeignKey) EmbeddedElementPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedElementPCMapping) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) Collection(java.util.Collection) SerialisedPCMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedPCMapping) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) NoTableManagedException(org.datanucleus.store.rdbms.exceptions.NoTableManagedException)

Example 23 with ReferenceMapping

use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.

the class JoinArrayStore method iterator.

/**
 * Method to return an iterator to the array.
 * @param ownerOP ObjectProvider for the owner of the array
 */
public Iterator<E> iterator(ObjectProvider ownerOP) {
    ExecutionContext ec = ownerOP.getExecutionContext();
    // Generate the statement, and statement mapping/parameter information
    IteratorStatement iterStmt = getIteratorStatement(ec, ec.getFetchPlan(), true);
    SelectStatement sqlStmt = iterStmt.sqlStmt;
    StatementClassMapping iteratorMappingClass = iterStmt.stmtClassMapping;
    // Input parameter(s) - the owner
    int inputParamNum = 1;
    StatementMappingIndex ownerIdx = new StatementMappingIndex(ownerMapping);
    if (sqlStmt.getNumberOfUnions() > 0) {
        // Add parameter occurrence for each union of statement
        for (int j = 0; j < sqlStmt.getNumberOfUnions() + 1; j++) {
            int[] paramPositions = new int[ownerMapping.getNumberOfDatastoreMappings()];
            for (int k = 0; k < paramPositions.length; k++) {
                paramPositions[k] = inputParamNum++;
            }
            ownerIdx.addParameterOccurrence(paramPositions);
        }
    } else {
        int[] paramPositions = new int[ownerMapping.getNumberOfDatastoreMappings()];
        for (int k = 0; k < paramPositions.length; k++) {
            paramPositions[k] = inputParamNum++;
        }
        ownerIdx.addParameterOccurrence(paramPositions);
    }
    StatementParameterMapping iteratorMappingParams = new StatementParameterMapping();
    iteratorMappingParams.addMappingForParameter("owner", ownerIdx);
    if (ec.getTransaction().getSerializeRead() != null && ec.getTransaction().getSerializeRead()) {
        sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
    }
    String stmt = sqlStmt.getSQLText().toSQL();
    try {
        ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
        SQLController sqlControl = storeMgr.getSQLController();
        try {
            // Create the statement
            PreparedStatement ps = sqlControl.getStatementForQuery(mconn, stmt);
            // Set the owner
            ObjectProvider stmtOwnerOP = BackingStoreHelper.getOwnerObjectProviderForBackingStore(ownerOP);
            int numParams = ownerIdx.getNumberOfParameterOccurrences();
            for (int paramInstance = 0; paramInstance < numParams; paramInstance++) {
                ownerIdx.getMapping().setObject(ec, ps, ownerIdx.getParameterPositionsForOccurrence(paramInstance), stmtOwnerOP.getObject());
            }
            try {
                ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, stmt, ps);
                try {
                    if (elementsAreEmbedded || elementsAreSerialised) {
                        // No ResultObjectFactory needed - handled by SetStoreIterator
                        return new ArrayStoreIterator(ownerOP, rs, null, this);
                    } else if (elementMapping instanceof ReferenceMapping) {
                        // No ResultObjectFactory needed - handled by SetStoreIterator
                        return new ArrayStoreIterator(ownerOP, rs, null, this);
                    } else {
                        ResultObjectFactory rof = new PersistentClassROF(ec, rs, false, iteratorMappingClass, elementCmd, clr.classForName(elementType));
                        return new ArrayStoreIterator(ownerOP, rs, rof, this);
                    }
                } finally {
                    rs.close();
                }
            } finally {
                sqlControl.closeStatement(mconn, ps);
            }
        } finally {
            mconn.release();
        }
    } catch (SQLException | MappedDatastoreException e) {
        throw new NucleusDataStoreException(Localiser.msg("056006", stmt), e);
    }
}
Also used : StatementParameterMapping(org.datanucleus.store.rdbms.query.StatementParameterMapping) MappedDatastoreException(org.datanucleus.store.rdbms.exceptions.MappedDatastoreException) SQLException(java.sql.SQLException) ResultObjectFactory(org.datanucleus.store.rdbms.query.ResultObjectFactory) PreparedStatement(java.sql.PreparedStatement) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) SQLController(org.datanucleus.store.rdbms.SQLController) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ExecutionContext(org.datanucleus.ExecutionContext) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) PersistentClassROF(org.datanucleus.store.rdbms.query.PersistentClassROF) ResultSet(java.sql.ResultSet) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) ObjectProvider(org.datanucleus.state.ObjectProvider)

Example 24 with ReferenceMapping

use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.

the class JoinSetStore method iterator.

/**
 * Accessor for an iterator for the set.
 * @param ownerOP ObjectProvider for the set.
 * @return Iterator for the set.
 */
public Iterator<E> iterator(ObjectProvider ownerOP) {
    ExecutionContext ec = ownerOP.getExecutionContext();
    // Generate the statement, and statement mapping/parameter information
    IteratorStatement iterStmt = getIteratorStatement(ec, ec.getFetchPlan(), true);
    SelectStatement sqlStmt = iterStmt.sqlStmt;
    StatementClassMapping iteratorMappingClass = iterStmt.stmtClassMapping;
    // Input parameter(s) - the owner
    int inputParamNum = 1;
    StatementMappingIndex ownerStmtMapIdx = new StatementMappingIndex(ownerMapping);
    if (sqlStmt.getNumberOfUnions() > 0) {
        // Add parameter occurrence for each union of statement
        for (int j = 0; j < sqlStmt.getNumberOfUnions() + 1; j++) {
            int[] paramPositions = new int[ownerMapping.getNumberOfDatastoreMappings()];
            for (int k = 0; k < paramPositions.length; k++) {
                paramPositions[k] = inputParamNum++;
            }
            ownerStmtMapIdx.addParameterOccurrence(paramPositions);
        }
    } else {
        int[] paramPositions = new int[ownerMapping.getNumberOfDatastoreMappings()];
        for (int k = 0; k < paramPositions.length; k++) {
            paramPositions[k] = inputParamNum++;
        }
        ownerStmtMapIdx.addParameterOccurrence(paramPositions);
    }
    if (ec.getTransaction().getSerializeRead() != null && ec.getTransaction().getSerializeRead()) {
        sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
    }
    String stmt = sqlStmt.getSQLText().toSQL();
    try {
        ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
        SQLController sqlControl = storeMgr.getSQLController();
        try {
            // Create the statement
            PreparedStatement ps = sqlControl.getStatementForQuery(mconn, stmt);
            // Set the owner
            ObjectProvider stmtOwnerOP = BackingStoreHelper.getOwnerObjectProviderForBackingStore(ownerOP);
            int numParams = ownerStmtMapIdx.getNumberOfParameterOccurrences();
            for (int paramInstance = 0; paramInstance < numParams; paramInstance++) {
                ownerStmtMapIdx.getMapping().setObject(ec, ps, ownerStmtMapIdx.getParameterPositionsForOccurrence(paramInstance), stmtOwnerOP.getObject());
            }
            try {
                ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, stmt, ps);
                try {
                    if (elementsAreEmbedded || elementsAreSerialised) {
                        // No ResultObjectFactory needed - handled by SetStoreIterator
                        return new CollectionStoreIterator(ownerOP, rs, null, this);
                    } else if (elementMapping instanceof ReferenceMapping) {
                        // No ResultObjectFactory needed - handled by SetStoreIterator
                        return new CollectionStoreIterator(ownerOP, rs, null, this);
                    } else {
                        ResultObjectFactory rof = new PersistentClassROF(ec, rs, false, iteratorMappingClass, elementCmd, clr.classForName(elementType));
                        return new CollectionStoreIterator(ownerOP, rs, rof, this);
                    }
                } finally {
                    rs.close();
                }
            } finally {
                sqlControl.closeStatement(mconn, ps);
            }
        } finally {
            mconn.release();
        }
    } catch (SQLException | MappedDatastoreException e) {
        throw new NucleusDataStoreException(Localiser.msg("056006", stmt), e);
    }
}
Also used : MappedDatastoreException(org.datanucleus.store.rdbms.exceptions.MappedDatastoreException) SQLException(java.sql.SQLException) ResultObjectFactory(org.datanucleus.store.rdbms.query.ResultObjectFactory) PreparedStatement(java.sql.PreparedStatement) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) SQLController(org.datanucleus.store.rdbms.SQLController) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ExecutionContext(org.datanucleus.ExecutionContext) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) PersistentClassROF(org.datanucleus.store.rdbms.query.PersistentClassROF) ResultSet(java.sql.ResultSet) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) ObjectProvider(org.datanucleus.state.ObjectProvider)

Example 25 with ReferenceMapping

use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.

the class JoinArrayStore method getIteratorStatement.

/**
 * Method to return the SQLStatement and mapping for an iterator for this backing store.
 * Create a statement of the form
 * <pre>
 * SELECT ELEM_COLS
 * FROM JOIN_TBL
 *   [JOIN ELEM_TBL ON ELEM_TBL.ID = JOIN_TBL.ELEM_ID]
 * [WHERE]
 *   [JOIN_TBL.OWNER_ID = {value}] [AND]
 *   [JOIN_TBL.DISCRIM = {discrimValue}]
 * [ORDER BY {orderClause}]
 * </pre>
 * @param ec ExecutionContext
 * @param fp FetchPlan to use in determing which fields of element to select
 * @param addRestrictionOnOwner Whether to restrict to a particular owner (otherwise functions as bulk fetch for many owners).
 * @return The SQLStatement and its associated StatementClassMapping
 */
public ElementIteratorStatement getIteratorStatement(ExecutionContext ec, FetchPlan fp, boolean addRestrictionOnOwner) {
    SelectStatement sqlStmt = null;
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    StatementClassMapping elementClsMapping = null;
    if (elementsAreEmbedded || elementsAreSerialised) {
        // Element = embedded, serialised (maybe Non-PC)
        // Just select the join table since we're going to return the embedded/serialised columns from it
        sqlStmt = new SelectStatement(storeMgr, containerTable, null, null);
        sqlStmt.setClassLoaderResolver(clr);
        // Select the element column - first select is assumed by SetStoreIterator
        sqlStmt.select(sqlStmt.getPrimaryTable(), elementMapping, null);
    // TODO If embedded element and it includes 1-1/N-1 in FetchPlan then select its fields also
    } else if (elementMapping instanceof ReferenceMapping) {
        // Element = Reference type (interface/Object)
        // Just select the join table since we're going to return the implementation id columns only
        sqlStmt = new SelectStatement(storeMgr, containerTable, null, null);
        sqlStmt.setClassLoaderResolver(clr);
        // Select the reference column(s) - first select is assumed by SetStoreIterator
        sqlStmt.select(sqlStmt.getPrimaryTable(), elementMapping, null);
    } else {
        // Element = PC
        // Join to the element table(s)
        elementClsMapping = new StatementClassMapping();
        for (int i = 0; i < elementInfo.length; i++) {
            // TODO This will only work if all element types have a discriminator
            final int elementNo = i;
            final Class elementCls = clr.classForName(elementInfo[elementNo].getClassName());
            SelectStatement elementStmt = null;
            if (elementInfo[elementNo].getDiscriminatorStrategy() != null && elementInfo[elementNo].getDiscriminatorStrategy() != DiscriminatorStrategy.NONE) {
                // The element uses a discriminator so just use that in the SELECT
                String elementType = ownerMemberMetaData.getCollection().getElementType();
                if (ClassUtils.isReferenceType(clr.classForName(elementType))) {
                    String[] clsNames = storeMgr.getNucleusContext().getMetaDataManager().getClassesImplementingInterface(elementType, clr);
                    Class[] cls = new Class[clsNames.length];
                    for (int j = 0; j < clsNames.length; j++) {
                        cls[j] = clr.classForName(clsNames[j]);
                    }
                    SelectStatementGenerator stmtGen = new DiscriminatorStatementGenerator(storeMgr, clr, cls, true, null, null, containerTable, null, elementMapping);
                    if (allowNulls) {
                        stmtGen.setOption(SelectStatementGenerator.OPTION_ALLOW_NULLS);
                    }
                    elementStmt = stmtGen.getStatement(ec);
                } else {
                    SelectStatementGenerator stmtGen = new DiscriminatorStatementGenerator(storeMgr, clr, elementCls, true, null, null, containerTable, null, elementMapping);
                    if (allowNulls) {
                        stmtGen.setOption(SelectStatementGenerator.OPTION_ALLOW_NULLS);
                    }
                    elementStmt = stmtGen.getStatement(ec);
                }
                iterateUsingDiscriminator = true;
            } else {
                // No discriminator, but subclasses so use UNIONs
                SelectStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, elementCls, true, null, null, containerTable, null, elementMapping);
                stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
                if (allowNulls) {
                    stmtGen.setOption(SelectStatementGenerator.OPTION_ALLOW_NULLS);
                }
                elementClsMapping.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
                elementStmt = stmtGen.getStatement(ec);
            }
            if (sqlStmt == null) {
                sqlStmt = elementStmt;
            } else {
                sqlStmt.union(elementStmt);
            }
        }
        if (sqlStmt == null) {
            throw new NucleusException("Error in generation of SQL statement for iterator over (Join) array. Statement is null");
        }
        // Select the required fields
        SQLTable elementSqlTbl = sqlStmt.getTable(elementInfo[0].getDatastoreClass(), sqlStmt.getPrimaryTable().getGroupName());
        SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, elementClsMapping, fp, elementSqlTbl, elementCmd, fp.getMaxFetchDepth());
    }
    if (addRestrictionOnOwner) {
        // Apply condition on join-table owner field to filter by owner
        SQLTable ownerSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), ownerMapping);
        SQLExpression ownerExpr = exprFactory.newExpression(sqlStmt, ownerSqlTbl, ownerMapping);
        SQLExpression ownerVal = exprFactory.newLiteralParameter(sqlStmt, ownerMapping, null, "OWNER");
        sqlStmt.whereAnd(ownerExpr.eq(ownerVal), true);
    }
    if (relationDiscriminatorMapping != null) {
        // Apply condition on distinguisher field to filter by distinguisher (when present)
        SQLTable distSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), relationDiscriminatorMapping);
        SQLExpression distExpr = exprFactory.newExpression(sqlStmt, distSqlTbl, relationDiscriminatorMapping);
        SQLExpression distVal = exprFactory.newLiteral(sqlStmt, relationDiscriminatorMapping, relationDiscriminatorValue);
        sqlStmt.whereAnd(distExpr.eq(distVal), true);
    }
    if (orderMapping != null) {
        // Order by the ordering column, when present
        SQLTable orderSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
        SQLExpression[] orderExprs = new SQLExpression[orderMapping.getNumberOfColumnMappings()];
        boolean[] descendingOrder = new boolean[orderMapping.getNumberOfColumnMappings()];
        orderExprs[0] = exprFactory.newExpression(sqlStmt, orderSqlTbl, orderMapping);
        sqlStmt.setOrdering(orderExprs, descendingOrder);
    }
    return new ElementIteratorStatement(this, sqlStmt, elementClsMapping);
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) UnionStatementGenerator(org.datanucleus.store.rdbms.sql.UnionStatementGenerator) SelectStatementGenerator(org.datanucleus.store.rdbms.sql.SelectStatementGenerator) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) DiscriminatorStatementGenerator(org.datanucleus.store.rdbms.sql.DiscriminatorStatementGenerator) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException)

Aggregations

ReferenceMapping (org.datanucleus.store.rdbms.mapping.java.ReferenceMapping)38 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)23 PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)16 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)14 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)13 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)13 ExecutionContext (org.datanucleus.ExecutionContext)12 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)12 SQLException (java.sql.SQLException)11 PersistentClassROF (org.datanucleus.store.rdbms.query.PersistentClassROF)11 StatementClassMapping (org.datanucleus.store.rdbms.query.StatementClassMapping)11 PreparedStatement (java.sql.PreparedStatement)10 ResultSet (java.sql.ResultSet)10 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)10 ManagedConnection (org.datanucleus.store.connection.ManagedConnection)10 SQLController (org.datanucleus.store.rdbms.SQLController)10 ResultObjectFactory (org.datanucleus.store.rdbms.query.ResultObjectFactory)10 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)10 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)8 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)7