Skip to content

Conversation

@alumni
Copy link
Collaborator

@alumni alumni commented Aug 2, 2025

Description of change

Allows the user to declare VirtualColumns that by default are not selected, similar to regular columns. They can be explicitly selected using QueryBuilder.addSelect or FindOptions.select.

Fixes #11277

Pull-Request Checklist

  • Code is up-to-date with the master branch
  • This pull request links relevant issues as Fixes #00000
  • There are new or updated unit tests validating the change
  • Documentation has been updated to reflect this change

Summary by CodeRabbit

  • New Features

    • Added support for marking virtual columns as non-selectable by default, allowing finer control over which virtual columns are included in query results.
    • Introduced a new virtual column for companies to report total hours from related activities, which is not selected by default.
  • Bug Fixes

    • Improved handling and selection logic for virtual columns in queries.
  • Tests

    • Enhanced and expanded tests for virtual columns, including scenarios for non-selectable virtual columns and complex data aggregation.
    • Simplified test data creation for better readability and maintainability.
  • Refactor

    • Streamlined entity definitions and updated decorators for clarity and consistency.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 2, 2025

Walkthrough

A new select option was added to the VirtualColumnOptions interface, allowing virtual columns to be excluded from default selection. The Company, Employee, and TimeSheet entity classes were updated to use this option and to streamline their property decorators and relations. The test suite for virtual columns was expanded and refactored to cover these changes and to simplify test data creation. The SelectQueryBuilder's internal logic for column selection was also simplified.

Changes

Cohort / File(s) Change Summary
VirtualColumnOptions Interface Update
src/decorator/options/VirtualColumnOptions.ts
Added optional select property to VirtualColumnOptions interface to control default selection of virtual columns.
SelectQueryBuilder Logic Simplification
src/query-builder/SelectQueryBuilder.ts
Refactored findEntityColumnSelects method to directly return all matching selects, removing previous conditional logic.
Company Entity Enhancements
test/functional/columns/virtual-columns/entity/Company.ts
Simplified primary column decorator, added cascading to employees relation, used SQL template tag for virtual columns, made virtual column types optional, added totalReportedHours with select: false, and removed duplicate property.
Employee Entity Adjustments
test/functional/columns/virtual-columns/entity/Employee.ts
Simplified primary column decorator and enabled cascading on timesheets relation.
TimeSheet Entity Refactor
test/functional/columns/virtual-columns/entity/TimeSheet.ts
Changed activities relation to OneToMany with cascade, updated virtual column to use SQL template tag and made its type optional, reordered properties.
Virtual Columns Test Suite Overhaul
test/functional/columns/virtual-columns/virtual-columns.ts
Refactored test data setup to use nested entity creation, added tests for non-selected virtual columns, updated assertions, and improved coverage for new and existing virtual columns.

Sequence Diagram(s)

sequenceDiagram
    participant TestSuite
    participant Repository
    participant CompanyEntity
    participant QueryBuilder

    TestSuite->>Repository: Save Company with nested Employees, Timesheets, Activities
    Repository->>CompanyEntity: Persist entity and relations (with cascade)
    TestSuite->>QueryBuilder: Find Company (default select)
    QueryBuilder->>CompanyEntity: Retrieve columns (excluding select: false virtuals)
    TestSuite->>QueryBuilder: AddSelect('totalReportedHours')
    QueryBuilder->>CompanyEntity: Retrieve columns (including totalReportedHours)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

In the warren of code, a new path appears,
Virtual columns now hide, unless select clears.
Entities refactored, relations cascade,
Tests nest their data, assertions remade.
With a hop and a skip, the queries delight—
Rabbits rejoice in the virtual column light!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 17cf837 and 3c34e01.

📒 Files selected for processing (6)
  • src/decorator/options/VirtualColumnOptions.ts (1 hunks)
  • src/query-builder/SelectQueryBuilder.ts (1 hunks)
  • test/functional/columns/virtual-columns/entity/Company.ts (2 hunks)
  • test/functional/columns/virtual-columns/entity/Employee.ts (1 hunks)
  • test/functional/columns/virtual-columns/entity/TimeSheet.ts (2 hunks)
  • test/functional/columns/virtual-columns/virtual-columns.ts (6 hunks)
🔇 Additional comments (15)
src/decorator/options/VirtualColumnOptions.ts (1)

13-17: Default value needs to be enforced in implementation

The comment says the new select flag “Default value is true”, but the interface alone does not apply a default—undefined will propagate unless some runtime path converts it to true.
Double-check that:

  1. VirtualColumn registration code explicitly sets select = true when the option is undefined, mirroring the behaviour of regular columns.
  2. All places that consume metadata.select treat undefined the same as true.

Otherwise virtual columns could silently become non-selectable.

src/query-builder/SelectQueryBuilder.ts (1)

2968-2977: LGTM! Clean simplification that supports virtual column selection.

The method correctly filters selects to find all matches for either the alias name directly or any of the alias's column property paths. This simplified approach removes conditional branching while maintaining the same functionality and properly supports the new virtual column selection semantics introduced in this PR.

test/functional/columns/virtual-columns/entity/Employee.ts (2)

7-8: LGTM! Clean simplification of the decorator.

Removing explicit type and length options from @PrimaryColumn() improves readability while TypeORM correctly infers the column type from the TypeScript property type.


13-16: Appropriate use of cascading for test entities.

Adding cascade: true simplifies test data creation by allowing nested entity persistence. This is a good pattern for test fixtures.

Note: While cascading is convenient here, use it cautiously in production entities as it can lead to unintended data modifications or deletions.

test/functional/columns/virtual-columns/entity/TimeSheet.ts (3)

1-1: Good use of dedent for SQL template literals.

Aliasing dedent as sql clearly indicates SQL query strings and improves readability for multi-line queries.


17-23: Correct relationship direction and consistent cascading pattern.

The change from ManyToOne to OneToMany for activities better represents the domain model where a timesheet contains multiple activities. The cascade option aligns with the test data creation pattern used across other entities.


25-29: Well-structured virtual column with appropriate nullable type.

The virtual column correctly:

  • Uses the sql template for better readability
  • Marks the return type as optional since SUM() returns null when no activities exist
  • Properly aggregates hours from related activities
test/functional/columns/virtual-columns/virtual-columns.ts (4)

2-2: Comprehensive setup for testing complex virtual columns.

The addition properly:

  • Imports dedent for SQL readability
  • Sets up MySQL-specific query syntax with backticks
  • Tests complex multi-table aggregation queries
  • Aligns with the totalReportedHours virtual column implementation

Also applies to: 42-54


157-177: Excellent use of cascading relations for test data setup.

The nested object creation pattern:

  • Significantly simplifies test data setup
  • Makes the entity relationships clear
  • Properly leverages the cascade options added to the entities
  • Reduces test boilerplate

89-89: Skip minor assertion style changes.

Also applies to: 147-147


302-355: Thorough test coverage for the new non-selectable virtual column feature.

This test effectively validates:

  • Virtual columns with select: false are excluded by default
  • Explicit selection via addSelect() works correctly
  • Complex aggregation queries return expected results

The test directly verifies the PR's main objective of allowing virtual columns to be initially non-selectable.

test/functional/columns/virtual-columns/entity/Company.ts (4)

1-1: Consistent patterns with other entity files.

Good use of:

  • sql template literal for query readability
  • Simplified @PrimaryColumn() decorator

Also applies to: 12-13


15-18: Consistent cascading pattern for test relations.

The cascade: true option on the employees relation aligns with the test data creation pattern used throughout these test entities.


20-24: Improved virtual column definition.

The updates properly:

  • Use sql template for better query formatting
  • Mark the type as optional to handle aggregate results correctly

26-35: Excellent implementation of the non-selectable virtual column feature.

This virtual column perfectly demonstrates the PR's objective:

  • select: false ensures it's not included in queries by default
  • Complex multi-table aggregation showcases real-world usage
  • Proper use of sql template for the multi-line query
  • Correct optional typing for aggregate results

This is the centerpiece implementation that enables virtual columns to be initially non-selectable, addressing issue #11277.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 generate unit tests to generate unit tests for 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.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Aug 2, 2025

typeorm-sql-js-example

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

commit: 3c34e01

@coveralls
Copy link

Coverage Status

coverage: 76.352% (-0.001%) from 76.353%
when pulling 3c34e01 on alumni:feat/non-selectable-by-default-virtual-column
into 17cf837 on typeorm:master.

* Indicates if column is always selected by QueryBuilder and find operations.
* Default value is "true".
*/
select?: boolean
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't see this value used in the changed code. Is there a test that checks that virtual column now can be un-selected?

Copy link
Collaborator Author

@alumni alumni Aug 13, 2025

Choose a reason for hiding this comment

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

Yes: "should be able to read non-selectable virtual columns (with query builder)" checks if Company.totalReportedHours is returned correctly when that column is explicitly selected.

BTW, this feature already exists for regular Columns. This PR just enables it for VirtualColumns (basically in types only) + fixes a bug with adding the select twice.

@alumni alumni requested review from gioboa and mguida22 August 18, 2025 18:16
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 @alumni you are great 👏

@alumni alumni merged commit 22b26d1 into typeorm:master Aug 18, 2025
58 checks passed
ThbltLmr pushed a commit to ThbltLmr/typeorm that referenced this pull request Dec 2, 2025
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.

Ignore column when generating migration

5 participants