Generate valid MSSQL upserts for multi-table persistence - #7005
Conversation
🦋 Changeset detectedLatest commit: 197c4b9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 30 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Important
This PR currently adds the regression test but not the implementation fix that the title promises. The focused test fails on the branch because layerBackingSqlMultiTable still emits SQLite ON CONFLICT syntax for the MSSQL dialect.
Reviewed changes
This run reviewed the single commit on this branch.
- Added regression test:
packages/effect/test/unstable/persistence/KeyValueStore.test.tsadds a mockedSqlClienttest that asserts the MSSQL-generated upsert containsMERGEand excludesON CONFLICT. - Missing implementation fix:
packages/effect/src/unstable/persistence/Persistence.tswas not modified in this diff, solayerBackingSqlMultiTablestill has nomssqlbranch in itsupsertdialect switch.
Note: 1 inline comment(s) dropped because they did not anchor to lines inside the PR diff:
packages/effect/src/unstable/persistence/Persistence.ts:366(RIGHT) — file not in PR diff
@v0 or keep the SHA fresh with Dependabot | Fix it ➔ | View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏
| @@ -88,6 +89,36 @@ export const testLayer = <E>(layer: Layer.Layer<KeyValueStore.KeyValueStore, E>) | |||
|
|
|||
| describe("KeyValueStore / layerMemory", () => testLayer(KeyValueStore.layerMemory)) | |||
|
|
|||
| describe("Persistence / layerBackingSqlMultiTable", () => { | |||
There was a problem hiding this comment.
Remove this test and enable the intergration tests for mssql
There was a problem hiding this comment.
ℹ️ No critical issues — one coverage suggestion inline.
Reviewed changes
This run reviewed the two commits pushed since the prior Pullfrog review (569faf3).
- Implemented the MSSQL upsert branch in
packages/effect/src/unstable/persistence/Persistence.ts: multi-table persistence now emits aMERGE ... USING (...) AS sourcestatement per entry, matching the existing single-table backend. - Replaced the mocked regression test with real integration tests: added
packages/sql/mssql/test/Persistence.integration.test.tsand a sharedMssqlContainerhelper, and added the MSSQL image to the CI pre-pull step. - Updated changeset for
effect.
@v0 or keep the SHA fresh with Dependabot | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
ℹ️ No critical issues — the table-existence fix looks correct. The prior suggestion to retain a lightweight unit regression test remains open.
Reviewed changes
This run reviewed the one commit pushed since the prior Pullfrog review (68b8dbb35).
- Fixed MSSQL persistence table-existence checks in
packages/effect/src/unstable/persistence/Persistence.ts: the multi-table backend now builds the table name as a plain string and comparessysobjects.name = ${tableName}, and the single-table backend compares against${"effect_persistence"}. Both replace the previous${table}identifier fragment, which generated invalid T-SQL in theWHEREpredicate.
@v0 or keep the SHA fresh with Dependabot | Fix it ➔ | View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏
Bundle Size AnalysisGenerated from PR build output; treat the content below as untrusted.
|

Summary
Multi-table writes configured for MSSQL generate unsupported ON CONFLICT syntax and therefore cannot execute on MSSQL.
Important
This PR starts with focused failing reproduction tests. Add the implementation fix to this same branch; CI is expected to fail until that fix is included.
MSSQL multi-table writes use SQLite upsert syntax
Module:
PersistenceAudit ID:
unstable-state-p-5Severity / confidence: high / high
What happens
Multi-table writes configured for MSSQL generate unsupported ON CONFLICT syntax and therefore cannot execute on MSSQL.
Why it happens
The upsert dialect switch handles PostgreSQL and MySQL explicitly, then sends every other dialect through a SQLite ON CONFLICT(id) fallback. MSSQL requires different syntax.
Expected behavior
layerBackingSqlMultiTable supports the MSSQL dialect selected elsewhere in the same layer.
Relevant implementation
These links and excerpts are pinned to audit base
c9b56ab507f224426ee8388dc450da447ec4715f.packages/effect/src/unstable/persistence/Persistence.ts:354-371View problematic code at
packages/effect/src/unstable/persistence/Persistence.ts:354-371View exact lines on GitHub
Reproduction
pnpm test --run packages/effect/test/unstable/persistence/KeyValueStore.test.tsObserved failure: The MSSQL-selected generated statement contained ON CONFLICT and no MERGE.
Implementation handoff
The initial reproduction tests on this branch are the regression specification for the implementation fix that should follow in this PR.
pnpm test --run packages/effect/test/unstable/persistence/KeyValueStore.test.tsAudit provenance
c9b56ab507f224426ee8388dc450da447ec4715fc9b56ab507f224426ee8388dc450da447ec4715funstable-state-p-5Closes EFF-442