Skip to content

feat(core): add type-safe using option for index hints#7375

Merged
B4nan merged 9 commits intonextfrom
feat/using-index-hints
Apr 18, 2026
Merged

feat(core): add type-safe using option for index hints#7375
B4nan merged 9 commits intonextfrom
feat/using-index-hints

Conversation

@B4nan
Copy link
Copy Markdown
Member

@B4nan B4nan commented Mar 21, 2026

Summary

  • Adds using option to FindOptions that validates where/orderBy against named indexes and emits driver-specific SQL hints
  • For defineEntity, index names are inferred automatically from .index('name')/.unique('name') and entity-level indexes/uniques
  • For decorator entities, uses [IndexHints] symbol (same pattern as [PrimaryKeyProp])
  • Type-safe: narrows where to only allow properties from the specified index(es) via overloaded signatures on find, findOne, findOneOrFail, findAndCount, findAll, findByCursor, stream (both EM and EntityRepository)
  • Runtime validation throws when query uses properties not covered by the index, or when the index name doesn't exist
  • SQL hint generation: MySQL/MariaDB (USE INDEX), MSSQL (WITH (INDEX(...))), PostgreSQL/SQLite/libSQL (validation only)
  • MongoDB: passes index name as hint option
  • Coexists with existing indexHint option (explicit indexHint takes precedence)

Closes #7175

🤖 Generated with Claude Code

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 21, 2026

Codecov Report

❌ Patch coverage is 98.90110% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 99.64%. Comparing base (1e765d0) to head (913c4e4).
⚠️ Report is 1 commits behind head on next.

Files with missing lines Patch % Lines
packages/core/src/EntityManager.ts 98.36% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             next    #7375      +/-   ##
==========================================
- Coverage   99.64%   99.64%   -0.01%     
==========================================
  Files         263      263              
  Lines       26558    26625      +67     
  Branches     6895     7214     +319     
==========================================
+ Hits        26465    26531      +66     
  Misses         88       88              
- Partials        5        6       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@B4nan B4nan mentioned this pull request Mar 22, 2026
@B4nan B4nan marked this pull request as ready for review March 22, 2026 11:56
@B4nan B4nan force-pushed the feat/using-index-hints branch 2 times, most recently from 88c1a0a to a46b85e Compare April 1, 2026 14:53
@B4nan B4nan force-pushed the feat/using-index-hints branch from a46b85e to 56f6449 Compare April 14, 2026 07:23
B4nan and others added 9 commits April 18, 2026 16:57
Adds a new `using` option to `FindOptions` that provides type-safe index
awareness for queries. When specified, it validates that `where` and
`orderBy` only reference columns covered by the named index(es), and
emits driver-specific SQL index hints (MySQL `USE INDEX`, MSSQL
`WITH (INDEX(...))`).

For `defineEntity` entities, index names are automatically inferred from
property-level `.index('name')`/`.unique('name')` calls and entity-level
`indexes`/`uniques` definitions. For decorator entities, users declare
the `[IndexHints]` symbol (similar to `[PrimaryKeyProp]`).

Closes #7175

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract `WithUsingOptions` utility type to reduce inline `Omit` duplication
- Move `using` → `indexHint` conversion into `validateSqlOptions`
- Remove redundant comments in `validateIndexUsage`
- Fix type assertions in defineEntity.test.ts for `[IndexHints]` phantom property
- Fix benchmark to use `p.integer()` instead of `p.number()`

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move validateIndexUsage before processWhere in find() to avoid
  false-positive errors from filter-injected properties
- Fix MongoDB: use first index name only (MongoDB only supports
  a single hint per query), remove invalid array hint
- Add 'using' to MongoDB buildQueryOptions Pick type, remove as-any cast

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Recurse into $and/$or/$not when validating where keys against index
- Remove TIndexDefs/TUniqueDefs const generics from defineEntity (major
  type perf win: setClass pattern 9496 -> 8897, embeddable 1246 -> 926)
- Property-level .index('name')/.unique('name') still auto-infer;
  entity-level composite indexes need manual [IndexHints] for type narrowing
- Fixes expression callback inference regression (no explicit types needed)
- MongoDB: throw error when using has multiple indexes (only one supported)
- Revert unrelated MSSQL snapshot changes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Store raw [Properties] tuple in [IndexHints] instead of computed map.
ExtractIndexHints lazily computes InferPropertyIndexMap only when
the using option is actually accessed (via IndexName<T> or IndexColumns<T, N>).

This avoids evaluating the property iteration during defineEntity(),
especially in expression callback types where InferEntityFromProperties
is referenced multiple times.

Impact vs original pre-PR baselines:
- realistic entity - setClass: 7419 → 8049 (+8.5%, down from +20%)
- embeddable extends: 914 → 926 (+1.3%)
- entity extends: 1460 → 1472 (+0.8%)
- defineEntity with relations: 7118 → 7349 (+3.2%)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add MySQL tests: USE INDEX hint generation, multiple indexes, findOne, findAndCount
- Add MSSQL tests: WITH (INDEX(...)) hint generation, multiple indexes
- Add MongoDB tests: hint passthrough, multiple-index error, indexHint precedence
- Add SQLite tests: no-named-indexes error, orderBy array, valid orderBy,
  PK where, findAll, findByCursor, stream, findOneOrFail, $eq operator
- Add Plain entity (no named indexes) for 'No named indexes defined' branch
- Add Doc entity (MongoDB-compatible) with _id PK

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds patch coverage for the `using` index-hint option across
EntityRepository delegation, MongoEntityManager.stream, findByCursor
with includeCount=false, array/$-operator where clauses, expression-only
indexes, and the stream/findAll default-where paths.
@B4nan B4nan force-pushed the feat/using-index-hints branch from 56f6449 to 913c4e4 Compare April 18, 2026 15:06
@B4nan B4nan changed the base branch from master to next April 18, 2026 15:06
@B4nan B4nan merged commit a5b491a into next Apr 18, 2026
21 of 22 checks passed
@B4nan B4nan deleted the feat/using-index-hints branch April 18, 2026 15:15
B4nan added a commit that referenced this pull request Apr 19, 2026
## Summary

- Adds `using` option to `FindOptions` that validates `where`/`orderBy`
against named indexes and emits driver-specific SQL hints
- For `defineEntity`, index names are inferred automatically from
`.index('name')`/`.unique('name')` and entity-level `indexes`/`uniques`
- For decorator entities, uses `[IndexHints]` symbol (same pattern as
`[PrimaryKeyProp]`)
- Type-safe: narrows `where` to only allow properties from the specified
index(es) via overloaded signatures on `find`, `findOne`,
`findOneOrFail`, `findAndCount`, `findAll`, `findByCursor`, `stream`
(both EM and EntityRepository)
- Runtime validation throws when query uses properties not covered by
the index, or when the index name doesn't exist
- SQL hint generation: MySQL/MariaDB (`USE INDEX`), MSSQL (`WITH
(INDEX(...))`), PostgreSQL/SQLite/libSQL (validation only)
- MongoDB: passes index name as `hint` option
- Coexists with existing `indexHint` option (explicit `indexHint` takes
precedence)

Closes #7175

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
B4nan added a commit that referenced this pull request Apr 20, 2026
## Summary

- Adds `using` option to `FindOptions` that validates `where`/`orderBy`
against named indexes and emits driver-specific SQL hints
- For `defineEntity`, index names are inferred automatically from
`.index('name')`/`.unique('name')` and entity-level `indexes`/`uniques`
- For decorator entities, uses `[IndexHints]` symbol (same pattern as
`[PrimaryKeyProp]`)
- Type-safe: narrows `where` to only allow properties from the specified
index(es) via overloaded signatures on `find`, `findOne`,
`findOneOrFail`, `findAndCount`, `findAll`, `findByCursor`, `stream`
(both EM and EntityRepository)
- Runtime validation throws when query uses properties not covered by
the index, or when the index name doesn't exist
- SQL hint generation: MySQL/MariaDB (`USE INDEX`), MSSQL (`WITH
(INDEX(...))`), PostgreSQL/SQLite/libSQL (validation only)
- MongoDB: passes index name as `hint` option
- Coexists with existing `indexHint` option (explicit `indexHint` takes
precedence)

Closes #7175

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

Finds limited to indexes

1 participant