Skip to content

Commit df58640

Browse files
committed
test: add failing tests for multi-line token JSON serialization bug
These tests demonstrate that scanSync throws 'Bad control character in string literal' when scanning SQL with multi-line tokens (dollar-quoted function bodies, tabs, multi-line C-style comments). The root cause is that build_scan_json() in wasm_wrapper.c only escapes '"' and '\\' in token text, but not '\n', '\r', '\t'. When token text contains literal newlines, the JSON output has unescaped control chars that break JSON.parse. These tests are expected to FAIL on this branch (no fix applied). See PR #147 for the fix.
1 parent 8ad9a92 commit df58640

1 file changed

Lines changed: 45 additions & 1 deletion

File tree

full/test/scan.test.js

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,5 +225,49 @@ describe("Query Scanning", () => {
225225
assert.equal(typeof result1.version, "number");
226226
assert.ok(result1.version > 0);
227227
});
228+
229+
it("should handle multi-line dollar-quoted strings without JSON errors", () => {
230+
// This tests that the JSON serialization properly escapes control
231+
// characters (newlines, tabs) inside token text fields.
232+
// Without a fix, scanSync throws: "Bad control character in string literal"
233+
const sql = `CREATE FUNCTION test() RETURNS void AS $$
234+
BEGIN
235+
RAISE NOTICE 'hello';
236+
END;
237+
$$ LANGUAGE plpgsql`;
238+
239+
const result = query.scanSync(sql);
240+
assert.equal(typeof result, "object");
241+
assert.ok(Array.isArray(result.tokens));
242+
assert.ok(result.tokens.length > 0);
243+
244+
// Find the dollar-quoted string token
245+
const dollarToken = result.tokens.find(t => t.text.includes('BEGIN'));
246+
assert.ok(dollarToken, "should have a token containing the function body");
247+
assert.ok(dollarToken.text.includes('\n'), "token text should contain newlines");
248+
});
249+
250+
it("should handle multi-line tokens with tabs", () => {
251+
const sql = "SELECT $$line1\n\tindented\nline3$$";
252+
253+
const result = query.scanSync(sql);
254+
assert.equal(typeof result, "object");
255+
assert.ok(Array.isArray(result.tokens));
256+
257+
const dollarToken = result.tokens.find(t => t.text.includes('indented'));
258+
assert.ok(dollarToken, "should have a token containing the tabbed content");
259+
});
260+
261+
it("should handle multi-line SQL comments", () => {
262+
const sql = "SELECT 1; /* multi\nline\ncomment */ SELECT 2";
263+
264+
const result = query.scanSync(sql);
265+
assert.equal(typeof result, "object");
266+
assert.ok(Array.isArray(result.tokens));
267+
268+
const commentToken = result.tokens.find(t => t.tokenName === "C_COMMENT");
269+
assert.ok(commentToken, "should have a C_COMMENT token");
270+
assert.ok(commentToken.text.includes('\n'), "comment text should contain newlines");
271+
});
228272
});
229-
});
273+
});

0 commit comments

Comments
 (0)