Skip to content

Conversation

ragrag
Copy link
Contributor

@ragrag ragrag commented Oct 26, 2024

Description of change

After the introduction of entityMetadatasMap in f12a95c an issue arises where a junction table defined by user in entities would have multiple metadata entries (one for entity manually defined by the user, and one for the auto-created metadata by typeorm). This would cause problems as the junction table metadata would override the user defined metadata in entityMetadatasMap.

This PR ensures metadata for junction tables already created by users do not exist twice in entityMetadatas and thus avoiding conflicts when its resolved from entityMetadatasMap. This works by always using the user defined entity metadata if it exists.

This bug exists from version 3.13 and blocks upgrading if junction tables are used.

Fixes:

#10412 (includes repro)
#10463
#10643

Apart from those issues, as a side effect of this fix, other various issues related to duplicate sql statements while generating migrations in conjunction with user defined junction tables, for example #7955, #11126 and similar issues are fixed or partially fixed

Pull-Request Checklist

  • Code is up-to-date with the master branch
  • npm run format to apply prettier formatting
  • npm run test passes with this change
  • This pull request links relevant issues as Fixes #0000
  • There are new or updated unit tests validating the change
  • Documentation has been updated to reflect this change
  • The new commits follow conventions explained in CONTRIBUTING.md

Summary by CodeRabbit

  • Bug Fixes

    • Resolved an issue where duplicate metadata could be created for user-defined junction tables in many-to-many relationships.
  • Tests

    • Added new test cases to verify correct handling of user-defined junction tables and ensure no duplicate metadata is generated.
  • New Features

    • Introduced entity schemas and relationships for User, Document, and DocumentRelation to support many-to-many associations via a custom junction table.

@ragrag ragrag changed the title fix: allow multiple entries in entityMetadatasMap fix: allow multiple entries in entityMetadatasMap to prevent conflict with junction tables Oct 26, 2024
@ragrag ragrag changed the title fix: allow multiple entries in entityMetadatasMap to prevent conflict with junction tables fix: do not create junction table metadata when it already exists Oct 26, 2024
Copy link

coderabbitai bot commented Jun 20, 2025

Walkthrough

The update modifies the logic for handling auto-generated junction entity metadata in many-to-many relations to prevent duplication when a user-defined junction table exists. It introduces new tests and entity schemas to verify correct metadata construction and relation handling with user-defined junction tables.

Changes

Files / Folders Change Summary
src/metadata-builder/EntityMetadataBuilder.ts Updated logic to conditionally add auto-generated junction entity metadata, avoiding duplication.
test/functional/entity-metadata/entity-metadata-builder.ts Added test suite to verify correct metadata and relation behavior with user-defined junction tables.
test/functional/entity-metadata/entity/junction-table/entities.ts Introduced entity schemas and interfaces modeling a many-to-many relation with a custom junction table.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Document
    participant DocumentRelation
    participant EntityMetadataBuilder

    User->>EntityMetadataBuilder: Defines many-to-many relation to Document via DocumentRelation
    Document->>EntityMetadataBuilder: Defines one-to-many relation to DocumentRelation
    DocumentRelation->>EntityMetadataBuilder: Defines many-to-one relation to Document

    EntityMetadataBuilder->>EntityMetadataBuilder: Check for user-defined junction table
    alt User-defined junction exists
        EntityMetadataBuilder-->>EntityMetadataBuilder: Do not add auto-generated junction metadata
    else No user-defined junction
        EntityMetadataBuilder-->>EntityMetadataBuilder: Add auto-generated junction metadata
    end
Loading

Suggested labels

comp: relations, need review help, size-m

Suggested reviewers

  • mguida22
  • sgarner
  • gioboa

Poem

In the warren of code, relations abound,
Junction tables hop and scurry around.
Now with a check, no duplicates appear,
User-defined tables get a hearty cheer!
With tests in the meadow, all is in sync—
The metadata garden’s greener than you think! 🐇

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-06-23T10_07_45_213Z-debug-0.log

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/metadata-builder/JunctionEntityMetadataBuilder.ts (1)

362-364: Misplaced JSDoc comment.

The JSDoc comment "Collects inverse referenced columns from the given join column args" is incorrectly placed above the changeDuplicatedColumnNames method. This method handles duplicate column name resolution, not collecting inverse referenced columns.

Move this comment to the correct location or update it to describe the actual method:

-    /**
-     * Collects inverse referenced columns from the given join column args.
-     */
     protected changeDuplicatedColumnNames(
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1bcf055 and b4328d6.

📒 Files selected for processing (4)
  • src/metadata-builder/EntityMetadataBuilder.ts (1 hunks)
  • src/metadata-builder/JunctionEntityMetadataBuilder.ts (3 hunks)
  • test/github-issues/10412/entity/entities.ts (1 hunks)
  • test/github-issues/10412/issue-10412.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
test/github-issues/10412/issue-10412.ts (2)
test/utils/test-utils.ts (3)
  • createTestingConnections (388-482)
  • reloadTestingDatabases (500-505)
  • closeTestingConnections (487-495)
test/github-issues/10412/entity/entities.ts (1)
  • documentRelationEntitySchema (65-87)
🔇 Additional comments (7)
test/github-issues/10412/entity/entities.ts (2)

23-45: Well-designed test entities for the junction table scenario.

The userEntitySchema correctly defines a many-to-many relationship with a join table named "document_relation", which matches the explicitly defined documentRelationEntitySchema entity. This setup perfectly reproduces the bug scenario where TypeORM would create duplicate metadata.


65-87: Explicit junction table entity properly defined.

The documentRelationEntitySchema entity correctly defines the same table ("document_relation") that's referenced in the User's joinTable configuration. This dual definition (implicit via joinTable + explicit via entity schema) is exactly what was causing the metadata duplication issue.

src/metadata-builder/JunctionEntityMetadataBuilder.ts (2)

297-297: Method visibility change is necessary for the fix.

Changing collectReferencedColumns from protected to public is required so that EntityMetadataBuilder can access this method when reusing existing junction table metadata.


329-329: Method visibility change is necessary for the fix.

Changing collectInverseReferencedColumns from protected to public enables EntityMetadataBuilder to properly collect inverse referenced columns when reusing existing junction metadata.

src/metadata-builder/EntityMetadataBuilder.ts (1)

295-334: Excellent fix for the junction table metadata duplication issue.

The logic correctly addresses the core problem by:

  1. Detection: Checks if junction table metadata already exists by comparing metadata.target === joinTable.name
  2. Reuse: Instead of creating new metadata, it reuses the existing metadata
  3. Integration: Properly registers foreign keys, join columns, and junction metadata from the existing entity

The column filtering logic (lines 315-328) correctly matches existing metadata columns with the referenced columns that would be created by the junction builder. This ensures the relation has the proper join columns without duplicating metadata.

This fix elegantly prevents the conflict described in the PR objectives where auto-created metadata would override user-defined metadata in entityMetadatasMap.

test/github-issues/10412/issue-10412.ts (2)

27-35: Effective test for verifying metadata deduplication.

This test correctly verifies that the repository metadata contains exactly one relation, confirming that the fix prevents duplicate junction table metadata creation. The assertion expect(repository.metadata.relations.length).to.be.eql(1) directly validates the core issue resolution.


37-50: Comprehensive test for the reported error condition.

This test effectively verifies that the EntityPropertyNotFoundError mentioned in GitHub issue #10412 no longer occurs when querying with relations and where conditions. The test setup correctly uses the documentRelationEntitySchema entity and includes both relation loading and filtering, which was the problematic scenario.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b4328d6 and bf19a2c.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • src/data-source/DataSource.ts (1 hunks)
  • test/github-issues/10412/issue-10412.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/data-source/DataSource.ts (4)
src/common/EntityTarget.ts (1)
  • EntityTarget (7-11)
src/metadata/EntityMetadata.ts (1)
  • EntityMetadata (30-1139)
src/repository/Repository.ts (1)
  • metadata (53-55)
src/util/ObjectUtils.ts (1)
  • ObjectUtils (3-82)
🪛 Biome (1.9.4)
test/github-issues/10412/issue-10412.ts

[error] 11-11: Don't focus the test.

The 'only' method is often used for debugging or during implementation. It should be removed before deploying to production.
Consider removing 'only' to ensure all tests are executed.
Unsafe fix: Remove focus from test.

(lint/suspicious/noFocusedTests)

🔇 Additional comments (1)
src/data-source/DataSource.ts (1)

736-760: Excellent fix for the junction table metadata conflict issue.

The two-phase approach correctly prioritizes user-defined entities over auto-generated junction entities. The logic ensures that:

  1. User-defined entities (non-junction) are added to the map first
  2. Junction entities are only added if they don't conflict with existing entries
  3. This prevents the bug where auto-created metadata overrides user-defined metadata

The solution directly addresses the core issue described in the PR objectives and maintains backward compatibility.

@ragrag
Copy link
Contributor Author

ragrag commented Jun 20, 2025

@michaelbromley @mguida22 any chance someone can take a look at this 👀 ? it blocks upgrading from 3.13 onwards for anyone who uses junction tables

Copy link

pkg-pr-new bot commented Jun 20, 2025

typeorm-sql-js-example

npm i https://pkg.pr.new/typeorm/typeorm@11114

commit: 73256da

Copy link
Collaborator

@sgarner sgarner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @ragrag

Can you investigate why tests are failing for some databases?

@ragrag ragrag force-pushed the master branch 2 times, most recently from 5279d77 to 71cee6d Compare June 20, 2025 23:07
@ragrag ragrag requested a review from sgarner June 20, 2025 23:15
@ragrag
Copy link
Contributor Author

ragrag commented Jun 21, 2025

Thanks for the PR @ragrag

Can you investigate why tests are failing for some databases?

@sgarner thanks 🙏🏻 all tests now work in my downstream repo, https://github.com/ragrag/typeorm/actions/runs/15789744898

@coveralls
Copy link

coveralls commented Jun 21, 2025

Coverage Status

coverage: 76.348% (+0.004%) from 76.344%
when pulling 73256da on ragrag:master
into 01dddfe on typeorm:master.

Comment on lines 3 to 9
"version": "0.3.25",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "typeorm",
"version": "0.3.24",
"version": "0.3.25",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert this change

import { expect } from "chai"
import { documentRelationEntitySchema } from "./entity/entities"

describe("github issues > #10412 EntityPropertyNotFoundError when joinTable is used", () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are moving away from creating tests for specific GitHub issues. Instead we need tests which demonstrate that EntityMetadataBuilder works correctly. Unfortunately there isn't a test suite for this class yet, so one needs to be created.

Please move this test file to test/functional/entity-metadata/entity-metadata-builder.ts and adjust test descriptions appropriately for this context.

ragrag and others added 2 commits June 23, 2025 09:21
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8498452 and f296659.

📒 Files selected for processing (2)
  • test/functional/entity-metadata/entity-metadata-builder.ts (1 hunks)
  • test/functional/entity-metadata/entity/JunctionTableEntities.ts (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
test/functional/entity-metadata/entity-metadata-builder.ts

[error] 15-15: Don't focus the test.

The 'only' method is often used for debugging or during implementation. It should be removed before deploying to production.
Consider removing 'only' to ensure all tests are executed.
Unsafe fix: Remove focus from test.

(lint/suspicious/noFocusedTests)

🔇 Additional comments (2)
test/functional/entity-metadata/entity/JunctionTableEntities.ts (1)

1-87: Well-structured test entity schemas for junction table testing.

The entity schemas effectively model the scenario described in the PR objectives. The relationships between User, Document, and DocumentRelation (user-defined junction table) are properly configured with correct column mappings and join table definitions. This setup will adequately test the junction table metadata duplication fix.

test/functional/entity-metadata/entity-metadata-builder.ts (1)

35-58: Excellent test coverage for the junction table metadata fix.

The test cases effectively validate the fix described in the PR objectives:

  1. The first test verifies that repository metadata correctly includes relations when user-defined junction tables are used
  2. The second test ensures that querying with relations doesn't throw EntityPropertyNotFoundError

These tests directly address the core issues mentioned in the PR (resolving conflicts from duplicate metadata entries and preventing query errors).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
test/functional/entity-metadata/entity/junction-table/entities.ts (3)

3-9: Consider adding a User relation to the DocumentRelation interface.

The DocumentRelation interface represents a junction table but only has a relation to Document. For completeness and bidirectional navigation, consider adding a user property to establish the relationship to the User entity.

 interface DocumentRelation {
     documentRelationId: number
     documentId: number
     userId?: number
 
     document?: Document
+    user?: User
 }

52-62: Remove unnecessary joinColumn specification from one-to-many relation.

The joinColumn specification in a one-to-many relation is typically unnecessary since the foreign key constraint is defined on the "many" side (DocumentRelation entity). The foreign key relationship is already properly defined in the DocumentRelation entity schema.

 relations: {
     documentRelation: {
         type: "one-to-many",
         target: "document_relation",
         inverseSide: "document",
-        joinColumn: {
-            name: "document_id",
-            referencedColumnName: "documentId",
-        },
     },
 },

65-87: Consider adding a User relation to complete the junction table.

The DocumentRelation entity is missing a relation to the User entity. While this might be intentional for testing specific scenarios, a complete junction table typically has relations to both entities it connects.

 relations: {
     document: {
         type: "many-to-one",
         target: "document",
         inverseSide: "documentRelation",
         joinColumn: {
             name: "document_id",
             referencedColumnName: "documentId",
         },
     },
+    user: {
+        type: "many-to-one",
+        target: "user",
+        joinColumn: {
+            name: "user_id",
+            referencedColumnName: "userId",
+        },
+    },
 },
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 48483e2 and 73256da.

📒 Files selected for processing (2)
  • test/functional/entity-metadata/entity-metadata-builder.ts (1 hunks)
  • test/functional/entity-metadata/entity/junction-table/entities.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/functional/entity-metadata/entity-metadata-builder.ts
🔇 Additional comments (1)
test/functional/entity-metadata/entity/junction-table/entities.ts (1)

23-45: Excellent junction table configuration for testing.

The User entity schema correctly defines the many-to-many relationship using a custom junction table. The join table configuration properly maps to the user-defined "document_relation" entity, which is exactly what this test needs to verify the junction table metadata fix.

@ragrag
Copy link
Contributor Author

ragrag commented Jun 23, 2025

@sgarner thank you again 🙏🏻 i addressed all requested changes

@ragrag ragrag requested a review from sgarner June 26, 2025 11:49
@ragrag
Copy link
Contributor Author

ragrag commented Jul 7, 2025

@sgarner apologies for the bump 🙏🏻 any updates on when we can merge this?

Copy link
Collaborator

@sgarner sgarner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution @ragrag 💜

@sgarner sgarner merged commit 3c26cf1 into typeorm:master Jul 8, 2025
58 checks passed
Copy link
Collaborator

@gioboa gioboa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your help @ragrag

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.

5 participants