Read the source and its declared rule
The original local script creates a memo table and inserts a;b then c. Semicolon inside its quoted value is data, not a statement boundary. The corrected path passes the complete generated script to SQLite. Values are quoted with apostrophes doubled; only these fixed local CREATE/INSERT shapes are generated.
| Record | Input JSON |
|---|---|
| Base input | {"memos":["a;b","c"]} |
Compare the actual paths
Naive splitting leaves the first value’s quote unfinished and fails before data rows exist. Corrected target contains the exact two memos in order.
| Path | Output JSON |
|---|---|
| Misleading path | {"error":{"code":1},"records":[]} |
| Corrected path | {"error":null,"records":[{"memo":"a;b"},{"memo":"c"}]} |
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{const quoted=s=>"'"+s.replace(/'/g,"''")+"'";const script='CREATE TABLE target(memo TEXT);'+i.memos.map(m=>'INSERT INTO target VALUES('+quoted(m)+');').join('');
const error=failed(()=>{if(corrected)db.exec(script);else for(const fragment of script.split(';'))if(fragment.trim())db.exec(fragment);});
return {error,records:rows(db,'SELECT * FROM target ORDER BY rowid')};
}finally{db.close();}
};
const cases=[{"label":"misleading base","input":{"memos":["a;b","c"]},"expected":{"error":{"code":1},"records":[]},"corrected":false},{"label":"corrected base","input":{"memos":["a;b","c"]},"expected":{"error":null,"records":[{"memo":"a;b"},{"memo":"c"}]},"corrected":true},{"label":"escaped quote and semicolon","input":{"memos":["O'Neil;next"]},"expected":{"error":null,"records":[{"memo":"O'Neil;next"}]},"corrected":true},{"label":"no data statements","input":{"memos":[]},"expected":{"error":null,"records":[]},"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
O'Neil;next keeps both apostrophe and semicolon. No input memos creates an empty target with no insert statements.
| Case | Input JSON | Expected output JSON |
|---|---|---|
| Apostrophe and semicolon in data | {"memos":["O'Neil;next"]} | {"error":null,"records":[{"memo":"O'Neil;next"}]} |
| No inserted memo records | {"memos":[]} | {"error":null,"records":[]} |
Should a;b become two statements or remain one stored memo?
Show the worked answer
One memo. Its semicolon is inside the quoted value; the engine preserves a;b without treating it as a boundary.