Search in sources :

Example 1 with NoTableManagedException

use of org.datanucleus.store.rdbms.exceptions.NoTableManagedException in project datanucleus-rdbms by datanucleus.

the class ReferenceMapping method createPerImplementationColumnsForReferenceField.

/**
 * Create columns for reference (Interface/Object) fields on a per-implementation basis.
 * This call ColumnCreator.createColumnsForField for each implementation class of the reference.
 */
void createPerImplementationColumnsForReferenceField(boolean pk, boolean nullable, boolean serialised, boolean embedded, FieldRole fieldRole, ColumnMetaData[] columnMetaData, ClassLoaderResolver clr) {
    if (this instanceof InterfaceMapping && mmd.hasExtension(MetaData.EXTENSION_MEMBER_IMPLEMENTATION_CLASSES)) {
        // Store the implementation-classes with the mapping (persistent interfaces?)
        ((InterfaceMapping) this).setImplementationClasses(mmd.getValueForExtension(MetaData.EXTENSION_MEMBER_IMPLEMENTATION_CLASSES));
    }
    // Find the available implementations that we are creating columns for
    String[] implTypes = null;
    try {
        implTypes = MetaDataUtils.getInstance().getImplementationNamesForReferenceField(mmd, fieldRole, clr, storeMgr.getMetaDataManager());
    } catch (NucleusUserException nue) {
        // No implementation classes found, so log warning and return
        if (storeMgr.getBooleanProperty(PropertyNames.PROPERTY_STORE_ALLOW_REFS_WITHOUT_IMPLS, false)) {
            NucleusLogger.DATASTORE_SCHEMA.warn("Possible problem encountered while adding columns for field " + mmd.getFullFieldName() + " : " + nue.getMessage());
            return;
        }
        throw nue;
    }
    // Set the PK and nullability of column(s) for the implementations (based on the number of impls etc)
    if (implTypes.length > 1) {
        // Cannot be part of PK if more than 1 implementation
        pk = false;
    }
    if (implTypes.length > 1 && !pk) {
        // Must be nullable if more than 1 impl (since only 1 impl can have value at a time)
        nullable = true;
    }
    // Create list of classes that require columns.
    // We only add columns for the implementation that is the root of a particular inheritance tree
    // e.g if we have A implements I1, and B extends A then they both are valid implementations
    // but we only want to create column(s) for A.
    Collection implClasses = new ArrayList();
    for (int i = 0; i < implTypes.length; i++) {
        Class type = clr.classForName(implTypes[i]);
        if (type == null) {
            throw new NucleusUserException(Localiser.msg("020189", mmd.getTypeName(), implTypes[i]));
        } else if (type.isInterface()) {
            throw new NucleusUserException(Localiser.msg("020190", mmd.getFullFieldName(), mmd.getTypeName(), implTypes[i]));
        }
        Iterator iter = implClasses.iterator();
        boolean toBeAdded = true;
        Class clsToSwap = null;
        while (iter.hasNext()) {
            Class cls = (Class) iter.next();
            if (cls == type) {
                // Implementation already present
                toBeAdded = false;
                break;
            }
            if (type.isAssignableFrom(cls)) {
                // "type" is superclass of "cls" so swap subclass for this class
                clsToSwap = cls;
                toBeAdded = false;
                break;
            } else if (cls.isAssignableFrom(type)) {
                toBeAdded = false;
                break;
            }
        }
        if (toBeAdded) {
            implClasses.add(type);
        } else if (clsToSwap != null) {
            implClasses.remove(clsToSwap);
            implClasses.add(type);
        }
    }
    // Add columns for each of these implementations
    int colPos = 0;
    Iterator implClsIter = implClasses.iterator();
    while (implClsIter.hasNext()) {
        Class implClass = (Class) implClsIter.next();
        boolean present = false;
        int numJavaTypeMappings = getJavaTypeMapping().length;
        for (int i = 0; i < numJavaTypeMappings; i++) {
            JavaTypeMapping implMapping = getJavaTypeMapping()[i];
            if (implClass.getName().equals(implMapping.getType())) {
                present = true;
            }
        }
        if (present) {
            // Implementation already present in mapping (e.g reinitialising) so skip this
            continue;
        }
        String fieldTypeName = getReferenceFieldType(fieldRole);
        boolean isPersistentInterfaceField = storeMgr.getNucleusContext().getMetaDataManager().isPersistentInterface(fieldTypeName);
        boolean columnsNeeded = true;
        if (isPersistentInterfaceField && !storeMgr.getNucleusContext().getMetaDataManager().isPersistentInterfaceImplementation(fieldTypeName, implClass.getName())) {
            // We have a "persistent-interface" field yet this is not a generated implementation so ignore it
            // It is arguable if we should allow the real implementations of this interface here, but the JDO2 TCK doesn't
            // make that assumption so we don't either
            columnsNeeded = false;
        }
        if (columnsNeeded) {
            // Get the mapping for this implementation
            JavaTypeMapping m;
            if (storeMgr.getMappingManager().isSupportedMappedType(implClass.getName())) {
                m = storeMgr.getMappingManager().getMapping(implClass, serialised, embedded, mmd.getFullFieldName());
            } else {
                try {
                    DatastoreClass dc = storeMgr.getDatastoreClass(implClass.getName(), clr);
                    m = dc.getIdMapping();
                } catch (NoTableManagedException ex) {
                    // TODO Localise this message
                    throw new NucleusUserException("Cannot define columns for " + mmd.getFullFieldName() + " due to " + ex.getMessage(), ex);
                }
            }
            ColumnMetaData[] columnMetaDataForType = null;
            if (columnMetaData != null && columnMetaData.length > 0) {
                if (columnMetaData.length < colPos + m.getNumberOfDatastoreMappings()) {
                    throw new NucleusUserException(Localiser.msg("020186", mmd.getFullFieldName(), "" + columnMetaData.length, "" + (colPos + m.getNumberOfDatastoreMappings())));
                }
                columnMetaDataForType = new ColumnMetaData[m.getNumberOfDatastoreMappings()];
                System.arraycopy(columnMetaData, colPos, columnMetaDataForType, 0, columnMetaDataForType.length);
                colPos += columnMetaDataForType.length;
            }
            // Create the FK column(s) for this implementation
            ColumnCreator.createColumnsForField(implClass, this, table, storeMgr, mmd, pk, nullable, serialised, embedded, fieldRole, columnMetaDataForType, clr, true, null);
            if (NucleusLogger.DATASTORE.isInfoEnabled()) {
                NucleusLogger.DATASTORE.info(Localiser.msg("020188", implClass, mmd.getName()));
            }
        }
    }
}
Also used : NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ArrayList(java.util.ArrayList) Iterator(java.util.Iterator) Collection(java.util.Collection) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) NoTableManagedException(org.datanucleus.store.rdbms.exceptions.NoTableManagedException)

Example 2 with NoTableManagedException

use of org.datanucleus.store.rdbms.exceptions.NoTableManagedException 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.
 */
public List 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;
    }
    ArrayList 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.getNumberOfDatastoreMappings() > 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.getNumberOfDatastoreMappings() > 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 3 with NoTableManagedException

use of org.datanucleus.store.rdbms.exceptions.NoTableManagedException in project datanucleus-rdbms by datanucleus.

the class ElementContainerTable method initialize.

/**
 * Method to initialise the table definition. Adds the owner mapping.
 * @param clr The ClassLoaderResolver
 */
public void initialize(ClassLoaderResolver clr) {
    assertIsUninitialized();
    // Add owner mapping
    AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
    ColumnMetaData[] columnMetaData = 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
        columnMetaData = mmd.getJoinMetaData().getColumnMetaData();
    } else if (relatedMmds != null && relatedMmds[0].getElementMetaData() != null && relatedMmds[0].getElementMetaData().getColumnMetaData() != null && relatedMmds[0].getElementMetaData().getColumnMetaData().length > 0) {
        // Column mappings defined at other side (M-N)
        // When specified at other side they use the <element> tag
        // ** This is really only for Collections/Sets since M-N doesnt make sense for indexed Lists/arrays **
        columnMetaData = relatedMmds[0].getElementMetaData().getColumnMetaData();
    }
    try {
        ownerMapping = ColumnCreator.createColumnsForJoinTables(clr.classForName(ownerType), mmd, columnMetaData, storeMgr, this, false, false, FieldRole.ROLE_OWNER, clr, ownerTable);
    } catch (NoTableManagedException ntme) {
        // Maybe this is a join table from an embedded object, so no table to link back to
        throw new NucleusUserException("Table " + toString() + " for member=" + mmd.getFullFieldName() + " needs a column to link back to its owner, yet the owner type (" + ownerType + ") has no table of its own (embedded?)");
    }
    if (NucleusLogger.DATASTORE.isDebugEnabled()) {
        logMapping(mmd.getFullFieldName() + ".[OWNER]", ownerMapping);
    }
    // Add any distinguisher column
    if (mmd.hasExtension(MetaData.EXTENSION_MEMBER_RELATION_DISCRIM_COLUMN) || mmd.hasExtension(MetaData.EXTENSION_MEMBER_RELATION_DISCRIM_VALUE)) {
        // Generate some columnMetaData for our new column
        String colName = mmd.getValueForExtension(MetaData.EXTENSION_MEMBER_RELATION_DISCRIM_COLUMN);
        if (colName == null) {
            // No column defined so use a fallback name
            colName = "RELATION_DISCRIM";
        }
        ColumnMetaData colmd = new ColumnMetaData();
        colmd.setName(colName);
        boolean relationDiscriminatorPk = false;
        if (mmd.hasExtension(MetaData.EXTENSION_MEMBER_RELATION_DISCRIM_PK) && mmd.getValueForExtension(MetaData.EXTENSION_MEMBER_RELATION_DISCRIM_PK).equalsIgnoreCase("true")) {
            // Default this to not be part of the PK of the join table, but allow the user to override it
            relationDiscriminatorPk = true;
        }
        if (!relationDiscriminatorPk) {
            // Allow for elements not in any discriminated collection (when not PK)
            colmd.setAllowsNull(Boolean.TRUE);
        }
        // Create the mapping and its datastore column (only support String relation discriminators here)
        relationDiscriminatorMapping = storeMgr.getMappingManager().getMapping(String.class);
        ColumnCreator.createIndexColumn(relationDiscriminatorMapping, storeMgr, clr, this, colmd, relationDiscriminatorPk);
        relationDiscriminatorValue = mmd.getValueForExtension(MetaData.EXTENSION_MEMBER_RELATION_DISCRIM_VALUE);
        if (relationDiscriminatorValue == null) {
            // No value defined so just use the field name
            relationDiscriminatorValue = mmd.getFullFieldName();
        }
    }
}
Also used : NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) NoTableManagedException(org.datanucleus.store.rdbms.exceptions.NoTableManagedException)

Example 4 with NoTableManagedException

use of org.datanucleus.store.rdbms.exceptions.NoTableManagedException in project datanucleus-rdbms by datanucleus.

the class RDBMSStoreManager method getBackingStoreForField.

/**
 * Accessor for the backing store for the specified member.
 * Note : if we have an embedded object that is embedded into some other type and the object has a member that requires a join table (backing store), this method
 * will not cater for the different places that can be embedded.
 * @param clr The ClassLoaderResolver
 * @param mmd metadata for the member to be persisted by this Store
 * @param type instantiated type or prefered type
 * @return The backing store
 */
public Store getBackingStoreForField(ClassLoaderResolver clr, AbstractMemberMetaData mmd, Class type) {
    if (mmd == null || mmd.isSerialized()) {
        return null;
    }
    Store store = backingStoreByMemberName.get(mmd.getFullFieldName());
    if (store != null) {
        return store;
    }
    synchronized (backingStoreByMemberName) {
        // Just in case we synced just after someone added since our previous lookup above
        store = backingStoreByMemberName.get(mmd.getFullFieldName());
        if (store != null) {
            return store;
        }
        Class expectedMappingType = null;
        if (mmd.getMap() != null) {
            expectedMappingType = MapMapping.class;
        } else if (mmd.getArray() != null) {
            expectedMappingType = ArrayMapping.class;
        } else if (mmd.getCollection() != null) {
            expectedMappingType = CollectionMapping.class;
        } else {
            expectedMappingType = PersistableMapping.class;
        }
        // Validate the mapping type matches the table
        try {
            DatastoreClass ownerTable = getDatastoreClass(mmd.getClassName(), clr);
            if (ownerTable == null) {
                // Class doesn't manage its own table (uses subclass-table, or superclass-table?)
                AbstractClassMetaData fieldTypeCmd = getMetaDataManager().getMetaDataForClass(mmd.getClassName(), clr);
                AbstractClassMetaData[] tableOwnerCmds = getClassesManagingTableForClass(fieldTypeCmd, clr);
                if (tableOwnerCmds != null && tableOwnerCmds.length == 1) {
                    ownerTable = getDatastoreClass(tableOwnerCmds[0].getFullClassName(), clr);
                }
            }
            if (ownerTable != null) {
                JavaTypeMapping m = ownerTable.getMemberMapping(mmd);
                if (!expectedMappingType.isAssignableFrom(m.getClass())) {
                    String requiredType = type != null ? type.getName() : mmd.getTypeName();
                    NucleusLogger.PERSISTENCE.warn("Member " + mmd.getFullFieldName() + " in table=" + ownerTable + " has mapping=" + m + " but expected mapping type=" + expectedMappingType);
                    throw new IncompatibleFieldTypeException(mmd.getFullFieldName(), requiredType, m.getType());
                }
            }
        } catch (NoTableManagedException ntme) {
        // Embedded, so just pass through
        }
        if (mmd.getMap() != null) {
            Table datastoreTable = getTable(mmd);
            if (datastoreTable == null) {
                store = new FKMapStore(mmd, this, clr);
            } else {
                store = new JoinMapStore((MapTable) datastoreTable, clr);
            }
        } else if (mmd.getArray() != null) {
            Table datastoreTable = getTable(mmd);
            if (datastoreTable != null) {
                store = new JoinArrayStore(mmd, (ArrayTable) datastoreTable, clr);
            } else {
                store = new FKArrayStore(mmd, this, clr);
            }
        } else if (mmd.getCollection() != null) {
            Table datastoreTable = getTable(mmd);
            if (type == null) {
                // No type to base it on so create it based on the field declared type
                if (datastoreTable == null) {
                    // We need a "FK" relation
                    if (Set.class.isAssignableFrom(mmd.getType())) {
                        store = new FKSetStore(mmd, this, clr);
                    } else if (List.class.isAssignableFrom(mmd.getType()) || Queue.class.isAssignableFrom(mmd.getType())) {
                        store = new FKListStore(mmd, this, clr);
                    } else if (mmd.getOrderMetaData() != null) {
                        // User has requested ordering
                        store = new FKListStore(mmd, this, clr);
                    } else {
                        store = new FKSetStore(mmd, this, clr);
                    }
                } else {
                    // We need a "JoinTable" relation.
                    if (Set.class.isAssignableFrom(mmd.getType())) {
                        store = new JoinSetStore(mmd, (CollectionTable) datastoreTable, clr);
                    } else if (List.class.isAssignableFrom(mmd.getType()) || Queue.class.isAssignableFrom(mmd.getType())) {
                        store = new JoinListStore(mmd, (CollectionTable) datastoreTable, clr);
                    } else if (mmd.getOrderMetaData() != null) {
                        // User has requested ordering
                        store = new JoinListStore(mmd, (CollectionTable) datastoreTable, clr);
                    } else {
                        store = new JoinSetStore(mmd, (CollectionTable) datastoreTable, clr);
                    }
                }
            } else {
                // Instantiated type specified, so use it to pick the associated backing store
                if (datastoreTable == null) {
                    if (SCOUtils.isListBased(type)) {
                        // List required
                        store = new FKListStore(mmd, this, clr);
                    } else {
                        // Set required
                        store = new FKSetStore(mmd, this, clr);
                    }
                } else {
                    if (SCOUtils.isListBased(type)) {
                        // List required
                        store = new JoinListStore(mmd, (CollectionTable) datastoreTable, clr);
                    } else {
                        // Set required
                        store = new JoinSetStore(mmd, (CollectionTable) datastoreTable, clr);
                    }
                }
            }
        } else {
            store = new JoinPersistableRelationStore(mmd, (PersistableJoinTable) getTable(mmd), clr);
        }
        backingStoreByMemberName.put(mmd.getFullFieldName(), store);
        return store;
    }
}
Also used : Table(org.datanucleus.store.rdbms.table.Table) ProbeTable(org.datanucleus.store.rdbms.table.ProbeTable) JoinTable(org.datanucleus.store.rdbms.table.JoinTable) ClassTable(org.datanucleus.store.rdbms.table.ClassTable) MapTable(org.datanucleus.store.rdbms.table.MapTable) PersistableJoinTable(org.datanucleus.store.rdbms.table.PersistableJoinTable) ArrayTable(org.datanucleus.store.rdbms.table.ArrayTable) CollectionTable(org.datanucleus.store.rdbms.table.CollectionTable) SequenceTable(org.datanucleus.store.rdbms.valuegenerator.SequenceTable) JoinArrayStore(org.datanucleus.store.rdbms.scostore.JoinArrayStore) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) JoinMapStore(org.datanucleus.store.rdbms.scostore.JoinMapStore) JoinSetStore(org.datanucleus.store.rdbms.scostore.JoinSetStore) JoinListStore(org.datanucleus.store.rdbms.scostore.JoinListStore) Store(org.datanucleus.store.types.scostore.Store) JoinArrayStore(org.datanucleus.store.rdbms.scostore.JoinArrayStore) JoinPersistableRelationStore(org.datanucleus.store.rdbms.scostore.JoinPersistableRelationStore) FKSetStore(org.datanucleus.store.rdbms.scostore.FKSetStore) FKListStore(org.datanucleus.store.rdbms.scostore.FKListStore) FKMapStore(org.datanucleus.store.rdbms.scostore.FKMapStore) FKArrayStore(org.datanucleus.store.rdbms.scostore.FKArrayStore) JoinMapStore(org.datanucleus.store.rdbms.scostore.JoinMapStore) IncompatibleFieldTypeException(org.datanucleus.store.types.IncompatibleFieldTypeException) MacroString(org.datanucleus.util.MacroString) JoinListStore(org.datanucleus.store.rdbms.scostore.JoinListStore) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) MapTable(org.datanucleus.store.rdbms.table.MapTable) ArrayMapping(org.datanucleus.store.rdbms.mapping.java.ArrayMapping) JoinSetStore(org.datanucleus.store.rdbms.scostore.JoinSetStore) CollectionTable(org.datanucleus.store.rdbms.table.CollectionTable) FKMapStore(org.datanucleus.store.rdbms.scostore.FKMapStore) FKSetStore(org.datanucleus.store.rdbms.scostore.FKSetStore) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) FKArrayStore(org.datanucleus.store.rdbms.scostore.FKArrayStore) PersistableJoinTable(org.datanucleus.store.rdbms.table.PersistableJoinTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NoTableManagedException(org.datanucleus.store.rdbms.exceptions.NoTableManagedException) FKListStore(org.datanucleus.store.rdbms.scostore.FKListStore) JoinPersistableRelationStore(org.datanucleus.store.rdbms.scostore.JoinPersistableRelationStore)

Example 5 with NoTableManagedException

use of org.datanucleus.store.rdbms.exceptions.NoTableManagedException in project datanucleus-rdbms by datanucleus.

the class ClassTable method initializePK.

/**
 * Method to initialise the table primary key field(s).
 * @param clr The ClassLoaderResolver
 */
protected void initializePK(ClassLoaderResolver clr) {
    assertIsPKUninitialized();
    AbstractMemberMetaData[] membersToAdd = new AbstractMemberMetaData[cmd.getNoOfPrimaryKeyMembers()];
    // Initialise Primary Key mappings for application id with PK fields in this class
    int pkFieldNum = 0;
    int fieldCount = cmd.getNoOfManagedMembers();
    boolean hasPrimaryKeyInThisClass = false;
    if (cmd.getNoOfPrimaryKeyMembers() > 0) {
        pkMappings = new JavaTypeMapping[cmd.getNoOfPrimaryKeyMembers()];
        if (cmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.COMPLETE_TABLE) {
            // COMPLETE-TABLE so use root class metadata and add PK members
            // TODO Does this allow for overridden PK field info ?
            AbstractClassMetaData baseCmd = cmd.getBaseAbstractClassMetaData();
            fieldCount = baseCmd.getNoOfManagedMembers();
            for (int relFieldNum = 0; relFieldNum < fieldCount; ++relFieldNum) {
                AbstractMemberMetaData mmd = baseCmd.getMetaDataForManagedMemberAtRelativePosition(relFieldNum);
                if (mmd.isPrimaryKey()) {
                    AbstractMemberMetaData overriddenMmd = cmd.getOverriddenMember(mmd.getName());
                    if (overriddenMmd != null) {
                        // PK field is overridden so use the overriding definition
                        mmd = overriddenMmd;
                    }
                    if (mmd.getPersistenceModifier() == FieldPersistenceModifier.PERSISTENT) {
                        membersToAdd[pkFieldNum++] = mmd;
                        hasPrimaryKeyInThisClass = true;
                    } else if (mmd.getPersistenceModifier() != FieldPersistenceModifier.TRANSACTIONAL) {
                        throw new NucleusException(Localiser.msg("057006", mmd.getName())).setFatal();
                    }
                    // Check if auto-increment and that it is supported by this RDBMS
                    if ((mmd.getValueStrategy() == ValueGenerationStrategy.IDENTITY) && !dba.supportsOption(DatastoreAdapter.IDENTITY_COLUMNS)) {
                        throw new NucleusException(Localiser.msg("057020", cmd.getFullClassName(), mmd.getName())).setFatal();
                    }
                }
            }
        } else {
            for (int relFieldNum = 0; relFieldNum < fieldCount; ++relFieldNum) {
                AbstractMemberMetaData fmd = cmd.getMetaDataForManagedMemberAtRelativePosition(relFieldNum);
                if (fmd.isPrimaryKey()) {
                    if (fmd.getPersistenceModifier() == FieldPersistenceModifier.PERSISTENT) {
                        membersToAdd[pkFieldNum++] = fmd;
                        hasPrimaryKeyInThisClass = true;
                    } else if (fmd.getPersistenceModifier() != FieldPersistenceModifier.TRANSACTIONAL) {
                        throw new NucleusException(Localiser.msg("057006", fmd.getName())).setFatal();
                    }
                    // Check if auto-increment and that it is supported by this RDBMS
                    if ((fmd.getValueStrategy() == ValueGenerationStrategy.IDENTITY) && !dba.supportsOption(DatastoreAdapter.IDENTITY_COLUMNS)) {
                        throw new NucleusException(Localiser.msg("057020", cmd.getFullClassName(), fmd.getName())).setFatal();
                    }
                }
            }
        }
    }
    // No Primary Key defined, so search for superclass or handle datastore id
    if (!hasPrimaryKeyInThisClass) {
        if (cmd.getIdentityType() == IdentityType.APPLICATION) {
            // application-identity
            // TODO rewrite this to just use metadata to get the PKs of the superclass(es). Any reason why not?
            DatastoreClass superTable = storeMgr.getDatastoreClass(cmd.getPersistableSuperclass(), clr);
            if (isPKInitialized()) {
                // The above call could have triggered a population of the PK here
                return;
            }
            if (superTable == null && cmd.getPersistableSuperclass() != null) {
                // The superclass doesn't have its own table, so keep going up til we find the next table
                AbstractClassMetaData supercmd = cmd.getSuperAbstractClassMetaData();
                while (true) {
                    if (supercmd.getPersistableSuperclass() == null) {
                        break;
                    }
                    superTable = storeMgr.getDatastoreClass(supercmd.getPersistableSuperclass(), clr);
                    if (isPKInitialized()) {
                        // The above call could have triggered a population of the PK here
                        return;
                    }
                    if (superTable != null) {
                        break;
                    }
                    supercmd = supercmd.getSuperAbstractClassMetaData();
                    if (supercmd == null) {
                        break;
                    }
                }
            }
            if (superTable != null) {
                // Superclass has a table so copy its PK mappings
                ColumnMetaDataContainer colContainer = null;
                if (cmd.getInheritanceMetaData() != null) {
                    // Try via <inheritance><join>...</join></inheritance>
                    colContainer = cmd.getInheritanceMetaData().getJoinMetaData();
                }
                if (colContainer == null) {
                    // Try via <primary-key>...</primary-key>
                    colContainer = cmd.getPrimaryKeyMetaData();
                }
                addApplicationIdUsingClassTableId(colContainer, superTable, clr, cmd);
            } else {
                // No supertable to copy, so find superclass with PK fields and create new mappings and columns
                AbstractClassMetaData pkCmd = getClassWithPrimaryKeyForClass(cmd.getSuperAbstractClassMetaData(), clr);
                if (pkCmd != null) {
                    // TODO Just use cmd.getPKMemberPositions to avoid iteration to find PKs
                    pkMappings = new JavaTypeMapping[pkCmd.getNoOfPrimaryKeyMembers()];
                    pkFieldNum = 0;
                    fieldCount = pkCmd.getNoOfInheritedManagedMembers() + pkCmd.getNoOfManagedMembers();
                    for (int absFieldNum = 0; absFieldNum < fieldCount; ++absFieldNum) {
                        AbstractMemberMetaData fmd = pkCmd.getMetaDataForManagedMemberAtAbsolutePosition(absFieldNum);
                        if (fmd.isPrimaryKey()) {
                            AbstractMemberMetaData overriddenFmd = cmd.getOverriddenMember(fmd.getName());
                            if (overriddenFmd != null) {
                                // PK field is overridden so use the overriding definition
                                fmd = overriddenFmd;
                            } else {
                                AbstractClassMetaData thisCmd = cmd;
                                while (thisCmd.getSuperAbstractClassMetaData() != null && thisCmd.getSuperAbstractClassMetaData() != pkCmd) {
                                    thisCmd = thisCmd.getSuperAbstractClassMetaData();
                                    overriddenFmd = thisCmd.getOverriddenMember(fmd.getName());
                                    if (overriddenFmd != null) {
                                        // PK field is overridden so use the overriding definition
                                        fmd = overriddenFmd;
                                        break;
                                    }
                                }
                            }
                            if (fmd.getPersistenceModifier() == FieldPersistenceModifier.PERSISTENT) {
                                membersToAdd[pkFieldNum++] = fmd;
                            } else if (fmd.getPersistenceModifier() != FieldPersistenceModifier.TRANSACTIONAL) {
                                throw new NucleusException(Localiser.msg("057006", fmd.getName())).setFatal();
                            }
                        }
                    }
                }
            }
        } else if (cmd.getIdentityType() == IdentityType.DATASTORE) {
            // datastore-identity
            ColumnMetaData colmd = null;
            if (cmd.getIdentityMetaData() != null && cmd.getIdentityMetaData().getColumnMetaData() != null) {
                // Try via <datastore-identity>...</datastore-identity>
                colmd = cmd.getIdentityMetaData().getColumnMetaData();
            }
            if (colmd == null) {
                // Try via <primary-key>...</primary-key>
                if (cmd.getPrimaryKeyMetaData() != null && cmd.getPrimaryKeyMetaData().getColumnMetaData() != null && cmd.getPrimaryKeyMetaData().getColumnMetaData().length > 0) {
                    colmd = cmd.getPrimaryKeyMetaData().getColumnMetaData()[0];
                }
            }
            addDatastoreId(colmd, null, cmd);
        } else if (cmd.getIdentityType() == IdentityType.NONDURABLE) {
        // Do nothing since no identity!
        }
    }
    // add field mappings in the end, so we compute all columns after the post initialize
    for (int i = 0; i < membersToAdd.length; i++) {
        if (membersToAdd[i] != null) {
            try {
                DatastoreClass datastoreClass = getStoreManager().getDatastoreClass(membersToAdd[i].getType().getName(), clr);
                if (datastoreClass.getIdMapping() == null) {
                    throw new NucleusException("Unsupported relationship with field " + membersToAdd[i].getFullFieldName()).setFatal();
                }
            } catch (NoTableManagedException ex) {
            // do nothing
            }
            JavaTypeMapping fieldMapping = storeMgr.getMappingManager().getMapping(this, membersToAdd[i], clr, FieldRole.ROLE_FIELD);
            addMemberMapping(fieldMapping);
            pkMappings[i] = fieldMapping;
        }
    }
    initializeIDMapping();
    state = TABLE_STATE_PK_INITIALIZED;
}
Also used : ColumnMetaDataContainer(org.datanucleus.metadata.ColumnMetaDataContainer) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusException(org.datanucleus.exceptions.NucleusException) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) NoTableManagedException(org.datanucleus.store.rdbms.exceptions.NoTableManagedException) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData)

Aggregations

NoTableManagedException (org.datanucleus.store.rdbms.exceptions.NoTableManagedException)10 ArrayList (java.util.ArrayList)5 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)5 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)5 ColumnMetaData (org.datanucleus.metadata.ColumnMetaData)4 ForeignKey (org.datanucleus.store.rdbms.key.ForeignKey)4 Collection (java.util.Collection)3 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)3 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)3 PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)3 ReferenceMapping (org.datanucleus.store.rdbms.mapping.java.ReferenceMapping)3 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)3 Iterator (java.util.Iterator)2 ColumnMetaDataContainer (org.datanucleus.metadata.ColumnMetaDataContainer)2 ForeignKeyMetaData (org.datanucleus.metadata.ForeignKeyMetaData)2 HashSet (java.util.HashSet)1 ApiAdapter (org.datanucleus.api.ApiAdapter)1 NucleusException (org.datanucleus.exceptions.NucleusException)1 StoreData (org.datanucleus.store.StoreData)1 DuplicateColumnException (org.datanucleus.store.rdbms.exceptions.DuplicateColumnException)1