Skip to content

Commit

Permalink
fix(postgres): use schema for foreign key constrains of a table (#17099)
Browse files Browse the repository at this point in the history
Co-authored-by: Ales Menzel <ales.menzel@emplifi.io>
Co-authored-by: Rik Smale <13023439+WikiRik@users.noreply.github.com>
  • Loading branch information
3 people committed Apr 13, 2024
1 parent 7c8972f commit 6aba382
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/dialects/postgres/query-interface.js
Expand Up @@ -157,7 +157,7 @@ class PostgresQueryInterface extends QueryInterface {

// postgres needs some special treatment as those field names returned are all lowercase
// in order to keep same result with other dialects.
const query = this.queryGenerator.getForeignKeyReferencesQuery(table.tableName || table, this.sequelize.config.database);
const query = this.queryGenerator.getForeignKeyReferencesQuery(table.tableName || table, this.sequelize.config.database, table.schema);
const result = await this.sequelize.query(query, queryOptions);

return result.map(fkMeta => {
Expand Down
50 changes: 50 additions & 0 deletions test/integration/sequelize/drop.test.js
Expand Up @@ -33,4 +33,54 @@ describe('Sequelize#drop', () => {
// drop both tables
await sequelize.drop();
});

describe('with schemas', () => {
beforeEach(async () => {
await Promise.all([
sequelize.createSchema('schemaA'),
sequelize.createSchema('schemaB')
]);
});

afterEach(async () => {
await Promise.all([
sequelize.dropSchema('schemaA'),
sequelize.dropSchema('schemaB')
]);
});

it('supports schemas when dropping foreign keys for a table', async () => {
sequelize.define('schemaA_A', {}, {
tableName: 'A',
schema: 'schemaA'
});


// External tables, use sequelize interface to create them.
const schemaB_A = sequelize.define('schemaB_A', {}, {
tableName: 'A',
schema: 'schemaB'
});

const schemaB_B = sequelize.define('schemaB_B', {
BId: {
type: DataTypes.INTEGER
}
}, {
tableName: 'B',
schema: 'schemaB'
});

schemaB_A.belongsTo(schemaB_B, { foreignKey: { allowNull: false } });

await sequelize.sync();

// Assume "schemaB" models were not created by sequelize and already exist in the database.
sequelize.modelManager.removeModel(schemaB_A);
sequelize.modelManager.removeModel(schemaB_B);

// Try to drop "schemaA" table.
await sequelize.drop();
});
});
});
49 changes: 49 additions & 0 deletions test/unit/dialects/postgres/query-generator.test.js
Expand Up @@ -1206,6 +1206,55 @@ if (dialect.startsWith('postgres')) {
}
],

getForeignKeyReferencesQuery: [
{
arguments: ['myTable', 'myDatabase'],
expectation: 'SELECT ' +
'DISTINCT tc.constraint_name as constraint_name, ' +
'tc.constraint_schema as constraint_schema, ' +
'tc.constraint_catalog as constraint_catalog, ' +
'tc.table_name as table_name,' +
'tc.table_schema as table_schema,' +
'tc.table_catalog as table_catalog,' +
'tc.initially_deferred as initially_deferred,' +
'tc.is_deferrable as is_deferrable,' +
'kcu.column_name as column_name,' +
'ccu.table_schema AS referenced_table_schema,' +
'ccu.table_catalog AS referenced_table_catalog,' +
'ccu.table_name AS referenced_table_name,' +
'ccu.column_name AS referenced_column_name ' +
'FROM information_schema.table_constraints AS tc ' +
'JOIN information_schema.key_column_usage AS kcu ' +
'ON tc.constraint_name = kcu.constraint_name ' +
'JOIN information_schema.constraint_column_usage AS ccu ' +
'ON ccu.constraint_name = tc.constraint_name ' +
'WHERE constraint_type = \'FOREIGN KEY\' AND tc.table_name = \'myTable\' AND tc.table_catalog = \'myDatabase\''
},
{
arguments: ['myTable', 'myDatabase', 'mySchema'],
expectation: 'SELECT ' +
'DISTINCT tc.constraint_name as constraint_name, ' +
'tc.constraint_schema as constraint_schema, ' +
'tc.constraint_catalog as constraint_catalog, ' +
'tc.table_name as table_name,' +
'tc.table_schema as table_schema,' +
'tc.table_catalog as table_catalog,' +
'tc.initially_deferred as initially_deferred,' +
'tc.is_deferrable as is_deferrable,' +
'kcu.column_name as column_name,' +
'ccu.table_schema AS referenced_table_schema,' +
'ccu.table_catalog AS referenced_table_catalog,' +
'ccu.table_name AS referenced_table_name,' +
'ccu.column_name AS referenced_column_name ' +
'FROM information_schema.table_constraints AS tc ' +
'JOIN information_schema.key_column_usage AS kcu ' +
'ON tc.constraint_name = kcu.constraint_name ' +
'JOIN information_schema.constraint_column_usage AS ccu ' +
'ON ccu.constraint_name = tc.constraint_name ' +
'WHERE constraint_type = \'FOREIGN KEY\' AND tc.table_name = \'myTable\' AND tc.table_catalog = \'myDatabase\' AND tc.table_schema = \'mySchema\''
}
],

getForeignKeyReferenceQuery: [
{
arguments: ['myTable', 'myColumn'],
Expand Down

0 comments on commit 6aba382

Please sign in to comment.