Skip to content

WIP: add support for partial indexes based on the Prisma syntax#2622

Open
lsmith77 wants to merge 1 commit intozenstackhq:devfrom
lsmith77:partial-indexes
Open

WIP: add support for partial indexes based on the Prisma syntax#2622
lsmith77 wants to merge 1 commit intozenstackhq:devfrom
lsmith77:partial-indexes

Conversation

@lsmith77
Copy link
Copy Markdown
Contributor

@lsmith77 lsmith77 commented Apr 27, 2026

https://www.prisma.io/docs/orm/prisma-schema/data-model/indexes#configuring-partial-indexes-with-where

fix #2621

I wasn't quite sure where to place the test.

Summary by CodeRabbit

  • New Features

    • @@index and @@unique now accept an optional where clause for conditional (partial) indexes/uniques.
    • where clauses may be provided as raw SQL expressions or as filter objects.
  • Behavior / Validation

    • Plain string literals for where are rejected; only filter objects or raw SQL are accepted.
    • Generator enables partial-index output when where clauses are used.
  • Tests

    • Added e2e and regression tests verifying partial index/unique generation.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: eaa2cb4e-8cbc-4e13-ace6-2fe2b793a648

📥 Commits

Reviewing files that changed from the base of the PR and between 57d82e2 and 87ea867.

📒 Files selected for processing (7)
  • packages/language/res/stdlib.zmodel
  • packages/language/src/validators/attribute-application-validator.ts
  • packages/sdk/src/prisma/prisma-builder.ts
  • packages/sdk/src/prisma/prisma-schema-generator.ts
  • packages/sdk/src/ts-schema-generator.ts
  • tests/e2e/orm/partial-index.e2e.test.ts
  • tests/regression/test/prisma-schema-generator.test.ts
 _______________________________________________________________
< Making your code shine like the top of the Chrysler Building. >
 ---------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
📝 Walkthrough

Walkthrough

Adds optional where arguments to @@index and @@unique, introduces ExpressionContext.Unique, extends raw(string) to be usable in unique/index contexts, adds a Raw attribute argument kind, updates generators/validators to handle object/raw where clauses, and adds tests for partial indexes/uniques.

Changes

Cohort / File(s) Summary
Standard library
packages/language/res/stdlib.zmodel
Added where: Any? to @@index and @@unique; added Unique to ExpressionContext; allowed raw(String) in Unique and Index contexts.
SDK — Prisma builder
packages/sdk/src/prisma/prisma-builder.ts
Added 'Raw' variant to AttributeArgValue; validate it is a string and serialize verbatim.
SDK — Prisma schema generator
packages/sdk/src/prisma/prisma-schema-generator.ts
Enable partialIndexes preview when where args exist; convert object-shaped where exprs into Raw text via exprToText.
TypeScript schema generator
packages/sdk/src/ts-schema-generator.ts
Emit object literal AST nodes for object-shaped expressions when generating TS expressions.
Validators
packages/language/src/validators/attribute-application-validator.ts
Reject plain string-literal where arguments; require filter object or raw("...").
E2E tests & schema
tests/e2e/orm/partial-index.e2e.test.ts, tests/e2e/orm/schemas/partial-index/schema.zmodel
Added e2e test and schema verifying generated Prisma schema includes @@index(..., where: { ... }) and @@unique(..., where: { ... }).
Regression tests
tests/regression/test/prisma-schema-generator.test.ts
Added tests asserting partialIndexes preview is emitted and that where appears as raw("...") and as object forms in generated schema.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • #2467: Adds partial (filtered) @@index/@@unique support and raw/object where handling, matching the request for partial indexes.

Poem

🐰 I hopped through lines of schema light,

nudged a raw string into the night,
where clauses tucked like secret keys,
indexes blooming on conditional trees,
a rabbit claps—code's garden grows bright.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding support for partial indexes using Prisma syntax with where clauses.
Linked Issues check ✅ Passed The PR fully implements the feature request from issue #2621 by adding partial index support with where clauses and raw() expressions.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing partial index support as requested in issue #2621; no unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can disable poems in the walkthrough.

Disable the reviews.poem setting to disable the poems in the walkthrough.

Copy link
Copy Markdown
Contributor

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/sdk/src/prisma/prisma-schema-generator.ts (1)

351-380: ⚠️ Potential issue | 🟠 Major

String literals passed as where will produce invalid Prisma output.

A user writing @@index([id], where: "id > 0") reaches the isLiteralExpr branch (line 352) and is emitted as where: "id > 0". Prisma's where only accepts raw("…") or { field: value } object literals, so a bare quoted string is a syntax error in the generated Prisma schema — even though the regression test in tests/regression/test/prisma-schema-generator.test.ts (lines 6–22, 43–60) currently asserts this output is produced.

Two reasonable options:

  1. Reject String/non-object/non-raw() values on where at validation time, so the user is steered to raw("…").
  2. Auto-wrap a string literal where value with raw(...) in the generator (e.g. produce where: raw("id > 0")) so the emitted Prisma is valid.

If string-shaped where is intentional for ZModel ergonomics, option 2 is the least surprising; otherwise option 1 keeps things explicit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/sdk/src/prisma/prisma-schema-generator.ts` around lines 351 - 380,
The generator currently emits raw string literals for attribute args (in
makeAttributeArgValue) which produces invalid Prisma for a `where` arg; change
makeAttributeArgValue to accept an optional argName (e.g. add parameter
argName?: string) and when isLiteralExpr(node) && node.$type === StringLiteral
&& argName === 'where' return a PrismaAttributeArgValue('Raw',
this.exprToText(node)) or construct a raw(...) FunctionCall equivalent instead
of emitting a plain String; update all callers that create attribute args (where
attribute parsing site(s)) to pass the arg name so the function can auto-wrap
`where` string literals into Raw (or alternatively throw a validation error
there if you prefer rejection).
🧹 Nitpick comments (1)
packages/language/res/stdlib.zmodel (1)

253-253: Document the new where parameter and broaden raw() expression context to include @@unique.

Two small follow-ups for the new where: Any? parameter on @@unique (line 253) and @@index (line 356):

  1. The JSDoc above each attribute (lines 244–252 and 345–355) doesn't describe the new where parameter. Adding a one-liner clarifying it's used for partial indexes (Prisma partialIndexes preview) and accepts either raw("SQL") or an object literal would help schema authors discover it.
  2. The raw() helper is declared with @@@expressionContext([Index]) (line 634). Now that where is also valid on @@unique, raw(...) used inside @@unique(..., where: raw("...")) is technically outside the declared expression context. Consider widening that context (e.g. introduce a new Unique context or reuse Index) so language-level validation stays consistent.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/language/res/stdlib.zmodel` at line 253, Update the JSDoc for the
@@unique and @@index attributes to document the new where: Any? parameter with a
one-line description stating it is for partial indexes (Prisma partialIndexes
preview) and accepts either raw("SQL") or an object literal; then broaden the
raw() expression context declaration (the raw symbol/@@@expressionContext) to
include Unique (or both Index and Unique) so raw(...) used inside @@unique(...,
where: raw("...")) is recognized by the language-level validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/sdk/src/prisma/prisma-schema-generator.ts`:
- Around line 372-373: The generator currently neither adds previewFeatures =
["partialIndexes"] when index/constraint args use a where predicate nor properly
emits string literal predicates, so update generateDefaultGenerator to scan
index/unique definitions (where the code constructs @@index/@@unique and `@unique`
attributes) and if any PrismaAttributeArg with name "where" is present mark the
generator previewFeatures to include "partialIndexes"; additionally, change the
handling in exprToText/isLiteralExpr (the branch that returns
PrismaAttributeArgValue('Raw', this.exprToText(node)) and the branch emitting
bare quoted strings for literals) so that string literal `where` values are
either rejected with a clear validation error or automatically wrapped as
raw("...") (prefer wrapping to preserve compatibility), ensuring object
expressions remain emitted as before; reference the affected symbols:
generateDefaultGenerator, PrismaAttributeArgValue('Raw'), isLiteralExpr,
isObjectExpr, and exprToText.

In `@tests/e2e/orm/partial-index.e2e.test.ts`:
- Around line 1-21: This e2e test is brittle and redundant; remove this test
file (tests/e2e/orm/partial-index.e2e.test.ts) or rewrite it to use the
programmatic API: replace the execSync-based runGenerate()/npx invocation with a
call to loadSchema from `@zenstackhq/testtools` and invoke PrismaSchemaGenerator
directly (or the existing regression helper used in
tests/regression/test/prisma-schema-generator.test.ts), assert on the generated
schema string instead of reading/writing SCHEMA_FILE/GENERATED_PRISMA, and if
you must write files use a tmpdir or add cleanup in afterAll to avoid polluting
the source tree.

In `@tests/e2e/orm/schemas/partial-index/schema.zmodel`:
- Around line 1-13: The fixture is missing the generator preview feature for
partial indexes, so update the schema to include an explicit generator block
that sets previewFeatures = ["partialIndexes"] (so Prisma accepts the
model-level @@index and @@unique with where clauses); add this generator (using
the same generator name pattern produced by
PrismaSchemaGenerator.generateDefaultGenerator if you want parity) near the top
of the schema (above or below the datasource block) so the Post model's
@@index([title], where: { published: true }) and @@unique([title], where: {
published: true }) validate correctly.

In `@tests/regression/test/prisma-schema-generator.test.ts`:
- Around line 6-22: Tests currently expect the generator to emit bare quoted
string values for index `where`, which is invalid Prisma syntax; update the
PrismaSchemaGenerator so that when it encounters a string literal for an index
`where` it emits it wrapped in raw(...), e.g. `where: raw("...")`, and then
update the failing tests in
tests/regression/test/prisma-schema-generator.test.ts to assert for
`@@index([id], where: raw("id > 0"))` and `@@index([email], where: raw("email IS
NOT NULL"))` instead of the bare quoted strings; locate logic inside
PrismaSchemaGenerator.generate() that serializes index attributes and alter the
serializer for Index/@@index where-value handling to detect string nodes and
emit raw("...") accordingly.

---

Outside diff comments:
In `@packages/sdk/src/prisma/prisma-schema-generator.ts`:
- Around line 351-380: The generator currently emits raw string literals for
attribute args (in makeAttributeArgValue) which produces invalid Prisma for a
`where` arg; change makeAttributeArgValue to accept an optional argName (e.g.
add parameter argName?: string) and when isLiteralExpr(node) && node.$type ===
StringLiteral && argName === 'where' return a PrismaAttributeArgValue('Raw',
this.exprToText(node)) or construct a raw(...) FunctionCall equivalent instead
of emitting a plain String; update all callers that create attribute args (where
attribute parsing site(s)) to pass the arg name so the function can auto-wrap
`where` string literals into Raw (or alternatively throw a validation error
there if you prefer rejection).

---

Nitpick comments:
In `@packages/language/res/stdlib.zmodel`:
- Line 253: Update the JSDoc for the @@unique and @@index attributes to document
the new where: Any? parameter with a one-line description stating it is for
partial indexes (Prisma partialIndexes preview) and accepts either raw("SQL") or
an object literal; then broaden the raw() expression context declaration (the
raw symbol/@@@expressionContext) to include Unique (or both Index and Unique) so
raw(...) used inside @@unique(..., where: raw("...")) is recognized by the
language-level validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 008b5d0b-0d7c-4e01-bf01-577bd8d2229a

📥 Commits

Reviewing files that changed from the base of the PR and between 8609d5b and b06e557.

📒 Files selected for processing (6)
  • packages/language/res/stdlib.zmodel
  • packages/sdk/src/prisma/prisma-builder.ts
  • packages/sdk/src/prisma/prisma-schema-generator.ts
  • tests/e2e/orm/partial-index.e2e.test.ts
  • tests/e2e/orm/schemas/partial-index/schema.zmodel
  • tests/regression/test/prisma-schema-generator.test.ts

Comment thread packages/sdk/src/prisma/prisma-schema-generator.ts
Comment thread tests/e2e/orm/partial-index.e2e.test.ts Outdated
Comment thread tests/e2e/orm/schemas/partial-index/schema.zmodel Outdated
Comment thread tests/regression/test/prisma-schema-generator.test.ts Outdated
@lsmith77 lsmith77 force-pushed the partial-indexes branch 2 times, most recently from c641029 to 57d82e2 Compare April 28, 2026 06:14
@lsmith77
Copy link
Copy Markdown
Contributor Author

@ymc9 Unknown database 'test_db_pull_common_features_all_pr998e02' seems like an unrelated issue to this PR, which is causing the other DB's to not get tested at all. I have rebased on current dev.

* @param where: Filters rows included in the partial unique constraint; accepts a Prisma filter object or raw("SQL").
*/
attribute @@unique(_ fields: FieldReference[], name: String?, map: String?, length: Int?, sort: SortOrder?, clustered: Boolean?) @@@prisma
attribute @@unique(_ fields: FieldReference[], name: String?, map: String?, length: Int?, sort: SortOrder?, clustered: Boolean?, where: Any?) @@@prisma
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I guess there is no support for union types to be able to be more strict here.

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.

[Feature Request] Add support for partial indexes

1 participant