use of org.datanucleus.store.rdbms.key.ForeignKey in project datanucleus-rdbms by datanucleus.
the class ElementContainerTable method getForeignKeyToElement.
/**
* Convenience method to generate a ForeignKey from this join table to an element table using the specified mapping.
* @param elementTable The element table
* @param autoMode Whether we are in auto mode (where we generate the keys regardless of what the metadata says)
* @param m The mapping to the element table
* @return The ForeignKey
*/
protected ForeignKey getForeignKeyToElement(DatastoreClass elementTable, boolean autoMode, JavaTypeMapping m) {
ForeignKey fk = null;
if (elementTable != null) {
// Take <foreign-key> from either <field> or <element>
ForeignKeyMetaData fkmd = mmd.getForeignKeyMetaData();
if (fkmd == null && mmd.getElementMetaData() != null) {
fkmd = mmd.getElementMetaData().getForeignKeyMetaData();
}
// TODO If in autoMode and there are multiple possible element tables then don't create a FK
if (fkmd != null || autoMode) {
fk = new ForeignKey(m, dba, elementTable, true);
fk.setForMetaData(fkmd);
}
}
return fk;
}
use of org.datanucleus.store.rdbms.key.ForeignKey in project datanucleus-rdbms by datanucleus.
the class SecondaryTable method getExpectedForeignKeys.
/**
* Accessor for the expected foreign keys for this table.
* @return The expected foreign keys.
*/
protected List<ForeignKey> getExpectedForeignKeys() {
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;
}
// Add FK back to the primary table unless requested not to
List<ForeignKey> foreignKeys = new ArrayList<>();
ForeignKeyMetaData fkmd = joinMetaData != null ? joinMetaData.getForeignKeyMetaData() : null;
if (autoMode || (fkmd != null && fkmd.getDeleteAction() != ForeignKeyAction.NONE)) {
ForeignKey fk = new ForeignKey(getIdMapping(), dba, primaryTable, fkmd != null && fkmd.isDeferred() ? true : false);
if (fkmd != null && fkmd.getName() != null) {
fk.setName(fkmd.getName());
}
foreignKeys.add(0, fk);
}
return foreignKeys;
}
use of org.datanucleus.store.rdbms.key.ForeignKey in project datanucleus-rdbms by datanucleus.
the class TableImpl method getSQLAddFKStatements.
/**
* Get SQL statements to add expected Foreign Keys that are not yet at the table.
* If the returned Map is empty, the current FK setup is correct.
* @param actualForeignKeysByName Actual Map of foreign keys
* @param clr The ClassLoaderResolver
* @return a Map with the SQL statements
*/
protected Map<String, String> getSQLAddFKStatements(Map actualForeignKeysByName, ClassLoaderResolver clr) {
assertIsInitialized();
Map<String, String> stmtsByFKName = new HashMap<>();
List<ForeignKey> expectedForeignKeys = getExpectedForeignKeys(clr);
Iterator<ForeignKey> i = expectedForeignKeys.iterator();
int n = 1;
IdentifierFactory idFactory = storeMgr.getIdentifierFactory();
while (i.hasNext()) {
ForeignKey fk = i.next();
if (!actualForeignKeysByName.containsValue(fk)) {
// If no name assigned, make one up
if (fk.getName() == null) {
// Use the ForeignKeyIdentifier to generate the name
DatastoreIdentifier fkName;
do {
fkName = idFactory.newForeignKeyIdentifier(this, n++);
} while (actualForeignKeysByName.containsKey(fkName));
fk.setName(fkName.getName());
}
String stmtText = dba.getAddForeignKeyStatement(fk, idFactory);
if (stmtText != null) {
stmtsByFKName.put(fk.getName(), stmtText);
}
}
}
return stmtsByFKName;
}
use of org.datanucleus.store.rdbms.key.ForeignKey in project datanucleus-rdbms by datanucleus.
the class TableImpl method getExistingForeignKeys.
/**
* Accessor for the foreign keys for this table.
* @param conn The JDBC Connection
* @return Map of foreign keys
* @throws SQLException Thrown when an error occurs in the JDBC call.
*/
private Map<DatastoreIdentifier, ForeignKey> getExistingForeignKeys(Connection conn) throws SQLException {
Map<DatastoreIdentifier, ForeignKey> foreignKeysByName = new HashMap<>();
if (tableExistsInDatastore(conn)) {
StoreSchemaHandler handler = storeMgr.getSchemaHandler();
IdentifierFactory idFactory = storeMgr.getIdentifierFactory();
RDBMSTableFKInfo tableFkInfo = (RDBMSTableFKInfo) handler.getSchemaData(conn, RDBMSSchemaHandler.TYPE_FKS, new Object[] { this });
Iterator fksIter = tableFkInfo.getChildren().iterator();
while (fksIter.hasNext()) {
ForeignKeyInfo fkInfo = (ForeignKeyInfo) fksIter.next();
DatastoreIdentifier fkIdentifier;
String fkName = (String) fkInfo.getProperty("fk_name");
if (fkName == null) {
fkIdentifier = idFactory.newForeignKeyIdentifier(this, foreignKeysByName.size());
} else {
fkIdentifier = idFactory.newIdentifier(IdentifierType.FOREIGN_KEY, fkName);
}
short deferrability = ((Short) fkInfo.getProperty("deferrability")).shortValue();
boolean initiallyDeferred = deferrability == DatabaseMetaData.importedKeyInitiallyDeferred;
ForeignKey fk = foreignKeysByName.get(fkIdentifier);
if (fk == null) {
fk = new ForeignKey(dba, initiallyDeferred);
fk.setName(fkIdentifier.getName());
foreignKeysByName.put(fkIdentifier, fk);
}
// Find the referenced table from the provided name
String pkTableName = (String) fkInfo.getProperty("pk_table_name");
DatastoreIdentifier refTableId = idFactory.newTableIdentifier(pkTableName);
DatastoreClass refTable = storeMgr.getDatastoreClass(refTableId);
if (refTable == null) {
// Try with same catalog/schema as this table since some JDBC don't provide this info
if (getSchemaName() != null) {
refTableId.setSchemaName(getSchemaName());
}
if (getCatalogName() != null) {
refTableId.setCatalogName(getCatalogName());
}
refTable = storeMgr.getDatastoreClass(refTableId);
}
if (refTable != null) {
String fkColumnName = (String) fkInfo.getProperty("fk_column_name");
String pkColumnName = (String) fkInfo.getProperty("pk_column_name");
DatastoreIdentifier colName = idFactory.newIdentifier(IdentifierType.COLUMN, fkColumnName);
DatastoreIdentifier refColName = idFactory.newIdentifier(IdentifierType.COLUMN, pkColumnName);
Column col = columnsByIdentifier.get(colName);
Column refCol = refTable.getColumn(refColName);
if (col != null && refCol != null) {
fk.addColumn(col, refCol);
} else {
// TODO throw exception?
}
} else {
NucleusLogger.DATASTORE_SCHEMA.warn("Retrieved ForeignKey from datastore for table=" + toString() + " referencing table " + pkTableName + " but not found internally. Is there some catalog/schema or quoting causing problems?");
}
}
}
return foreignKeysByName;
}
use of org.datanucleus.store.rdbms.key.ForeignKey in project datanucleus-rdbms by datanucleus.
the class TableUtils method getForeignKeyForPCField.
/**
* Convenience method to add a foreign key for a PC field.
* Adds a FK from the PC column(s) in this table to the ID columns in the PC's table.
* @param fieldMapping Mapping for the PC field
* @param mmd MetaData for the field
* @param autoMode Whether we are in auto-create mode
* @param storeMgr Store Manager
* @param clr ClassLoader resolver
* @return The ForeignKey (if any)
*/
public static ForeignKey getForeignKeyForPCField(JavaTypeMapping fieldMapping, AbstractMemberMetaData mmd, boolean autoMode, RDBMSStoreManager storeMgr, ClassLoaderResolver clr) {
DatastoreClass referencedTable = storeMgr.getDatastoreClass(mmd.getTypeName(), clr);
if (referencedTable == null) {
// PC type uses subclass-table
AbstractClassMetaData refCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(mmd.getType(), clr);
if (refCmd != null) {
AbstractClassMetaData[] refCmds = storeMgr.getClassesManagingTableForClass(refCmd, clr);
if (refCmds != null && refCmds.length == 1) {
referencedTable = storeMgr.getDatastoreClass(refCmds[0].getFullClassName(), clr);
} else {
// "subclass-table" with more than 1 subclass with table (not supported)
}
}
}
if (referencedTable != null) {
ForeignKeyMetaData fkmd = mmd.getForeignKeyMetaData();
if ((fkmd != null && (fkmd.getDeleteAction() != ForeignKeyAction.NONE || fkmd.getFkDefinitionApplies())) || autoMode) {
// Either has been specified by user, or using autoMode, so add FK
ForeignKey fk = new ForeignKey(fieldMapping, storeMgr.getDatastoreAdapter(), referencedTable, true);
// Does nothing when no FK MetaData
fk.setForMetaData(fkmd);
if (fkmd != null && fkmd.getName() != null) {
fk.setName(fkmd.getName());
}
return fk;
}
}
return null;
}
Aggregations