Skip to content

fix(orm): don't build an empty IN() when zero rows match an update/updateMany on MySQL - #2887

Open
krist7599555 wants to merge 2 commits into
zenstackhq:devfrom
krist7599555:fix/mysql-empty-in-after-mutation-hook
Open

krist7599555 wants to merge 2 commits into
zenstackhq:devfrom
krist7599555:fix/mysql-empty-in-after-mutation-hook

Conversation

@krist7599555

@krist7599555 krist7599555 commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Test plan

  • New regression test tests/regression/test/issue-2886.test.ts: fails against dev HEAD with the exact ER_PARSE_ERROR from the issue, passes with this fix.
  • tests/e2e/orm/plugin-infra/entity-mutation-hooks.test.ts (35 tests) still green against MySQL with the fix applied.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue where bulk updates for records that do not exist could trigger an unnecessary reload attempt on some databases. These updates now complete successfully and report zero affected records. This keeps the result consistent when no records match, without changing how updates behave when matching records are found.

…dateMany on MySQL

loadAfterMutationEntities treated an empty preUpdateIds array as truthy,
building `WHERE (id) IN ()` for any zero-match update/updateMany once an
afterEntityMutation hook is registered. MySQL (no RETURNING support)
rejects that as a syntax error — breaking every zero-match write app-wide,
including ones a policy plugin legitimately denies down to zero rows.

Fixes zenstackhq#2886
@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between 3a928bd and 2f5978f.

📒 Files selected for processing: 1
  • tests/regression/test/issue-2884.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.

📝 Walkthrough

When a dialect does not support RETURNING and a mutation has no determined IDs, the executor now returns an empty entity list without reloading entities or issuing the warning for undetermined IDs. A MySQL regression test covers a zero-match updateMany with an after-mutation hook.

Changes: MySQL zero-match mutations

Layer / File(s) Summary
Empty ID handling and regression coverage
packages/orm/src/client/executor/zenstack-query-executor.ts, tests/regression/test/issue-2884.test.ts
The executor returns an empty list when the determined ID list is empty. The MySQL regression test checks that a zero-match updateMany with a no-op after-mutation hook resolves with a count of zero.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related issues

Merge Risk: ⚪ Minimal · up to 2f597

The reviewed change has no supported merge-blocking risk.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: preventing an empty IN() clause when MySQL updates match zero rows.
Linked Issues check Passed Issue #2884 requires zero-match MySQL mutations with an afterEntityMutation hook to complete without an empty IN clause. The change returns [] when the determined ID list is empty. It preserves …
Out of Scope Changes check Passed The changes are limited to the executor branch for empty mutation ID lists and a regression test for issue #2884. These changes directly support the linked issue. No unrelated change is shown.
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3…
Full details: Linked Issues check

Explanation

Issue #2884 requires zero-match MySQL mutations with an afterEntityMutation hook to complete without an empty IN clause. The change returns [] when the determined ID list is empty. It preserves the warning path for undetermined IDs. The regression test verifies zero-match updateMany returns { count: 0 }. The existing delete path returns before after-entity reload, so it does not build an empty IN clause.

Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3 files.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

loadAfterMutationEntities builds invalid WHERE (id) IN () for a zero-match updateMany/deleteMany when any afterEntityMutation hook is registered (MySQL)

1 participant