Skip to content

Conversation

@jay-l-e-e
Copy link
Contributor

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

  • PSL parser changes
  • Schema engine DDL generation
  • Migration diff logic
  • Introspection support
  • Preview feature gate
  • Unit tests
  • Migration tests (21 tests across 4 databases)
  • Introspection tests
  • SQL Server support
  • CockroachDB limitation handling
  • Documentation update (separate PR)

@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 from 3eefb77 to 6f861f6 Compare January 26, 2026 17:31
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
@jay-l-e-e jay-l-e-e force-pushed the feat/partial-index-support branch 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.

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.

2 participants