sequelize / sequelize/sequelize

getForeignKeyReferencesForTable for postgres is not filtering by schema

Open
#16,445 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

v6
Dominant language
TypeScript
Stars
30.4k
Forks
4.3k
Avg merge
1d 6h
Merged PRs (30d)
68

Description

Issue Creation Checklist

  • I understand that my issue will be automatically closed if I don't fill in the requested information
  • I have read the contribution guidelines

Bug Description

The postgres query interface method getForeignKeyReferencesForTable is not passing the schema parameter when calling this.queryGenerator.getForeignKeyReferencesQuery.

async getForeignKeyReferencesForTable(table, options) {
    const queryOptions = __spreadProps(__spreadValues({}, options), {
      type: QueryTypes.FOREIGNKEYS
    });
    const query = this.queryGenerator.getForeignKeyReferencesQuery(table.tableName || table, this.sequelize.config.database);
    const result = await this.sequelize.query(query, queryOptions);
    return result.map((fkMeta) => {
      const _a = Utils.camelizeObjectKeys(fkMeta), { initiallyDeferred, isDeferrable } = _a, remaining = __objRest(_a, ["initiallyDeferred", "isDeferrable"]);
      return __spreadProps(__spreadValues({}, remaining), {
        deferrable: isDeferrable === "NO" ? Deferrable.NOT : initiallyDeferred === "NO" ? Deferrable.INITIALLY_IMMEDIATE : Deferrable.INITIALLY_DEFERRED
      });
    });
}

This causes calls to sequelize.sync({force: true, schema: 's1'}) to fail or incorrectly attempt to drop constraints that belong to another table of same name in a different schema.

Reproducible Example

Here is the scenario I have:

  • Consider that in a postgres database we have two schemas: public and s1
  • Both on public schema and s1 schema I have the table abc
  • public.abc has the foreign key constraint abc_organization_id_fkey to another table in the same schema
  • s1.abc is a completely different table and does not have the foreign key constraint abc_organization_id_fkey`
  • We define a model for s1.abc and set the correct schema
  • Calling sequelize.sync({force: true, schema: 's1'}) fails with sequelize trying to drop a foreign key constraint that does not exists in the model for s1.abc
What do you expect to happen?

Calling queryInterface.getForeignKeyReferencesForTable should set the schema parameter for queryGenerator.getForeignKeyReferencesQuery if it is defined.

const query = this.queryGenerator.getForeignKeyReferencesQuery(table.tableName || table, this.sequelize.config.database, table?.schema);

So the generated SELECT will filter by schema and only return foreign keys that make sense to that table

What is actually happening?

The generated query is not filtering by schema and thus returns all foreign key constraints for any table of same in any schema:

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 = 'abc' AND tc.table_catalog = 'test'
Environment
  • Sequelize version: 6.32.1
  • Node.js version: v18.12.1
  • If TypeScript related: TypeScript version:
  • Database & Version: PostgresSQL 12
  • Connector library & Version: pg 8.11.1

Would you be willing to resolve this issue by submitting a Pull Request?

  • Yes, I have the time and I know how to start.
  • Yes, I have the time but I will need guidance.
  • No, I don't have the time, but my company or I are supporting Sequelize through donations on OpenCollective.
  • No, I don't have the time, and I understand that I will need to wait until someone from the community or maintainers is interested in resolving my issue.

Indicate your interest in the resolution of this issue by adding the 👍 reaction. Comments such as "+1" will be removed.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the PostgreSQL QueryInterface implementation and inspect getForeignKeyReferencesForTable, especially its call to getForeignKeyReferencesQuery. Reproduce the public and s1 tables described in the issue, then verify that schema-qualified sync only returns and handles foreign keys from the selected schema.

Written by the indexing model from the issue text.

Assessment

Tech stack
postgresql, typescript
Domain
databases
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.