Read the source and its declared rule
The original import requires this two-row batch to commit together, with each quantity present and positive. A2 inserts before B−1 fails CHECK. SQLite ABORT reverses the failing statement, not A’s earlier successful statement in the transaction. Catching that error and committing preserves a partial batch.
| Record | Input JSON |
|---|---|
| Base input | {"records":[{"id":"A","quantity":2},{"id":"B","quantity":-1}]} |
Compare the actual paths
Correct error handling issues ROLLBACK, so target is empty. The code retains the actual code 275 beside committed-state rows.
| Path | Output JSON |
|---|---|
| Misleading path | {"error":{"code":275},"target":[{"id":"A","quantity":2}]} |
| Corrected path | {"error":{"code":275},"target":[]} |
import {DatabaseSync} from 'node:sqlite';
import {TextDecoder} from 'node:util';
import {inflateSync} from 'node:zlib';
import {posix} from 'node:path';
import {createHash} from 'node:crypto';
const rows=(db,sql)=>db.prepare(sql).all().map(r=>({...r}));
const failed=(action)=>{try{action();return null;}catch(e){return {code:e.errcode??e.code??e.name};}};
import assert from 'node:assert/strict';
const run=function run(i,corrected=true){
const db=new DatabaseSync(':memory:');try{db.exec('CREATE TABLE target(id TEXT PRIMARY KEY,quantity INTEGER NOT NULL CHECK(quantity>0));BEGIN;');
const error=failed(()=>{for(const r of i.records)db.prepare('INSERT INTO target VALUES(?,?)').run(r.id,r.quantity);});
db.exec(corrected&&error?'ROLLBACK;':'COMMIT;');return {error,target:rows(db,'SELECT * FROM target ORDER BY id')};
}finally{db.close();}
};
const cases=[{"label":"misleading base","input":{"records":[{"id":"A","quantity":2},{"id":"B","quantity":-1}]},"expected":{"error":{"code":275},"target":[{"id":"A","quantity":2}]},"corrected":false},{"label":"corrected base","input":{"records":[{"id":"A","quantity":2},{"id":"B","quantity":-1}]},"expected":{"error":{"code":275},"target":[]},"corrected":true},{"label":"all-good batch commits both","input":{"records":[{"id":"A","quantity":2},{"id":"B","quantity":3}]},"expected":{"error":null,"target":[{"id":"A","quantity":2},{"id":"B","quantity":3}]},"corrected":true},{"label":"first statement fails","input":{"records":[{"id":"A","quantity":-2},{"id":"B","quantity":3}]},"expected":{"error":{"code":275},"target":[]},"corrected":true},{"label":"missing second quantity rolls back the batch","input":{"records":[{"id":"A","quantity":2},{"id":"B","quantity":null}]},"expected":{"error":{"code":1299},"target":[]},"corrected":true}];
for(const test of cases){
const actual=run(test.input,test.corrected);
assert.deepEqual(actual,test.expected,test.label);
console.log(test.label,actual);
}
Check boundaries before the next load
All-good A/B commit together. If the first insert fails, no later row is attempted and the rollback leaves empty state. Missing B quantity fails NOT NULL1299 and rolls back the earlier A too.
| Case | Input JSON | Expected output JSON |
|---|---|---|
| Complete valid batch | {"records":[{"id":"A","quantity":2},{"id":"B","quantity":3}]} | {"error":null,"target":[{"id":"A","quantity":2},{"id":"B","quantity":3}]} |
| First statement fails | {"records":[{"id":"A","quantity":-2},{"id":"B","quantity":3}]} | {"error":{"code":275},"target":[]} |
| Missing second quantity rolls back all | {"records":[{"id":"A","quantity":2},{"id":"B","quantity":null}]} | {"error":{"code":1299},"target":[]} |
Does catching code 275 automatically remove earlier successful statements?
Show the worked answer
No. A remains unless the batch transaction is rolled back. Corrected failure leaves no committed rows.