diff --git a/src/dialects/postgres/query-interface.js b/src/dialects/postgres/query-interface.js index 4dff28a6c5b5..b13fe3ec25f8 100644 --- a/src/dialects/postgres/query-interface.js +++ b/src/dialects/postgres/query-interface.js @@ -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 => { diff --git a/test/integration/sequelize/drop.test.js b/test/integration/sequelize/drop.test.js index d2794f984313..0d88f96a16d7 100644 --- a/test/integration/sequelize/drop.test.js +++ b/test/integration/sequelize/drop.test.js @@ -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(); + }); + }); }); diff --git a/test/unit/dialects/postgres/query-generator.test.js b/test/unit/dialects/postgres/query-generator.test.js index 0285d69af0bf..d3c6ed1a19fe 100644 --- a/test/unit/dialects/postgres/query-generator.test.js +++ b/test/unit/dialects/postgres/query-generator.test.js @@ -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'],