use of org.datanucleus.store.rdbms.key.ForeignKey in project datanucleus-rdbms by datanucleus.
the class ClassTable method addExpectedForeignKeysForEmbeddedPCField.
/**
* Convenience method to add the expected FKs for an embedded PC field.
* @param foreignKeys The list of FKs to add the FKs to
* @param autoMode Whether operating in "auto-mode" where DataNucleus can create its own FKs
* @param clr ClassLoader resolver
* @param embeddedMapping The embedded PC mapping
*/
private void addExpectedForeignKeysForEmbeddedPCField(List foreignKeys, boolean autoMode, ClassLoaderResolver clr, EmbeddedPCMapping embeddedMapping) {
for (int i = 0; i < embeddedMapping.getNumberOfJavaTypeMappings(); i++) {
JavaTypeMapping embFieldMapping = embeddedMapping.getJavaTypeMapping(i);
if (embFieldMapping instanceof EmbeddedPCMapping) {
// Nested embedded PC so add the FKs for that
addExpectedForeignKeysForEmbeddedPCField(foreignKeys, autoMode, clr, (EmbeddedPCMapping) embFieldMapping);
} else {
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);
}
}
}
}
}
use of org.datanucleus.store.rdbms.key.ForeignKey in project datanucleus-rdbms by datanucleus.
the class ClassTable method getForeignKeyForForeignKeyMetaData.
/**
* Convenience method to create a FK for the specified ForeignKeyMetaData.
* Used for foreign-keys specified at <class> level.
* @param fkmd ForeignKey MetaData
* @return The ForeignKey
*/
private ForeignKey getForeignKeyForForeignKeyMetaData(ForeignKeyMetaData fkmd) {
if (fkmd == null) {
return null;
}
// Create the ForeignKey base details
ForeignKey fk = new ForeignKey(dba, fkmd.isDeferred());
fk.setForMetaData(fkmd);
if (fkmd.getFkDefinitionApplies()) {
// User-defined FK definition should be used
return fk;
}
// Find the target of the foreign-key
AbstractClassMetaData acmd = cmd;
if (fkmd.getTable() == null) {
// Can't create a FK if we don't know where it goes to
NucleusLogger.DATASTORE_SCHEMA.warn(Localiser.msg("058105", acmd.getFullClassName()));
return null;
}
DatastoreIdentifier tableId = storeMgr.getIdentifierFactory().newTableIdentifier(fkmd.getTable());
ClassTable refTable = (ClassTable) storeMgr.getDatastoreClass(tableId);
if (refTable == null) {
// TODO Go to the datastore and query for this table to get the columns of the PK
NucleusLogger.DATASTORE_SCHEMA.warn(Localiser.msg("058106", acmd.getFullClassName(), fkmd.getTable()));
return null;
}
PrimaryKey pk = refTable.getPrimaryKey();
List targetCols = pk.getColumns();
// Generate the columns for the source of the foreign-key
List<Column> sourceCols = new ArrayList<>();
ColumnMetaData[] colmds = fkmd.getColumnMetaData();
String[] memberNames = fkmd.getMemberNames();
if (colmds != null && colmds.length > 0) {
// FK specified via <column>
for (int i = 0; i < colmds.length; i++) {
// Find the column and add to the source columns for the FK
DatastoreIdentifier colId = storeMgr.getIdentifierFactory().newColumnIdentifier(colmds[i].getName());
Column sourceCol = columnsByIdentifier.get(colId);
if (sourceCol == null) {
NucleusLogger.DATASTORE_SCHEMA.warn(Localiser.msg("058107", acmd.getFullClassName(), fkmd.getTable(), colmds[i].getName(), toString()));
return null;
}
sourceCols.add(sourceCol);
}
} else if (memberNames != null && memberNames.length > 0) {
// FK specified via <field>
for (int i = 0; i < memberNames.length; i++) {
// Find the metadata for the actual field with the same name as this "foreign-key" field
// and add all columns to the source columns for the FK
AbstractMemberMetaData realMmd = getMetaDataForMember(memberNames[i]);
if (realMmd == null) {
throw new NucleusUserException("Table " + this + " has foreign-key specified on member " + memberNames[i] + " but that member does not exist in the class that this table represents");
}
JavaTypeMapping fieldMapping = memberMappingsMap.get(realMmd);
int countCols = fieldMapping.getNumberOfColumnMappings();
for (int j = 0; j < countCols; j++) {
// Add each column of this field to the FK definition
sourceCols.add(fieldMapping.getColumnMapping(j).getColumn());
}
}
}
if (sourceCols.size() != targetCols.size()) {
// Different number of cols in this table and target table
NucleusLogger.DATASTORE_SCHEMA.warn(Localiser.msg("058108", acmd.getFullClassName(), fkmd.getTable(), "" + sourceCols.size(), "" + targetCols.size()));
}
// Add all column mappings to the ForeignKey
if (sourceCols.size() > 0) {
for (int i = 0; i < sourceCols.size(); i++) {
Column source = sourceCols.get(i);
String targetColName = (colmds != null && colmds[i] != null) ? colmds[i].getTarget() : null;
// Default to matching via the natural order
Column target = (Column) targetCols.get(i);
if (targetColName != null) {
// User has specified the target column for this col so try it in our target list
for (int j = 0; j < targetCols.size(); j++) {
Column targetCol = (Column) targetCols.get(j);
if (targetCol.getIdentifier().getName().equalsIgnoreCase(targetColName)) {
// Found the required column
target = targetCol;
break;
}
}
}
fk.addColumn(source, target);
}
}
return fk;
}
use of org.datanucleus.store.rdbms.key.ForeignKey in project datanucleus-rdbms by datanucleus.
the class ClassTable 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();
// Auto mode allows us to decide which FKs are needed as well as using what is in the users MetaData.
boolean autoMode = false;
if (storeMgr.getStringProperty(RDBMSPropertyNames.PROPERTY_RDBMS_CONSTRAINT_CREATE_MODE).equals("DataNucleus")) {
autoMode = true;
}
ArrayList<ForeignKey> foreignKeys = new ArrayList<>();
// Check each field for FK requirements (user-defined, or required)
// <field><foreign-key>...</foreign-key></field>
Set memberNumbersSet = memberMappingsMap.keySet();
Iterator iter = memberNumbersSet.iterator();
while (iter.hasNext()) {
AbstractMemberMetaData mmd = (AbstractMemberMetaData) iter.next();
JavaTypeMapping memberMapping = memberMappingsMap.get(mmd);
if (memberMapping instanceof EmbeddedPCMapping) {
EmbeddedPCMapping embMapping = (EmbeddedPCMapping) memberMapping;
addExpectedForeignKeysForEmbeddedPCField(foreignKeys, autoMode, clr, embMapping);
} else {
if (ClassUtils.isReferenceType(mmd.getType()) && memberMapping 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(memberMapping, mmd, autoMode, storeMgr, clr);
foreignKeys.addAll(fks);
} else if (storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(mmd.getType(), clr) != null && memberMapping.getNumberOfColumnMappings() > 0 && memberMapping 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(memberMapping, mmd, autoMode, storeMgr, clr);
if (fk != null) {
// Check for dups (can happen if we override a persistent property for 1-1/N-1 in a subclass)
boolean exists = false;
for (ForeignKey theFK : foreignKeys) {
if (theFK.isEqual(fk)) {
exists = true;
break;
}
}
if (!exists) {
foreignKeys.add(fk);
}
}
}
}
}
// FK from id column(s) to id column(s) of superclass, as specified by
// <inheritance><join><foreign-key ...></join></inheritance>
ForeignKeyMetaData idFkmd = (cmd.getInheritanceMetaData().getJoinMetaData() != null) ? cmd.getInheritanceMetaData().getJoinMetaData().getForeignKeyMetaData() : null;
if (supertable != null && (autoMode || (idFkmd != null && idFkmd.getDeleteAction() != ForeignKeyAction.NONE))) {
ForeignKey fk = new ForeignKey(getIdMapping(), dba, supertable, false);
if (idFkmd != null && idFkmd.getName() != null) {
fk.setName(idFkmd.getName());
}
foreignKeys.add(0, fk);
}
// Add any user-required FKs for the class as a whole
// <class><foreign-key>...</foreign-key></field>
Iterator<AbstractClassMetaData> cmdIter = managedClassMetaData.iterator();
while (cmdIter.hasNext()) {
AbstractClassMetaData thisCmd = cmdIter.next();
List<ForeignKeyMetaData> fkmds = thisCmd.getForeignKeyMetaData();
if (fkmds != null) {
for (ForeignKeyMetaData fkmd : fkmds) {
ForeignKey fk = getForeignKeyForForeignKeyMetaData(fkmd);
if (fk != null) {
foreignKeys.add(fk);
}
}
}
}
Map externalFks = getExternalFkMappings();
if (!externalFks.isEmpty()) {
// 1-N FK relationships - FK to id column(s) of owner table where this is the element table and we have a FK
Collection externalFkKeys = externalFks.entrySet();
Iterator<Map.Entry<AbstractMemberMetaData, JavaTypeMapping>> externalFkKeysIter = externalFkKeys.iterator();
while (externalFkKeysIter.hasNext()) {
Map.Entry<AbstractMemberMetaData, JavaTypeMapping> entry = externalFkKeysIter.next();
AbstractMemberMetaData fmd = entry.getKey();
DatastoreClass referencedTable = storeMgr.getDatastoreClass(fmd.getAbstractClassMetaData().getFullClassName(), clr);
if (referencedTable != null) {
// Take <foreign-key> from either <field> or <element>
ForeignKeyMetaData fkmd = fmd.getForeignKeyMetaData();
if (fkmd == null && fmd.getElementMetaData() != null) {
fkmd = fmd.getElementMetaData().getForeignKeyMetaData();
}
if ((fkmd != null && fkmd.getDeleteAction() != ForeignKeyAction.NONE) || autoMode) {
// Either has been specified by user, or using autoMode, so add FK
JavaTypeMapping fkMapping = entry.getValue();
ForeignKey fk = new ForeignKey(fkMapping, dba, referencedTable, true);
// Does nothing when no FK MetaData
fk.setForMetaData(fkmd);
if (!foreignKeys.contains(fk)) {
// Only add when not already present (in the case of shared FKs there can be dups here)
foreignKeys.add(fk);
}
}
}
}
}
return foreignKeys;
}
use of org.datanucleus.store.rdbms.key.ForeignKey in project datanucleus-rdbms by datanucleus.
the class PersistableJoinTable 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(mmd.getClassName(true), clr);
if (referencedTable != null) {
// Single owner table, so add a single FK to the owner as appropriate
// Take <foreign-key> from <join>
ForeignKey fk = null;
ForeignKeyMetaData fkmd = null;
if (mmd.getJoinMetaData() != null) {
fkmd = mmd.getJoinMetaData().getForeignKeyMetaData();
}
if (fkmd != null || autoMode) {
fk = new ForeignKey(ownerMapping, dba, referencedTable, true);
fk.setForMetaData(fkmd);
}
if (fk != null) {
foreignKeys.add(fk);
}
}
// FK from join table to related table
referencedTable = storeMgr.getDatastoreClass(mmd.getTypeName(), clr);
if (referencedTable != null) {
// Take <foreign-key> from <field>
ForeignKey fk = null;
ForeignKeyMetaData fkmd = mmd.getForeignKeyMetaData();
if (fkmd != null || autoMode) {
fk = new ForeignKey(relatedMapping, dba, referencedTable, true);
fk.setForMetaData(fkmd);
}
if (fk != null) {
foreignKeys.add(fk);
}
}
} catch (NoTableManagedException e) {
// expected when no table exists
}
return foreignKeys;
}
use of org.datanucleus.store.rdbms.key.ForeignKey in project datanucleus-rdbms by datanucleus.
the class MapTable method getExpectedForeignKeys.
/**
* Accessor for the expected foreign keys for this table.
* @param clr The ClassLoaderResolver
* @return The expected foreign keys.
*/
@Override
public List getExpectedForeignKeys(ClassLoaderResolver clr) {
assertIsInitialized();
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) {
// Take <foreign-key> from <join>
ForeignKeyMetaData fkmd = null;
if (mmd.getJoinMetaData() != null) {
fkmd = mmd.getJoinMetaData().getForeignKeyMetaData();
}
if (fkmd != null || autoMode) {
ForeignKey fk = new ForeignKey(ownerMapping, dba, referencedTable, true);
fk.setForMetaData(fkmd);
foreignKeys.add(fk);
}
}
if (!isSerialisedValuePC()) {
if (isEmbeddedValuePC()) {
// Add any FKs for the fields of the (embedded) value
EmbeddedValuePCMapping embMapping = (EmbeddedValuePCMapping) valueMapping;
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 (mmd.getMap().valueIsPersistent()) {
// FK from join table to value table
referencedTable = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr);
if (referencedTable != null) {
// Take <foreign-key> from <value>
ForeignKeyMetaData fkmd = null;
if (mmd.getValueMetaData() != null) {
fkmd = mmd.getValueMetaData().getForeignKeyMetaData();
}
if (fkmd != null || autoMode) {
ForeignKey fk = new ForeignKey(valueMapping, dba, referencedTable, true);
fk.setForMetaData(fkmd);
foreignKeys.add(fk);
}
}
}
}
if (!isSerialisedKeyPC()) {
if (isEmbeddedKeyPC()) {
// Add any FKs for the fields of the (embedded) key
EmbeddedKeyPCMapping embMapping = (EmbeddedKeyPCMapping) keyMapping;
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 (mmd.getMap().keyIsPersistent()) {
// FK from join table to key table
referencedTable = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
if (referencedTable != null) {
// Take <foreign-key> from <key>
ForeignKeyMetaData fkmd = null;
if (mmd.getKeyMetaData() != null) {
fkmd = mmd.getKeyMetaData().getForeignKeyMetaData();
}
if (fkmd != null || autoMode) {
ForeignKey fk = new ForeignKey(keyMapping, dba, referencedTable, true);
fk.setForMetaData(fkmd);
foreignKeys.add(fk);
}
}
}
}
} catch (NoTableManagedException e) {
// expected when no table exists
}
return foreignKeys;
}
Aggregations