Search in sources :

Example 36 with JavaTypeMapping

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

the class InsertRequest method execute.

/**
 * Method performing the insertion of the record from the datastore.
 * Takes the constructed insert query and populates with the specific record information.
 * @param op The ObjectProvider for the record to be inserted
 */
public void execute(ObjectProvider op) {
    ExecutionContext ec = op.getExecutionContext();
    if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
        // Debug information about what we are inserting
        NucleusLogger.PERSISTENCE.debug(Localiser.msg("052207", op.getObjectAsPrintable(), table));
    }
    try {
        VersionMetaData vermd = table.getVersionMetaData();
        RDBMSStoreManager storeMgr = table.getStoreManager();
        if (vermd != null && vermd.getFieldName() != null) {
            // Version field - Update the version in the object
            AbstractMemberMetaData verfmd = ((AbstractClassMetaData) vermd.getParent()).getMetaDataForMember(vermd.getFieldName());
            Object currentVersion = op.getVersion();
            if (currentVersion instanceof Number) {
                // Cater for Integer based versions
                currentVersion = Long.valueOf(((Number) currentVersion).longValue());
            }
            Object nextOptimisticVersion = ec.getLockManager().getNextVersion(vermd, currentVersion);
            if (verfmd.getType() == Integer.class || verfmd.getType() == int.class) {
                // Cater for Integer based versions
                nextOptimisticVersion = Integer.valueOf(((Number) nextOptimisticVersion).intValue());
            }
            op.replaceField(verfmd.getAbsoluteFieldNumber(), nextOptimisticVersion);
        }
        // Set the state to "inserting" (may already be at this state if multiple inheritance level INSERT)
        op.changeActivityState(ActivityState.INSERTING);
        SQLController sqlControl = storeMgr.getSQLController();
        ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
        try {
            PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, insertStmt, batch, hasIdentityColumn && storeMgr.getDatastoreAdapter().supportsOption(DatastoreAdapter.GET_GENERATED_KEYS_STATEMENT));
            try {
                StatementClassMapping mappingDefinition = new StatementClassMapping();
                StatementMappingIndex[] idxs = stmtMappings;
                for (int i = 0; i < idxs.length; i++) {
                    if (idxs[i] != null) {
                        mappingDefinition.addMappingForMember(i, idxs[i]);
                    }
                }
                // Provide the primary key field(s)
                if (table.getIdentityType() == IdentityType.DATASTORE) {
                    if (!table.isObjectIdDatastoreAttributed() || !table.isBaseDatastoreClass()) {
                        int[] paramNumber = { IDPARAMNUMBER };
                        table.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false).setObject(ec, ps, paramNumber, op.getInternalObjectId());
                    }
                } else if (table.getIdentityType() == IdentityType.APPLICATION) {
                    op.provideFields(pkFieldNumbers, new ParameterSetter(op, ps, mappingDefinition));
                }
                // This provides "persistence-by-reachability" for these fields
                if (insertFieldNumbers.length > 0) {
                    // TODO Support surrogate current-user, create-timestamp
                    int numberOfFieldsToProvide = 0;
                    for (int i = 0; i < insertFieldNumbers.length; i++) {
                        if (insertFieldNumbers[i] < op.getClassMetaData().getMemberCount()) {
                            AbstractMemberMetaData mmd = op.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(insertFieldNumbers[i]);
                            if (mmd.isCreateTimestamp()) {
                                // Set create timestamp to time for the start of this transaction
                                op.replaceField(insertFieldNumbers[i], new Timestamp(ec.getTransaction().getIsActive() ? ec.getTransaction().getBeginTime() : System.currentTimeMillis()));
                            } else if (mmd.isCreateUser()) {
                                // Set create user to current user
                                op.replaceField(insertFieldNumbers[i], ec.getNucleusContext().getCurrentUser(ec));
                            }
                            numberOfFieldsToProvide++;
                        }
                    }
                    int j = 0;
                    int[] fieldNums = new int[numberOfFieldsToProvide];
                    for (int i = 0; i < insertFieldNumbers.length; i++) {
                        if (insertFieldNumbers[i] < op.getClassMetaData().getMemberCount()) {
                            fieldNums[j++] = insertFieldNumbers[i];
                        }
                    }
                    op.provideFields(fieldNums, new ParameterSetter(op, ps, mappingDefinition));
                }
                JavaTypeMapping versionMapping = table.getSurrogateMapping(SurrogateColumnType.VERSION, false);
                if (versionMapping != null) {
                    // Surrogate version - set the new version for the object
                    Object currentVersion = op.getVersion();
                    Object nextOptimisticVersion = ec.getLockManager().getNextVersion(vermd, currentVersion);
                    for (int k = 0; k < versionStmtMapping.getNumberOfParameterOccurrences(); k++) {
                        versionMapping.setObject(ec, ps, versionStmtMapping.getParameterPositionsForOccurrence(k), nextOptimisticVersion);
                    }
                    op.setTransactionalVersion(nextOptimisticVersion);
                } else if (vermd != null && vermd.getFieldName() != null) {
                    // Version field - set the new version for the object
                    Object currentVersion = op.getVersion();
                    Object nextOptimisticVersion = ec.getLockManager().getNextVersion(vermd, currentVersion);
                    op.setTransactionalVersion(nextOptimisticVersion);
                }
                if (multitenancyStmtMapping != null) {
                    // Multitenancy mapping
                    table.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false).setObject(ec, ps, multitenancyStmtMapping.getParameterPositionsForOccurrence(0), ec.getNucleusContext().getMultiTenancyId(ec, op.getClassMetaData()));
                }
                if (softDeleteStmtMapping != null) {
                    // Soft-Delete mapping
                    table.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false).setObject(ec, ps, softDeleteStmtMapping.getParameterPositionsForOccurrence(0), Boolean.FALSE);
                }
                JavaTypeMapping discrimMapping = table.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, false);
                if (discrimMapping != null) {
                    // Discriminator mapping
                    Object discVal = op.getClassMetaData().getDiscriminatorValue();
                    for (int k = 0; k < discriminatorStmtMapping.getNumberOfParameterOccurrences(); k++) {
                        discrimMapping.setObject(ec, ps, discriminatorStmtMapping.getParameterPositionsForOccurrence(k), discVal);
                    }
                }
                // External FK columns (optional)
                if (externalFKStmtMappings != null) {
                    for (int i = 0; i < externalFKStmtMappings.length; i++) {
                        Object fkValue = op.getAssociatedValue(externalFKStmtMappings[i].getMapping());
                        if (fkValue != null) {
                            // Need to provide the owner field number so PCMapping can work out if it is inserted yet
                            AbstractMemberMetaData ownerFmd = table.getMetaDataForExternalMapping(externalFKStmtMappings[i].getMapping(), MappingType.EXTERNAL_FK);
                            for (int k = 0; k < externalFKStmtMappings[i].getNumberOfParameterOccurrences(); k++) {
                                externalFKStmtMappings[i].getMapping().setObject(ec, ps, externalFKStmtMappings[i].getParameterPositionsForOccurrence(k), fkValue, null, ownerFmd.getAbsoluteFieldNumber());
                            }
                        } else {
                            // We're inserting a null so don't need the owner field
                            for (int k = 0; k < externalFKStmtMappings[i].getNumberOfParameterOccurrences(); k++) {
                                externalFKStmtMappings[i].getMapping().setObject(ec, ps, externalFKStmtMappings[i].getParameterPositionsForOccurrence(k), null);
                            }
                        }
                    }
                }
                // External FK discriminator columns (optional)
                if (externalFKDiscrimStmtMappings != null) {
                    for (int i = 0; i < externalFKDiscrimStmtMappings.length; i++) {
                        Object discrimValue = op.getAssociatedValue(externalFKDiscrimStmtMappings[i].getMapping());
                        for (int k = 0; k < externalFKDiscrimStmtMappings[i].getNumberOfParameterOccurrences(); k++) {
                            externalFKDiscrimStmtMappings[i].getMapping().setObject(ec, ps, externalFKDiscrimStmtMappings[i].getParameterPositionsForOccurrence(k), discrimValue);
                        }
                    }
                }
                // External order columns (optional)
                if (externalOrderStmtMappings != null) {
                    for (int i = 0; i < externalOrderStmtMappings.length; i++) {
                        Object orderValue = op.getAssociatedValue(externalOrderStmtMappings[i].getMapping());
                        if (orderValue == null) {
                            // No order value so use -1
                            orderValue = Integer.valueOf(-1);
                        }
                        for (int k = 0; k < externalOrderStmtMappings[i].getNumberOfParameterOccurrences(); k++) {
                            externalOrderStmtMappings[i].getMapping().setObject(ec, ps, externalOrderStmtMappings[i].getParameterPositionsForOccurrence(k), orderValue);
                        }
                    }
                }
                sqlControl.executeStatementUpdate(ec, mconn, insertStmt, ps, !batch);
                if (hasIdentityColumn) {
                    // Identity was set in the datastore using auto-increment/identity/serial etc
                    Object newId = getInsertedDatastoreIdentity(ec, sqlControl, op, mconn, ps);
                    if (NucleusLogger.DATASTORE_PERSIST.isDebugEnabled()) {
                        NucleusLogger.DATASTORE_PERSIST.debug(Localiser.msg("052206", op.getObjectAsPrintable(), newId));
                    }
                    op.setPostStoreNewObjectId(newId);
                }
                // Execute any mapping actions on the insert of the fields (e.g Oracle CLOBs/BLOBs)
                for (int i = 0; i < callbacks.length; ++i) {
                    if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                        NucleusLogger.PERSISTENCE.debug(Localiser.msg("052222", op.getObjectAsPrintable(), ((JavaTypeMapping) callbacks[i]).getMemberMetaData().getFullFieldName()));
                    }
                    callbacks[i].insertPostProcessing(op);
                }
                // Update the insert status for this table via the StoreManager
                storeMgr.setObjectIsInsertedToLevel(op, table);
                // (if we did it the other way around we would get a NotYetFlushedException thrown above).
                for (int i = 0; i < relationFieldNumbers.length; i++) {
                    Object value = op.provideField(relationFieldNumbers[i]);
                    if (value != null && ec.getApiAdapter().isDetached(value)) {
                        Object valueAttached = ec.persistObjectInternal(value, null, -1, ObjectProvider.PC);
                        op.replaceField(relationFieldNumbers[i], valueAttached);
                    }
                }
                // Perform reachability on all fields that have no datastore column (1-1 bi non-owner, N-1 bi join)
                if (reachableFieldNumbers.length > 0) {
                    int numberOfReachableFields = 0;
                    for (int i = 0; i < reachableFieldNumbers.length; i++) {
                        if (reachableFieldNumbers[i] < op.getClassMetaData().getMemberCount()) {
                            numberOfReachableFields++;
                        }
                    }
                    int[] fieldNums = new int[numberOfReachableFields];
                    int j = 0;
                    for (int i = 0; i < reachableFieldNumbers.length; i++) {
                        if (reachableFieldNumbers[i] < op.getClassMetaData().getMemberCount()) {
                            fieldNums[j++] = reachableFieldNumbers[i];
                        }
                    }
                    mappingDefinition = new StatementClassMapping();
                    idxs = retrievedStmtMappings;
                    for (int i = 0; i < idxs.length; i++) {
                        if (idxs[i] != null) {
                            mappingDefinition.addMappingForMember(i, idxs[i]);
                        }
                    }
                    NucleusLogger.PERSISTENCE.debug("Performing reachability on fields " + StringUtils.intArrayToString(fieldNums));
                    op.provideFields(fieldNums, new ParameterSetter(op, ps, mappingDefinition));
                }
            } finally {
                sqlControl.closeStatement(mconn, ps);
            }
        } finally {
            mconn.release();
        }
    } catch (SQLException e) {
        String msg = Localiser.msg("052208", op.getObjectAsPrintable(), insertStmt, e.getMessage());
        NucleusLogger.DATASTORE_PERSIST.warn(msg);
        List exceptions = new ArrayList();
        exceptions.add(e);
        while ((e = e.getNextException()) != null) {
            exceptions.add(e);
        }
        throw new NucleusDataStoreException(msg, (Throwable[]) exceptions.toArray(new Throwable[exceptions.size()]));
    }
    // (things like inserting any association parent-child).
    for (int i = 0; i < callbacks.length; ++i) {
        try {
            if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                NucleusLogger.PERSISTENCE.debug(Localiser.msg("052209", op.getObjectAsPrintable(), ((JavaTypeMapping) callbacks[i]).getMemberMetaData().getFullFieldName()));
            }
            callbacks[i].postInsert(op);
        } catch (NotYetFlushedException e) {
            op.updateFieldAfterInsert(e.getPersistable(), ((JavaTypeMapping) callbacks[i]).getMemberMetaData().getAbsoluteFieldNumber());
        }
    }
}
Also used : VersionMetaData(org.datanucleus.metadata.VersionMetaData) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) ParameterSetter(org.datanucleus.store.rdbms.fieldmanager.ParameterSetter) Timestamp(java.sql.Timestamp) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) SQLController(org.datanucleus.store.rdbms.SQLController) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) ArrayList(java.util.ArrayList) List(java.util.List) PreparedStatement(java.sql.PreparedStatement) NotYetFlushedException(org.datanucleus.exceptions.NotYetFlushedException) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) ExecutionContext(org.datanucleus.ExecutionContext) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 37 with JavaTypeMapping

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

the class LocateBulkRequest method processResults.

private ObjectProvider[] processResults(ResultSet rs, ObjectProvider[] ops) throws SQLException {
    List<ObjectProvider> missingOps = new ArrayList<>();
    for (int i = 0; i < ops.length; i++) {
        missingOps.add(ops[i]);
    }
    ExecutionContext ec = ops[0].getExecutionContext();
    while (rs.next()) {
        FieldManager resultFM = new ResultSetGetter(ec, rs, resultMapping, cmd);
        Object id = null;
        Object key = null;
        if (cmd.getIdentityType() == IdentityType.DATASTORE) {
            StatementMappingIndex idx = resultMapping.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
            JavaTypeMapping idMapping = idx.getMapping();
            key = idMapping.getObject(ec, rs, idx.getColumnPositions());
            if (IdentityUtils.isDatastoreIdentity(key)) {
                // If mapping is OIDMapping then returns an OID rather than the column value
                key = IdentityUtils.getTargetKeyForDatastoreIdentity(key);
            }
        } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
            if (cmd.usesSingleFieldIdentityClass()) {
                int[] pkFieldNums = cmd.getPKMemberPositions();
                AbstractMemberMetaData pkMmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkFieldNums[0]);
                if (pkMmd.getType() == int.class) {
                    key = resultFM.fetchIntField(pkFieldNums[0]);
                } else if (pkMmd.getType() == short.class) {
                    key = resultFM.fetchShortField(pkFieldNums[0]);
                } else if (pkMmd.getType() == long.class) {
                    key = resultFM.fetchLongField(pkFieldNums[0]);
                } else if (pkMmd.getType() == char.class) {
                    key = resultFM.fetchCharField(pkFieldNums[0]);
                } else if (pkMmd.getType() == boolean.class) {
                    key = resultFM.fetchBooleanField(pkFieldNums[0]);
                } else if (pkMmd.getType() == byte.class) {
                    key = resultFM.fetchByteField(pkFieldNums[0]);
                } else if (pkMmd.getType() == double.class) {
                    key = resultFM.fetchDoubleField(pkFieldNums[0]);
                } else if (pkMmd.getType() == float.class) {
                    key = resultFM.fetchFloatField(pkFieldNums[0]);
                } else if (pkMmd.getType() == String.class) {
                    key = resultFM.fetchStringField(pkFieldNums[0]);
                } else {
                    key = resultFM.fetchObjectField(pkFieldNums[0]);
                }
            } else {
                id = IdentityUtils.getApplicationIdentityForResultSetRow(ec, cmd, null, true, resultFM);
            }
        }
        // Find which ObjectProvider this row is for
        ObjectProvider op = null;
        for (ObjectProvider missingOp : missingOps) {
            Object opId = missingOp.getInternalObjectId();
            if (cmd.getIdentityType() == IdentityType.DATASTORE) {
                Object opKey = IdentityUtils.getTargetKeyForDatastoreIdentity(opId);
                if (key != null && opKey.getClass() != key.getClass()) {
                    opKey = TypeConversionHelper.convertTo(opKey, key.getClass());
                }
                if (opKey.equals(key)) {
                    op = missingOp;
                    break;
                }
            } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
                if (cmd.usesSingleFieldIdentityClass()) {
                    Object opKey = IdentityUtils.getTargetKeyForSingleFieldIdentity(opId);
                    if (opKey.equals(key)) {
                        op = missingOp;
                        break;
                    }
                } else {
                    if (opId.equals(id)) {
                        op = missingOp;
                        break;
                    }
                }
            }
        }
        if (op != null) {
            // Mark ObjectProvider as processed
            missingOps.remove(op);
            // Load up any unloaded fields that we have selected
            int[] selectedMemberNums = resultMapping.getMemberNumbers();
            int[] unloadedMemberNums = ClassUtils.getFlagsSetTo(op.getLoadedFields(), selectedMemberNums, false);
            if (unloadedMemberNums != null && unloadedMemberNums.length > 0) {
                op.replaceFields(unloadedMemberNums, resultFM);
            }
            // Load version if present and not yet set
            JavaTypeMapping versionMapping = table.getSurrogateMapping(SurrogateColumnType.VERSION, false);
            if (op.getTransactionalVersion() == null && versionMapping != null) {
                VersionMetaData currentVermd = table.getVersionMetaData();
                Object datastoreVersion = null;
                if (currentVermd != null) {
                    if (currentVermd.getFieldName() == null) {
                        // Surrogate version
                        // Why use true now?
                        versionMapping = table.getSurrogateMapping(SurrogateColumnType.VERSION, true);
                        StatementMappingIndex verIdx = resultMapping.getMappingForMemberPosition(SurrogateColumnType.VERSION.getFieldNumber());
                        datastoreVersion = versionMapping.getObject(ec, rs, verIdx.getColumnPositions());
                    } else {
                        datastoreVersion = op.provideField(cmd.getAbsolutePositionOfMember(currentVermd.getFieldName()));
                    }
                    op.setVersion(datastoreVersion);
                }
            }
        }
    }
    if (!missingOps.isEmpty()) {
        return missingOps.toArray(new ObjectProvider[missingOps.size()]);
    }
    return null;
}
Also used : FieldManager(org.datanucleus.store.fieldmanager.FieldManager) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) VersionMetaData(org.datanucleus.metadata.VersionMetaData) ArrayList(java.util.ArrayList) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) ResultSetGetter(org.datanucleus.store.rdbms.fieldmanager.ResultSetGetter) ExecutionContext(org.datanucleus.ExecutionContext) ObjectProvider(org.datanucleus.state.ObjectProvider) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 38 with JavaTypeMapping

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

the class FKListStore method getUpdateFkStatementString.

private String getUpdateFkStatementString(Object element) {
    JavaTypeMapping ownerMapping = this.ownerMapping;
    JavaTypeMapping elemMapping = this.elementMapping;
    JavaTypeMapping orderMapping = this.orderMapping;
    JavaTypeMapping relDiscrimMapping = this.relationDiscriminatorMapping;
    Table table = containerTable;
    if (elementInfo.length > 1) {
        ComponentInfo elemInfo = getComponentInfoForElement(element);
        if (elemInfo != null) {
            table = elemInfo.getDatastoreClass();
            ownerMapping = elemInfo.getOwnerMapping();
            elemMapping = elemInfo.getDatastoreClass().getIdMapping();
            orderMapping = elemInfo.getDatastoreClass().getExternalMapping(ownerMemberMetaData, MappingType.EXTERNAL_INDEX);
            relDiscrimMapping = elemInfo.getDatastoreClass().getExternalMapping(ownerMemberMetaData, MappingType.EXTERNAL_FK_DISCRIMINATOR);
        }
    }
    StringBuilder stmt = new StringBuilder("UPDATE ").append(table.toString()).append(" SET ");
    for (int i = 0; i < ownerMapping.getNumberOfDatastoreMappings(); i++) {
        if (i > 0) {
            stmt.append(",");
        }
        stmt.append(ownerMapping.getDatastoreMapping(i).getColumn().getIdentifier().toString());
        stmt.append("=");
        stmt.append(ownerMapping.getDatastoreMapping(i).getUpdateInputParameter());
    }
    if (orderMapping != null) {
        for (int i = 0; i < orderMapping.getNumberOfDatastoreMappings(); i++) {
            stmt.append(",");
            stmt.append(orderMapping.getDatastoreMapping(i).getColumn().getIdentifier().toString());
            stmt.append("=");
            stmt.append(orderMapping.getDatastoreMapping(i).getUpdateInputParameter());
        }
    }
    if (relDiscrimMapping != null) {
        for (int i = 0; i < relDiscrimMapping.getNumberOfDatastoreMappings(); i++) {
            stmt.append(",");
            stmt.append(relDiscrimMapping.getDatastoreMapping(i).getColumn().getIdentifier().toString());
            stmt.append("=");
            stmt.append(relDiscrimMapping.getDatastoreMapping(i).getUpdateInputParameter());
        }
    }
    stmt.append(" WHERE ");
    BackingStoreHelper.appendWhereClauseForElement(stmt, elemMapping, element, elementsAreSerialised, null, true);
    return stmt.toString();
}
Also used : SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) Table(org.datanucleus.store.rdbms.table.Table) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)

Example 39 with JavaTypeMapping

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

the class FKListStore method validateElementForWriting.

/**
 * Method to validate that an element is valid for writing to the datastore.
 * TODO Minimise differences to super.validateElementForWriting()
 * @param op ObjectProvider for the List
 * @param element The element to validate
 * @param index The position that the element is being stored at in the list
 * @return Whether the element was inserted
 */
protected boolean validateElementForWriting(final ObjectProvider op, final Object element, final int index) {
    final Object newOwner = op.getObject();
    ComponentInfo info = getComponentInfoForElement(element);
    final DatastoreClass elementTable;
    if (storeMgr.getNucleusContext().getMetaDataManager().isPersistentInterface(elementType)) {
        elementTable = storeMgr.getDatastoreClass(storeMgr.getNucleusContext().getMetaDataManager().getImplementationNameForPersistentInterface(elementType), clr);
    } else {
        elementTable = storeMgr.getDatastoreClass(element.getClass().getName(), clr);
    }
    final JavaTypeMapping orderMapping;
    if (info != null) {
        orderMapping = info.getDatastoreClass().getExternalMapping(ownerMemberMetaData, MappingType.EXTERNAL_INDEX);
    } else {
        orderMapping = this.orderMapping;
    }
    // Check if element is ok for use in the datastore, specifying any external mappings that may be required
    boolean inserted = super.validateElementForWriting(op.getExecutionContext(), element, new FieldValues() {

        public void fetchFields(ObjectProvider elemOP) {
            // Find the (element) table storing the FK back to the owner
            if (elementTable != null) {
                JavaTypeMapping externalFKMapping = elementTable.getExternalMapping(ownerMemberMetaData, MappingType.EXTERNAL_FK);
                if (externalFKMapping != null) {
                    // The element has an external FK mapping so set the value it needs to use in the INSERT
                    elemOP.setAssociatedValue(externalFKMapping, op.getObject());
                }
                if (relationDiscriminatorMapping != null) {
                    elemOP.setAssociatedValue(relationDiscriminatorMapping, relationDiscriminatorValue);
                }
                if (orderMapping != null && index >= 0) {
                    if (ownerMemberMetaData.getOrderMetaData() != null && ownerMemberMetaData.getOrderMetaData().getMappedBy() != null) {
                        // Order is stored in a field in the element so update it
                        // We support mapped-by fields of types int/long/Integer/Long currently
                        Object indexValue = null;
                        if (orderMapping.getMemberMetaData().getTypeName().equals(ClassNameConstants.JAVA_LANG_LONG) || orderMapping.getMemberMetaData().getTypeName().equals(ClassNameConstants.LONG)) {
                            indexValue = Long.valueOf(index);
                        } else {
                            indexValue = Integer.valueOf(index);
                        }
                        elemOP.replaceFieldMakeDirty(orderMapping.getMemberMetaData().getAbsoluteFieldNumber(), indexValue);
                    } else {
                        // Order is stored in a surrogate column so save its vaue for the element to use later
                        elemOP.setAssociatedValue(orderMapping, Integer.valueOf(index));
                    }
                }
            }
            if (ownerMemberMetaData.getMappedBy() != null) {
                // TODO This is ManagedRelations - move into RelationshipManager
                // Managed Relations : 1-N bidir, so make sure owner is correct at persist
                // TODO Support DOT notation in mappedBy
                ObjectProvider ownerHolderOP = elemOP;
                int ownerFieldNumberInHolder = -1;
                if (ownerMemberMetaData.getMappedBy().indexOf('.') > 0) {
                    AbstractMemberMetaData otherMmd = null;
                    AbstractClassMetaData otherCmd = info.getAbstractClassMetaData();
                    String remainingMappedBy = ownerMemberMetaData.getMappedBy();
                    while (remainingMappedBy.indexOf('.') > 0) {
                        int dotPosition = remainingMappedBy.indexOf('.');
                        String thisMappedBy = remainingMappedBy.substring(0, dotPosition);
                        otherMmd = otherCmd.getMetaDataForMember(thisMappedBy);
                        Object holderValueAtField = ownerHolderOP.provideField(otherMmd.getAbsoluteFieldNumber());
                        ownerHolderOP = op.getExecutionContext().findObjectProviderForEmbedded(holderValueAtField, ownerHolderOP, otherMmd);
                        remainingMappedBy = remainingMappedBy.substring(dotPosition + 1);
                        otherCmd = storeMgr.getMetaDataManager().getMetaDataForClass(otherMmd.getTypeName(), clr);
                        if (remainingMappedBy.indexOf('.') < 0) {
                            otherMmd = otherCmd.getMetaDataForMember(remainingMappedBy);
                            ownerFieldNumberInHolder = otherMmd.getAbsoluteFieldNumber();
                        }
                    }
                } else {
                    ownerFieldNumberInHolder = info.getAbstractClassMetaData().getAbsolutePositionOfMember(ownerMemberMetaData.getMappedBy());
                }
                Object currentOwner = ownerHolderOP.provideField(ownerFieldNumberInHolder);
                if (currentOwner == null) {
                    // No owner, so correct it
                    NucleusLogger.PERSISTENCE.info(Localiser.msg("056037", op.getObjectAsPrintable(), ownerMemberMetaData.getFullFieldName(), StringUtils.toJVMIDString(ownerHolderOP.getObject())));
                    ownerHolderOP.replaceFieldMakeDirty(ownerFieldNumberInHolder, newOwner);
                } else if (currentOwner != newOwner && op.getReferencedPC() == null) {
                    // Inconsistent owner, so throw exception
                    throw new NucleusUserException(Localiser.msg("056038", op.getObjectAsPrintable(), ownerMemberMetaData.getFullFieldName(), StringUtils.toJVMIDString(ownerHolderOP.getObject()), StringUtils.toJVMIDString(currentOwner)));
                }
            }
        }

        public void fetchNonLoadedFields(ObjectProvider op) {
        }

        public FetchPlan getFetchPlanForLoading() {
            return null;
        }
    });
    return inserted;
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ObjectProvider(org.datanucleus.state.ObjectProvider) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) FieldValues(org.datanucleus.store.FieldValues) FetchPlan(org.datanucleus.FetchPlan) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData)

Example 40 with JavaTypeMapping

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

the class FKListStore 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 ELEM_TBL
 * [WHERE]
 *   [ELEM_TBL.OWNER_ID = {value}] [AND]
 *   [ELEM_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).
 * @param startIdx Start index for the iterator (or -1)
 * @param endIdx End index for the iterator (or -1)
 * @return The SQLStatement and its associated StatementClassMapping
 */
public IteratorStatement getIteratorStatement(ExecutionContext ec, FetchPlan fp, boolean addRestrictionOnOwner, int startIdx, int endIdx) {
    SelectStatement sqlStmt = null;
    StatementClassMapping stmtClassMapping = new StatementClassMapping();
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    if (elementInfo.length == 1 && elementInfo[0].getDatastoreClass().getDiscriminatorMetaData() != null && elementInfo[0].getDatastoreClass().getDiscriminatorMetaData().getStrategy() != DiscriminatorStrategy.NONE) {
        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 i = 0; i < clsNames.length; i++) {
                cls[i] = clr.classForName(clsNames[i]);
            }
            sqlStmt = new DiscriminatorStatementGenerator(storeMgr, clr, cls, true, null, null).getStatement(ec);
        } else {
            sqlStmt = new DiscriminatorStatementGenerator(storeMgr, clr, clr.classForName(elementInfo[0].getClassName()), true, null, null).getStatement(ec);
        }
        iterateUsingDiscriminator = true;
        // Select the required fields
        SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, stmtClassMapping, fp, sqlStmt.getPrimaryTable(), elementCmd, fp.getMaxFetchDepth());
    } else {
        for (int i = 0; i < elementInfo.length; i++) {
            final Class elementCls = clr.classForName(this.elementInfo[i].getClassName());
            UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, elementCls, true, null, null);
            stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
            stmtClassMapping.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
            SelectStatement subStmt = stmtGen.getStatement(ec);
            // Select the required fields (of the element class)
            if (sqlStmt == null) {
                if (elementInfo.length > 1) {
                    SQLStatementHelper.selectIdentityOfCandidateInStatement(subStmt, stmtClassMapping, elementInfo[i].getAbstractClassMetaData());
                } else {
                    SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(subStmt, stmtClassMapping, fp, subStmt.getPrimaryTable(), elementInfo[i].getAbstractClassMetaData(), fp.getMaxFetchDepth());
                }
            } else {
                if (elementInfo.length > 1) {
                    SQLStatementHelper.selectIdentityOfCandidateInStatement(subStmt, null, elementInfo[i].getAbstractClassMetaData());
                } else {
                    SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(subStmt, null, fp, subStmt.getPrimaryTable(), elementInfo[i].getAbstractClassMetaData(), fp.getMaxFetchDepth());
                }
            }
            if (sqlStmt == null) {
                sqlStmt = subStmt;
            } else {
                sqlStmt.union(subStmt);
            }
        }
        if (sqlStmt == null) {
            throw new NucleusException("Unable to generate iterator statement for field=" + getOwnerMemberMetaData().getFullFieldName());
        }
    }
    if (addRestrictionOnOwner) {
        // Apply condition to filter by owner
        // TODO If ownerMapping is not for containerTable then do JOIN to ownerTable in the FROM clause (or find if already done)
        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 (indexedList) {
        // "Indexed List" so allow restriction on returned indexes
        boolean needsOrdering = true;
        if (startIdx == -1 && endIdx == -1) {
            // Just restrict to >= 0 so we don't get any disassociated elements
            SQLExpression indexExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
            SQLExpression indexVal = exprFactory.newLiteral(sqlStmt, orderMapping, 0);
            sqlStmt.whereAnd(indexExpr.ge(indexVal), true);
        } else if (startIdx >= 0 && endIdx == startIdx) {
            // Particular index required so add restriction
            needsOrdering = false;
            SQLExpression indexExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
            SQLExpression indexVal = exprFactory.newLiteral(sqlStmt, orderMapping, startIdx);
            sqlStmt.whereAnd(indexExpr.eq(indexVal), true);
        } else {
            // Add restrictions on start/end indices as required
            if (startIdx >= 0) {
                SQLExpression indexExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
                SQLExpression indexVal = exprFactory.newLiteral(sqlStmt, orderMapping, startIdx);
                sqlStmt.whereAnd(indexExpr.ge(indexVal), true);
            } else {
                // Just restrict to >= 0 so we don't get any disassociated elements
                SQLExpression indexExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
                SQLExpression indexVal = exprFactory.newLiteral(sqlStmt, orderMapping, 0);
                sqlStmt.whereAnd(indexExpr.ge(indexVal), true);
            }
            if (endIdx >= 0) {
                SQLExpression indexExpr2 = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
                SQLExpression indexVal2 = exprFactory.newLiteral(sqlStmt, orderMapping, endIdx);
                sqlStmt.whereAnd(indexExpr2.lt(indexVal2), true);
            }
        }
        if (needsOrdering) {
            // Order by the ordering column
            SQLTable orderSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
            SQLExpression[] orderExprs = new SQLExpression[orderMapping.getNumberOfDatastoreMappings()];
            boolean[] descendingOrder = new boolean[orderMapping.getNumberOfDatastoreMappings()];
            orderExprs[0] = exprFactory.newExpression(sqlStmt, orderSqlTbl, orderMapping);
            sqlStmt.setOrdering(orderExprs, descendingOrder);
        }
    } else {
        // Apply ordering defined by <order-by>
        DatastoreClass elementTbl = elementInfo[0].getDatastoreClass();
        FieldOrder[] orderComponents = ownerMemberMetaData.getOrderMetaData().getFieldOrders();
        SQLExpression[] orderExprs = new SQLExpression[orderComponents.length];
        boolean[] orderDirs = new boolean[orderComponents.length];
        for (int i = 0; i < orderComponents.length; i++) {
            String fieldName = orderComponents[i].getFieldName();
            JavaTypeMapping fieldMapping = elementTbl.getMemberMapping(elementInfo[0].getAbstractClassMetaData().getMetaDataForMember(fieldName));
            orderDirs[i] = !orderComponents[i].isForward();
            SQLTable fieldSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), fieldMapping);
            orderExprs[i] = exprFactory.newExpression(sqlStmt, fieldSqlTbl, fieldMapping);
        }
        sqlStmt.setOrdering(orderExprs, orderDirs);
    }
    return new IteratorStatement(this, sqlStmt, stmtClassMapping);
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) FieldOrder(org.datanucleus.metadata.OrderMetaData.FieldOrder) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) UnionStatementGenerator(org.datanucleus.store.rdbms.sql.UnionStatementGenerator) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) DiscriminatorStatementGenerator(org.datanucleus.store.rdbms.sql.DiscriminatorStatementGenerator) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException)

Aggregations

JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)230 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)96 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)82 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)82 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)81 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)76 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)69 ArrayList (java.util.ArrayList)66 NucleusException (org.datanucleus.exceptions.NucleusException)57 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)50 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)47 NumericExpression (org.datanucleus.store.rdbms.sql.expression.NumericExpression)43 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)37 PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)30 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)30 StringExpression (org.datanucleus.store.rdbms.sql.expression.StringExpression)27 List (java.util.List)25 ReferenceMapping (org.datanucleus.store.rdbms.mapping.java.ReferenceMapping)22 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)21 StringLiteral (org.datanucleus.store.rdbms.sql.expression.StringLiteral)21