Search in sources :

Example 1 with ForeignKeyInfo

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();
        }
    }
}
Also used : ForeignKeyInfo(org.datanucleus.store.rdbms.schema.ForeignKeyInfo) RDBMSTableFKInfo(org.datanucleus.store.rdbms.schema.RDBMSTableFKInfo) Statement(java.sql.Statement) Iterator(java.util.Iterator) StoreSchemaHandler(org.datanucleus.store.schema.StoreSchemaHandler) IdentifierFactory(org.datanucleus.store.rdbms.identifier.IdentifierFactory) HashSet(java.util.HashSet)

Example 2 with ForeignKeyInfo

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());
}
Also used : ForeignKeyInfo(org.datanucleus.store.rdbms.schema.ForeignKeyInfo) JDOPersistenceManager(org.datanucleus.api.jdo.JDOPersistenceManager) PersistenceManager(javax.jdo.PersistenceManager) RDBMSTableFKInfo(org.datanucleus.store.rdbms.schema.RDBMSTableFKInfo) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) Connection(java.sql.Connection) SchemaClass1(org.jpox.samples.rdbms.schema.SchemaClass1) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) StoreSchemaHandler(org.datanucleus.store.schema.StoreSchemaHandler) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager)

Example 3 with ForeignKeyInfo

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;
}
Also used : HashMap(java.util.HashMap) RDBMSTableFKInfo(org.datanucleus.store.rdbms.schema.RDBMSTableFKInfo) StoreSchemaHandler(org.datanucleus.store.schema.StoreSchemaHandler) ForeignKey(org.datanucleus.store.rdbms.key.ForeignKey) IdentifierFactory(org.datanucleus.store.rdbms.identifier.IdentifierFactory) ForeignKeyInfo(org.datanucleus.store.rdbms.schema.ForeignKeyInfo) DatastoreIdentifier(org.datanucleus.store.rdbms.identifier.DatastoreIdentifier) Iterator(java.util.Iterator)

Example 4 with ForeignKeyInfo

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;
}
Also used : ForeignKeyInfo(org.datanucleus.store.rdbms.schema.ForeignKeyInfo)

Aggregations

ForeignKeyInfo (org.datanucleus.store.rdbms.schema.ForeignKeyInfo)4 RDBMSTableFKInfo (org.datanucleus.store.rdbms.schema.RDBMSTableFKInfo)3 StoreSchemaHandler (org.datanucleus.store.schema.StoreSchemaHandler)3 Iterator (java.util.Iterator)2 IdentifierFactory (org.datanucleus.store.rdbms.identifier.IdentifierFactory)2 Connection (java.sql.Connection)1 Statement (java.sql.Statement)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 PersistenceManager (javax.jdo.PersistenceManager)1 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)1 JDOPersistenceManager (org.datanucleus.api.jdo.JDOPersistenceManager)1 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)1 DatastoreIdentifier (org.datanucleus.store.rdbms.identifier.DatastoreIdentifier)1 ForeignKey (org.datanucleus.store.rdbms.key.ForeignKey)1 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)1 SchemaClass1 (org.jpox.samples.rdbms.schema.SchemaClass1)1