fix(associations): use custom sourceKey/targetKey in internal belongsToMany associations by tianyk · Pull Request #18299 · sequelize/sequelize · GitHub
Skip to content

fix(associations): use custom sourceKey/targetKey in internal belongsToMany associations - #18299

Open
tianyk wants to merge 2 commits into
sequelize:v6from
tianyk:fix/btm-custom-source-key-target-key
Open

fix(associations): use custom sourceKey/targetKey in internal belongsToMany associations#18299
tianyk wants to merge 2 commits into
sequelize:v6from
tianyk:fix/btm-custom-source-key-target-key

Conversation

@tianyk

@tianyk tianyk commented Aug 6, 2026

Copy link
Copy Markdown

What does this PR do?

Fixes the internal BelongsToMany associations losing the custom sourceKey / targetKey options.

When defining belongsToMany with a custom sourceKey or targetKey (i.e. not the model primary key), the internally created associations fell back to the primary key:

  • toSource / toTarget (BelongsTo) fell back to primaryKeyAttribute instead of sourceKey / targetKey
  • manyFromSource / manyFromTarget (HasMany) fell back to the primary key instead of sourceKey / targetKey
  • the paired.toTarget branch was also missing its targetKey

oneFromSource / oneFromTarget already passed sourceKey, so this aligns the remaining internal associations with the same behavior.

Example of the bug

User.belongsToMany(Department, {
  through: SysUserDepartment,
  foreignKey: "user_id",
  otherKey: "department_code",
  targetKey: "code",
  as: "departments",
});

Including through belongsToMany.toTarget generated a join on the primary key instead of the custom key:

-- before
LEFT OUTER JOIN `Departments` AS `Department` ON `SysUserDepartment`.`department_code` = `Department`.`id`;
-- after
LEFT OUTER JOIN `Departments` AS `Department` ON `SysUserDepartment`.`department_code` = `Department`.`code`;

Related issue

Related to #18256 (custom sourceKey/targetKey being dropped in some code paths; this PR fixes the internal-association code path on the v6 branch).

Test plan

Added a unit test that asserts toSource/toTarget/manyFromSource/manyFromTarget carry the custom sourceKey/targetKey:

DIALECT=mysql npx mocha -r ./test/registerEsbuild test/unit/associations/belongs-to-many.test.js

36 passing

…ToMany associations

The internal toSource/toTarget (BelongsTo) and manyFromSource/manyFromTarget
(HasMany) associations of BelongsToMany never received the custom sourceKey
and targetKey options, causing them to fall back to the primary key of the
source/target model. When sourceKey or targetKey is not the primary key, any
include through these internal associations joins on the wrong column.

oneFromSource/oneFromTarget already passed sourceKey, so this aligns the
remaining internal associations with the same behavior.
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@tianyk

tianyk commented Aug 6, 2026

Copy link
Copy Markdown
Author

The 5 failing checks appear to be environment/dependency issues unrelated to this change:

  • TS Typings (4.4): sqlite3@5.1.6 prebuilt binary download from GitHub releases failed with socket hang up, then node-gyp fallback failed (ValueError: invalid mode). Network flake on the runner.
  • Postgres 9.5/10 (native) (Node 10) × 4: pg-native@3.8.0 (latest, pulled via yarn add pg-native --ignore-engines) uses the ?? nullish coalescing operator at pg-native/index.js:153, which is a syntax error on Node 10. This is a dependency drift issue affecting any PR on this branch (e.g. fix: validate session variable assignments #18290 passed before pg-native 3.8.0 was released).

All other checks (MySQL, MariaDB, MSSQL, Oracle, Postgres on Node 18, TS typings 4.6-5.2, lint) passed, and the new unit test is included in the passing test-unit suites.

@SippieCup

Copy link
Copy Markdown
Contributor

LGTM, Thank you for doing this.

If you would like to do the v7 PR as well, be my guest. I've been meaning to do it for awhile now but just swamped with work. Otherwise I'll probably whip it up tonight.

@WikiRik Looks good to me, even if legacy v6. Could we just drop the Node 10 stuff out of the CI? I really hope no one is using it in prod!

@WikiRik

WikiRik commented Aug 13, 2026

Copy link
Copy Markdown
Member

@SippieCup dropping Node 10 is a breaking change, so unfortunately not. The postgres CI should be working again with #18292

@SippieCup

Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants