Skip to content

Conversation

@jay-l-e-e
Copy link
Contributor

@jay-l-e-e jay-l-e-e commented Jan 23, 2026

Summary

This PR implements support for partial indexes (also known as filtered indexes) in Prisma Schema Language. Partial indexes allow creating indexes that only include rows matching a specific condition, reducing index size and improving query performance.

There was an issue related to this PR that was 5 years old. 😱

New Syntax

Raw SQL Syntax (all supported databases)

model User {
  id       Int     @id
  email    String
  status   String
  
  @@unique([email], where: raw("status = 'active'"))
  @@index([email], where: raw("deletedAt IS NULL"))
}

Object Literal Syntax (type-safe alternative)

model Post {
  id        Int      @id
  title     String
  published Boolean
  
  @@index([title], where: { published: true })
  @@unique([title], where: { published: { not: false } })
}

Preview Feature

This feature is gated behind the partialIndexes preview feature:

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["partialIndexes"]
}

Supported Databases

Database Support Migrations Introspection Notes
PostgreSQL ✅ Full Full predicate support
SQLite ✅ Full Full predicate support
SQL Server ✅ Full Filtered indexes via CREATE INDEX
CockroachDB ⚠️ Partial ✅ Create only Cannot introspect predicate text
MySQL - - Not supported by the database

CockroachDB Limitation

CockroachDB supports creating partial indexes but cannot introspect predicate text. This means:

  • ✅ Initial index creation works
  • ❌ Predicate modifications are not detected
  • add/modify/remove predicate migrations don't work

The differ skips predicate comparison for CockroachDB to prevent false-positive migrations.

Changes

PSL Parser (psl/)

  • Grammar: Extended Pest grammar with object_expression and object_member rules
  • AST: Added Expression::Object variant and ObjectMember struct
  • Types: Added WhereClause, WhereCondition, WhereFieldCondition, WhereValue enums
  • Validation: Added partial_index_is_supported validation requiring preview feature
  • Capabilities: Added PartialIndex connector capability for PostgreSQL, SQLite, CockroachDB, SQL Server

Schema Engine (schema-engine/)

  • DDL Generation: Implemented CREATE INDEX ... WHERE for all supported databases
  • Migrations:
    • Added predicates_match() trait method to SqlSchemaDifferFlavour
    • Delegate predicate comparison to flavour-specific implementations
    • CockroachDB skips predicate comparison (DB limitation)
  • Introspection:
    • Modified PostgreSQL/SQLite/MSSQL describers to fetch index predicates
    • Auto-injects partialIndexes preview feature when partial indexes detected
  • Normalization:
    • PostgreSQL predicates wrapped in parentheses to match DB format
    • SQL Server predicates wrapped in parentheses for consistency

SQL Server Specifics

  • Filtered unique indexes must be created via CREATE INDEX (not as table constraints)
  • Modified render_create_table_as to exclude filtered unique indexes from constraints
  • Added filter_definition column to index introspection query

SQL DDL (libs/sql-ddl/)

  • Added WhereClause support to CreateIndex for PostgreSQL
  • Implemented CreatePartialIndex for SQLite

Test Coverage

PSL Unit Tests (psl/psl/tests/attributes/partial_index.rs)

  • 33 test cases covering:
    • Raw SQL syntax for @@unique and @@index
    • Object literal syntax (boolean, string, number, null conditions)
    • Multiple field conditions
    • { not: true/false/null } syntax
    • Error cases (unsupported databases, invalid syntax)
    • CockroachDB support

Migration Tests (schema-engine/sql-migration-tests/)

Database unique normal compound add modify remove Total
PostgreSQL 6
SQLite 6
SQL Server 6
CockroachDB - - - 3

Total: 21 migration tests

Introspection Tests (schema-engine/sql-introspection-tests/)

  • PostgreSQL partial unique index introspection
  • SQLite partial unique index introspection
  • SQL Server partial unique index introspection
  • Automatic preview feature injection
  • Field-level @unique with where clause

Generated SQL Examples

PostgreSQL

CREATE UNIQUE INDEX "User_email_key" ON "User" ("email") WHERE (status = 'active'::text);

SQLite

CREATE UNIQUE INDEX "User_email_key" ON "User" ("email") WHERE status = 'active';

SQL Server

CREATE UNIQUE NONCLUSTERED INDEX [User_email_key] ON [dbo].[User]([email]) WHERE ([status]='active');

CockroachDB

CREATE UNIQUE INDEX "User_email_key" ON "User" ("email") WHERE (status = 'active');

Key Files

File Changes
psl/schema-ast/src/parser/datamodel.pest Grammar rules for object expressions
psl/schema-ast/src/ast/expression.rs Expression::Object AST type
psl/parser-database/src/attributes.rs where clause parsing logic
psl/parser-database/src/walkers/index.rs SQL predicate generation
psl/psl-core/src/common/preview_features.rs PartialIndexes feature flag
psl/psl-core/src/builtin_connectors/mssql_datamodel_connector.rs MSSQL PartialIndex capability
schema-engine/.../sql_schema_calculator.rs DDL generation with predicates
schema-engine/.../sql_schema_differ/table.rs Predicate comparison for migrations
schema-engine/.../sql_schema_differ_flavour.rs predicates_match() trait method
schema-engine/.../flavour/postgres/schema_differ.rs CockroachDB predicate handling
schema-engine/.../flavour/mssql/renderer.rs SQL Server filtered index rendering
schema-engine/.../flavour/mssql/schema_differ.rs SQL Server index matching
schema-engine/sql-schema-describer/src/mssql.rs SQL Server predicate introspection
schema-engine/.../introspection/ Partial index introspection

Related

Checklist

@jay-l-e-e
Copy link
Contributor Author

@jacek-prisma Could you please review this PR?

@jay-l-e-e jay-l-e-e force-pushed the feat/partial-index-support branch 2 times, most recently from 6f861f6 to f4647c7 Compare January 26, 2026 18:07
@jay-l-e-e
Copy link
Contributor Author

jay-l-e-e commented Jan 26, 2026

@jkomyno Hi, Could you please review this PR?

@mikiyasET
Copy link

@aqrln @tomhoule This needs to be reviewed.

@jay-l-e-e
Copy link
Contributor Author

This PR has passed all tests that can be run locally, including tests against the real database and the shadow database. Clippy and fmt have both been applied. I’d like to run the GitHub Actions workflow.

@daunJung-dev
Copy link

@aqrln could you review this PR? I hope it pass review

@codspeed-hq
Copy link

codspeed-hq bot commented Feb 5, 2026

Merging this PR will not alter performance

✅ 11 untouched benchmarks
⏩ 11 skipped benchmarks1


Comparing jay-l-e-e:feat/partial-index-support (9af3b26) with main (57b675f)

Open in CodSpeed

Footnotes

  1. 11 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@jay-l-e-e
Copy link
Contributor Author

Okay, I can see that some tests have failed. I’ll fix the problem!

@jay-l-e-e
Copy link
Contributor Author

@jacek-prisma Added missing predicate: None to sql-schema-describer test snapshots. The Index struct gained a new field in the partial index commit, which required snapshot updates.

Please re-run the tests! Thank you 👍

@jay-l-e-e jay-l-e-e force-pushed the feat/partial-index-support branch 2 times, most recently from 2ce8b62 to 9c97582 Compare February 6, 2026 08:26
@jay-l-e-e
Copy link
Contributor Author

I have also added tests to verify partial indexes (filtered indexes) are correctly described for PostgreSQL, SQLite, MSSQL, and CockroachDB.

@jay-l-e-e jay-l-e-e force-pushed the feat/partial-index-support branch from 59a313b to 53adf6c Compare February 7, 2026 03:03
@jay-l-e-e
Copy link
Contributor Author

@jacek-prisma The tests I previously added to sql-schema-describer were failing in CI, so I updated the SQL schemas to be deterministic and fixed the snapshots accordingly. I've also addressed all of the review feedback. Could you re-run the CI workflow?

Thanks!

@jay-l-e-e
Copy link
Contributor Author

@jacek-prisma The tests I previously added to sql-schema-describer were failing in CI, so I updated the SQL schemas to be deterministic and fixed the snapshots accordingly. I've also addressed all of the review feedback. Could you re-run the CI workflow?

Thanks!

I've pushed to my branch and all CI tests are passing now, including the Schema Engine tests.

@jacek-prisma
Copy link
Contributor

Thanks for addressing my comments @jay-l-e-e , I left 2 additional comments about 2 edge cases that I think still need to be handled

@jay-l-e-e
Copy link
Contributor Author

@jacek-prisma Hi, I've addressed all the review comments you left. I also added unit tests for the changes and verified they pass. Would you mind running the CI workflow when you get a chance? Thanks.

Add support for partial indexes with WHERE clauses in Prisma Schema Language.

Features:
- New raw() syntax for WHERE clauses: @@unique([email], where: raw("status = 'active'"))
- Object literal syntax for conditions: @@unique([email], where: { active: true })
  - Supports: boolean (true/false), null, string, and number values
  - Conditions: equals, not equals (!=), IS NULL, IS NOT NULL
- Support for PostgreSQL, SQLite, SQL Server (filtered indexes), and CockroachDB
- Preview feature flag: partialIndexes
- Auto-injection of preview feature during introspection

Schema Engine:
- SQL generation for partial indexes across all supported databases
- Migration diffing with predicate comparison
- Introspection of existing partial indexes
- CockroachDB limitation handling (cannot introspect predicate text)

SQL Server specifics:
- Filtered unique indexes created via CREATE INDEX (not table constraints)
- Predicate normalization for consistent diffing

Tests:
- Comprehensive migration tests for all supported databases
- Introspection tests for PostgreSQL, SQLite, SQL Server, and CockroachDB
Add missing 'predicate: None' field to Index struct expectations in sql-schema-describer tests. This field was added in the partial index support commit but the test snapshots were not updated.
… databases

Added tests to verify partial indexes (filtered indexes) are correctly
described for PostgreSQL, SQLite, MSSQL, and CockroachDB.
… and move SQL rendering to walker_ext_traits
@jay-l-e-e jay-l-e-e force-pushed the feat/partial-index-support branch from c791e88 to bac37d2 Compare February 11, 2026 11:42
@jacek-prisma
Copy link
Contributor

Hi @jay-l-e-e
This PR will be merged soon.
Also can you avoid force pushing after approval please, becauses it forces us to re-review the changes.

@jay-l-e-e
Copy link
Contributor Author

Hi @jacek-prisma, I’m really glad to hear that the PR may be merged soon. Thank you very much.
The reason I did a force push was to rebase onto the latest commit of the main branch. Although there were no code changes, I realize that I pushed it carelessly as you mentioned. I’ll be more careful going forward.
Have a great day!

@jay-l-e-e
Copy link
Contributor Author

@jacek-prisma Hmm, a new PR was just merged and it caused a conflict. It seems to be because the version of sqlparser in the PR you recently merged was bumped to 0.60.

While I was working, I had considered upgrading sqlparser to 0.60 as well (since version 0.60 includes support for predicates), but I ended up not proceeding with it. Would you like me to update my changes to align with version 0.60?

@jay-l-e-e
Copy link
Contributor Author

Oh, I see you’re already working on resolving it. I’ll step back and leave it to you.

@jacek-prisma jacek-prisma merged commit 2997580 into prisma:main Feb 11, 2026
97 of 98 checks passed
jay-l-e-e added a commit to jay-l-e-e/docs that referenced this pull request Feb 11, 2026
…support

Add comprehensive documentation for the new `partialIndexes` preview feature,
which enables `where` argument on `@@index`, `@@unique`, and `@unique` attributes
for PostgreSQL, SQLite, SQL Server, and CockroachDB.

Ref: prisma/prisma-engines#5749, prisma/prisma#6974
jay-l-e-e added a commit to jay-l-e-e/docs that referenced this pull request Feb 11, 2026
…support

Add comprehensive documentation for the new `partialIndexes` preview feature,
which enables `where` argument on `@@index`, `@@unique`, and `@unique` attributes
for PostgreSQL, SQLite, SQL Server, and CockroachDB.

Ref: prisma/prisma-engines#5749, prisma/prisma#6974
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.

4 participants