use of org.datanucleus.store.rdbms.schema.ForeignKeyInfo in project datanucleus-rdbms by datanucleus.
the class TableImpl method dropConstraints.
/**
* Method to drop the constraints for the table from the datastore.
* @param conn The JDBC Connection
* @throws SQLException Thrown when an error occurs in the JDBC call.
*/
public void dropConstraints(Connection conn) throws SQLException {
assertIsInitialized();
boolean drop_using_constraint = dba.supportsOption(DatastoreAdapter.ALTER_TABLE_DROP_CONSTRAINT_SYNTAX);
boolean drop_using_foreign_key = dba.supportsOption(DatastoreAdapter.ALTER_TABLE_DROP_FOREIGN_KEY_CONSTRAINT);
if (!drop_using_constraint && !drop_using_foreign_key) {
return;
}
// There's no need to drop indices; we assume they'll go away quietly when the table is dropped.
Set<String> fkNames = new HashSet<>();
StoreSchemaHandler handler = storeMgr.getSchemaHandler();
RDBMSTableFKInfo fkInfo = (RDBMSTableFKInfo) handler.getSchemaData(conn, "foreign-keys", new Object[] { this });
Iterator iter = fkInfo.getChildren().iterator();
while (iter.hasNext()) {
// JDBC drivers can return null names for foreign keys, so we then skip the DROP CONSTRAINT.
ForeignKeyInfo fki = (ForeignKeyInfo) iter.next();
String fkName = (String) fki.getProperty("fk_name");
if (fkName != null) {
fkNames.add(fkName);
}
}
int numFKs = fkNames.size();
if (numFKs > 0) {
if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled()) {
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("058102", "" + numFKs, this));
}
iter = fkNames.iterator();
IdentifierFactory idFactory = storeMgr.getIdentifierFactory();
Statement stmt = conn.createStatement();
try {
while (iter.hasNext()) {
String constraintName = (String) iter.next();
String stmtText = null;
if (drop_using_constraint) {
stmtText = "ALTER TABLE " + toString() + " DROP CONSTRAINT " + idFactory.getIdentifierInAdapterCase(constraintName);
} else {
stmtText = "ALTER TABLE " + toString() + " DROP FOREIGN KEY " + idFactory.getIdentifierInAdapterCase(constraintName);
}
executeDdlStatement(stmt, stmtText);
}
} finally {
stmt.close();
}
}
}
use of org.datanucleus.store.rdbms.schema.ForeignKeyInfo in project tests by datanucleus.
the class SchemaHandlerTest method testForeignKeyRetrieval.
/**
* Test of the retrieval of FKs.
*/
public void testForeignKeyRetrieval() {
addClassesToSchema(new Class[] { SchemaClass1.class, SchemaClass2.class });
PersistenceManager pm = pmf.getPersistenceManager();
RDBMSStoreManager databaseMgr = (RDBMSStoreManager) storeMgr;
// Retrieve the table for SchemaClass1
ClassLoaderResolver clr = storeMgr.getNucleusContext().getClassLoaderResolver(null);
DatastoreClass table1 = databaseMgr.getDatastoreClass(SchemaClass1.class.getName(), clr);
// Check for the FK using the schema handler
StoreSchemaHandler handler = databaseMgr.getSchemaHandler();
Connection con = (Connection) databaseMgr.getConnectionManager().getConnection(((JDOPersistenceManager) pm).getExecutionContext()).getConnection();
RDBMSTableFKInfo fkInfo = (RDBMSTableFKInfo) handler.getSchemaData(con, "foreign-keys", new Object[] { table1 });
// Expecting single FK between SchemaClass1.other and SchemaClass2
assertEquals("Number of FKs for table " + table1 + " is wrong", 1, fkInfo.getNumberOfChildren());
// Check the FK details
ForeignKeyInfo fk = (ForeignKeyInfo) fkInfo.getChild(0);
assertEquals("FK Name is wrong", "TABLE1_FK1", ((String) fk.getProperty("fk_name")).toUpperCase());
assertEquals("PK Table Name is wrong", "SCHEMA_TABLE_2", ((String) fk.getProperty("pk_table_name")).toUpperCase());
assertEquals("FK Table Name is wrong", "SCHEMA_TABLE_1", ((String) fk.getProperty("fk_table_name")).toUpperCase());
assertEquals("PK Column Name is wrong", "TABLE2_ID", ((String) fk.getProperty("pk_column_name")).toUpperCase());
assertEquals("FK Column Name is wrong", "OTHER_ID", ((String) fk.getProperty("fk_column_name")).toUpperCase());
}
use of org.datanucleus.store.rdbms.schema.ForeignKeyInfo 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, "foreign-keys", 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.schema.ForeignKeyInfo in project datanucleus-rdbms by datanucleus.
the class PostgreSQLAdapter method newFKInfo.
/**
* Method to return ForeignKeyInfo for the current row of the ResultSet which will have been
* obtained from a call to DatabaseMetaData.getImportedKeys() or DatabaseMetaData.getExportedKeys().
* @param rs The result set returned from DatabaseMetaData.get??portedKeys()
* @return The foreign key info
*/
public ForeignKeyInfo newFKInfo(ResultSet rs) {
org.datanucleus.store.rdbms.schema.ForeignKeyInfo info = super.newFKInfo(rs);
// PostgreSQL sometimes return strange FK info. This checks for the FK name with various
// extraneous info on the end with a separator of \000.
String fkName = (String) info.getProperty("fk_name");
int firstBackslashIdx = fkName.indexOf('\\');
if (firstBackslashIdx > 0) {
info.addProperty("fk_name", fkName.substring(0, firstBackslashIdx));
}
return info;
}
Aggregations