Skip to content

fix(db2): Include identity offered a clause Db2 does not have - #267

Merged
huyplb merged 1 commit into
mainfrom
fix/db2-identity-insert
Aug 17, 2026
Merged

fix(db2): Include identity offered a clause Db2 does not have#267
huyplb merged 1 commit into
mainfrom
fix/db2-identity-insert

Conversation

@huyplb

@huyplb huyplb commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Tested the identity-insert capability matrix against the live engines instead
of reading it. For each dialect: create a table with an identity column, write an
explicit value using exactly the ceremony the app prescribes, then ask the engine
to generate the next id and see whether it collides.

The bug

Db2 was listed as overriding, and the data-copy path lets overriding through.
Verified on Db2 LUW 11.5 that this can never work:

Attempt Result
INSERT … (ID, NOTE) OVERRIDING SYSTEM VALUE VALUES … SQL0104N
clause before the column list SQL0104N
on INSERT … SELECT SQL0104N
plain insert into GENERATED ALWAYS SQL0798N

There is no override clause on Db2 LUW — that is Postgres (and Db2 for i/z-OS).
So "Include identity" started the copy and failed it mid-run, which is the one
outcome this table exists to prevent. Db2 is unsupported now, with the advice
Oracle already gives: switch the toggle off, or make the column GENERATED BY
DEFAULT — which does accept an explicit value, also verified.

The unit tests asserted the same wrong thing as the code, which is exactly why it
survived; they now encode what the servers answered.

What the run confirmed as already correct

  • PostgresOVERRIDING SYSTEM VALUE accepted, and resyncSequence: true
    is right: after writing id 500 the generator is still behind it, so the next
    generated id collides. That is the quiet failure mode, and the matrix has it.
  • MySQL — plain insert; the counter moves past the written value
    (resyncSequence: false).
  • Oracle — refuses GENERATED ALWAYS with ORA-32795, as documented.
  • SQL Server — the session toggle only holds within a single batch; run as
    separate statements it lands on another session and the insert is rejected. The
    migrate path already refuses toggle with a message saying it does not issue
    SET IDENTITY_INSERT, so that limitation is stated honestly.
  • GENERATED BY DEFAULT relaxes the requirement on Postgres, Db2 and Oracle.

Verification

npx vitest run — 1799 passed, 95 skipped · tsc --noEmit clean · eslint clean.

🤖 Generated with Claude Code


Note

Medium Risk
Changes data-migrate and insert SQL shaping for Db2 identity columns; wrong classification could block valid copies or allow failing runs, but behavior is aligned with live Db2 LUW testing and BY DEFAULT remains supported.

Overview
Db2 LUW no longer uses Postgres-style OVERRIDING SYSTEM VALUE for “Include identity.” The dialect capability table now marks Db2 as unsupported for GENERATED ALWAYS identity writes (with user-facing guidance to turn off Include identity or use GENERATED BY DEFAULT), because live verification on Db2 LUW 11.5 shows the override clause is rejected (SQL0104N) and plain inserts into ALWAYS fail (SQL0798N).

Postgres-family behavior is unchanged — only postgres, cockroachdb, and yugabytedb still get the overriding clause on ALWAYS; Db2 is removed from that list in tests and in buildPeekInsert commentary.

Tests now match engine behavior: Db2 ALWAYS is expected to be refused via identityInsertFor, while Db2 BY DEFAULT remains writable (native).

Reviewed by Cursor Bugbot for commit d625edb. Bugbot is set up for automated code reviews on this repo. Configure here.

Tested the identity-insert matrix against the live engines rather than reading
it: create a table with an identity column, write an explicit value using
exactly the ceremony the app prescribes, then ask the engine to generate the
*next* id and see whether it collides.

Db2 was listed as `overriding`, which the data-copy path lets through. Verified
on Db2 LUW 11.5 that this cannot work: `OVERRIDING SYSTEM VALUE` is **SQL0104N**
in every position (before the column list, after it, on INSERT … SELECT), and a
plain insert into GENERATED ALWAYS is **SQL0798N**. There is no override — so
the copy started and then failed mid-run, which is the single outcome that table
exists to prevent. Db2 is `unsupported` now, with the same advice Oracle gives:
turn the toggle off, or make the column GENERATED BY DEFAULT (which does take an
explicit value — also verified).

The unit tests asserted the same wrong thing the code did, which is why this
survived; they now encode what the servers actually answered.

What the run confirmed as already correct:

* Postgres — `OVERRIDING SYSTEM VALUE` accepted, and `resyncSequence: true` is
  right: after writing id 500 the generator is still behind, so the next
  generated id collides. That is the quiet one, and the matrix has it.
* MySQL — plain insert, and the counter moves past the written value
  (`resyncSequence: false`).
* Oracle — refuses GENERATED ALWAYS with ORA-32795, exactly as documented.
* SQL Server — the session toggle only holds inside one batch; separate
  statements land on a different session and the insert is rejected. The
  migrate path already refuses `toggle` with a message saying it does not issue
  SET IDENTITY_INSERT, so that limit is honestly stated.
* GENERATED BY DEFAULT relaxes the requirement on Postgres, Db2 and Oracle.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_147c8f56-b1ae-4f50-aa19-d544ed3f0a1c)

@huyplb
huyplb merged commit 6ef8b8b into main Aug 17, 2026
11 checks passed
@huyplb
huyplb deleted the fix/db2-identity-insert branch August 17, 2026 05:22
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.

1 participant