Skip to content

fix(qc): don't apply the nested upsert where filter to the parent update - #5854

Open
samuelmbabhazi wants to merge 1 commit into
prisma:mainfrom
samuelmbabhazi:fix/qc-nested-upsert-parent-filter
Open

samuelmbabhazi wants to merge 1 commit into
prisma:mainfrom
samuelmbabhazi:fix/qc-nested-upsert-parent-filter

Conversation

@samuelmbabhazi

Copy link
Copy Markdown

Problem

Reported in prisma/orm#29744.

A nested upsert on a to-one relation that is inlined on the parent fails when the optional where filter is provided and the create branch is taken. The generated SQL for the step that connects the newly created child references a child column inside the UPDATE on the parent table:

UPDATE "public"."Patient" SET "userId" = $1
WHERE ("public"."Patient"."id" IN ($2) AND "public"."User"."email" = $3)

The database rejects this with The column User.email does not exist in the current database, a cross table reference without a join. The bug only triggers when the where argument is passed, which is optional on to-one upserts. Without it the filter is empty and the query is valid, which is why this went mostly unnoticed.

Root cause

In nested_upsert, the update node that writes the foreign key on the parent receives the upsert where filter. That filter belongs to the child model, its only role is to select which child to read and update. The equivalent connect step in nested_connect, nested_connect_or_create and nested_create passes Filter::empty() to the same placeholder, since the parent rows are already pinned by the selectors injected through the graph edge.

Fix

Pass Filter::empty() for the parent update, matching the sibling builders. A now redundant clone of the filter is also removed since the filter is moved at its last remaining use.

Tests

  • New snapshot test update-nested-upsert.json covering the failing shape, a to-one relation inlined on the parent with a where filter. Before the fix the snapshot contains the invalid cross table condition shown above, after the fix the parent update is filtered by the selectors only. No other snapshot changed.
  • cargo test -p query-core -p query-compiler -p sql-query-builder passes.
  • cargo fmt --check and cargo clippy -p query-core -p query-compiler --all-targets with warnings as errors are clean.
  • Verified end to end against prisma/prisma v7: with the Wasm compiler built from this branch, the reproduction from the issue (same schema and nested upsert, better-sqlite3 driver adapter) passes, along with the existing upsert functional test suites.

For a to-one relation inlined on the parent, the create branch of a nested
upsert connects the newly created child by updating the foreign key on the
parent. That update node received the upsert where filter, which belongs to
the child model, so the rendered SQL referenced a child column inside the
update on the parent table and the query failed with "The column X does not
exist in the current database".

The parent rows are already pinned by the injected selectors, and the
equivalent connect step in nested connect and connectOrCreate passes an
empty filter, so do the same here.

Fixes prisma/orm#29744
@CLAassistant

CLAassistant commented Aug 2, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 38febc3f-6138-42ca-a6dd-68b2a6771d43

📥 Commits

Reviewing files that changed from the base of the PR and between 9bae2a3 and 32801c0.

⛔ Files ignored due to path filters (1)
  • query-compiler/query-compiler/tests/snapshots/queries__queries@update-nested-upsert.json.snap is excluded by !**/*.snap
📒 Files selected for processing (2)
  • query-compiler/core/src/query_graph_builder/write/nested/upsert_nested.rs
  • query-compiler/query-compiler/tests/data/update-nested-upsert.json

Summary by CodeRabbit

  • Bug Fixes

    • Fixed nested upsert updates for inlined relations by applying filters to the related record correctly.
    • Ensured parent records are selected reliably during nested upsert operations.
  • Tests

    • Added coverage for updating a patient with a nested user upsert.

Walkthrough

The nested upsert builder now moves the consumed where filter into the child update node. For inlined relations, the parent update placeholder uses an empty filter while existing selector dependencies select parent records. A query fixture covers updating Patient record id: 1 with a nested user upsert and scalar field selection.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the fix for applying a nested upsert filter to the parent update.
Description check ✅ Passed The description explains the nested upsert bug, root cause, fix, tests, and validation results.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
✨ Simplify code
  • Create PR with simplified code

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.

This branch has not been deployed

No deployments
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