diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 556db2e3..394cedc4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,7 +55,7 @@ jobs: if [ "${{ matrix.package.name }}" = "v13" ]; then # Download prebuilt WASM for v13 since it can't build in CI mkdir -p wasm - curl -o v13.tgz "https://registry.npmjs.org/@libpg-query/v13/-/v13-13.0.0.tgz" + curl -o v13.tgz "https://registry.npmjs.org/@libpg-query/v13/-/v13-13.5.2.tgz" tar -xzf v13.tgz --strip-components=1 package/wasm rm v13.tgz else diff --git a/full/src/index.ts b/full/src/index.ts index f9258e87..976d4341 100644 --- a/full/src/index.ts +++ b/full/src/index.ts @@ -92,7 +92,7 @@ export const parse = awaitInit(async (query: string): Promise => { resultPtr = wasmModule._wasm_parse_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } @@ -121,7 +121,7 @@ export const deparse = awaitInit(async (parseTree: ParseResult): Promise resultPtr = wasmModule._wasm_deparse_protobuf(dataPtr, data.length); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } @@ -142,7 +142,7 @@ export const parsePlPgSQL = awaitInit(async (query: string): Promise => { resultPtr = wasmModule._wasm_fingerprint(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } @@ -184,7 +184,7 @@ export const normalize = awaitInit(async (query: string): Promise => { resultPtr = wasmModule._wasm_normalize_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } @@ -209,7 +209,7 @@ export function parseSync(query: string): ParseResult { resultPtr = wasmModule._wasm_parse_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } @@ -241,7 +241,7 @@ export function deparseSync(parseTree: ParseResult): string { resultPtr = wasmModule._wasm_deparse_protobuf(dataPtr, data.length); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } @@ -265,7 +265,7 @@ export function parsePlPgSQLSync(query: string): ParseResult { resultPtr = wasmModule._wasm_parse_plpgsql(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } @@ -289,7 +289,7 @@ export function fingerprintSync(query: string): string { resultPtr = wasmModule._wasm_fingerprint(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } @@ -313,7 +313,7 @@ export function normalizeSync(query: string): string { resultPtr = wasmModule._wasm_normalize_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } @@ -334,7 +334,7 @@ export const scan = awaitInit(async (query: string): Promise => { resultPtr = wasmModule._wasm_scan(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } @@ -358,7 +358,7 @@ export function scanSync(query: string): ScanResult { resultPtr = wasmModule._wasm_scan(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } diff --git a/parser/test/parser.test.js b/parser/test/parser.test.js index dfc5f940..eb8b49db 100644 --- a/parser/test/parser.test.js +++ b/parser/test/parser.test.js @@ -88,4 +88,26 @@ describe('Parser', () => { }); } }); +}); + +describe('Issue Test - INSERT with multiple VALUES', () => { + const testSQL = "INSERT INTO logtable (message) VALUES ('Init'), ('Reboot'), ('ERROR'), ('Warning'), ('info');"; + const versions = [13, 14, 15, 16, 17]; + + for (const version of versions) { + it(`should parse with PostgreSQL v${version} without throwing`, async () => { + try { + const versionModule = require(`../wasm/v${version}.cjs`); + await versionModule.loadModule(); + const result = await versionModule.parse(testSQL); + assert.ok(result); // Just verify we got a result + } catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + console.log(`Version ${version} not available in this build`); + } else { + throw e; + } + } + }); + } }); \ No newline at end of file diff --git a/parser/test/parser.test.ts b/parser/test/parser.test.ts deleted file mode 100644 index 8f2b1197..00000000 --- a/parser/test/parser.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { PgParser, parse } from '../wasm/index.js'; -import * as v15 from '../wasm/v15.js'; -import * as v16 from '../wasm/v16.js'; -import * as v17 from '../wasm/v17.js'; - -describe('PgParser', () => { - describe('Dynamic API', () => { - it('should parse SQL with default version (17)', async () => { - const result = await parse('SELECT 1+1 as sum'); - expect(result.version).toBe(17); - expect(result.result).toBeDefined(); - expect(result.result.stmts).toHaveLength(1); - }); - - it('should parse SQL with version 15', async () => { - const result = await parse('SELECT 1+1 as sum', 15); - expect(result.version).toBe(15); - expect(result.result).toBeDefined(); - }); - - it('should handle parse errors', async () => { - const result = await parse('INVALID SQL'); - expect(result.error).toBeDefined(); - expect(result.error.type).toBe('syntax'); - expect(result.error.message).toContain('syntax error'); - }); - - it('should work with PgParser class', async () => { - const parser = new PgParser(16); - const result = await parser.parse('SELECT * FROM users'); - expect(result.version).toBe(16); - expect(result.result).toBeDefined(); - }); - }); - - describe('Static imports', () => { - it('should parse with v15', async () => { - await v15.loadModule(); - const result = await v15.parse('SELECT 1'); - expect(result).toBeDefined(); - expect(result.stmts).toHaveLength(1); - }); - - it('should parse with v16', async () => { - await v16.loadModule(); - const result = await v16.parse('SELECT 1'); - expect(result).toBeDefined(); - expect(result.stmts).toHaveLength(1); - }); - - it('should parse with v17', async () => { - await v17.loadModule(); - const result = await v17.parse('SELECT 1'); - expect(result).toBeDefined(); - expect(result.stmts).toHaveLength(1); - }); - }); -}); \ No newline at end of file diff --git a/versions/13/package.json b/versions/13/package.json index f44e1328..3d2b3119 100644 --- a/versions/13/package.json +++ b/versions/13/package.json @@ -1,6 +1,6 @@ { "name": "@libpg-query/v13", - "version": "13.5.1", + "version": "13.5.2", "description": "The real PostgreSQL query parser", "homepage": "https://github.com/launchql/libpg-query-node", "main": "./wasm/index.cjs", @@ -49,4 +49,4 @@ "plpgsql", "database" ] -} \ No newline at end of file +} diff --git a/versions/13/src/index.ts b/versions/13/src/index.ts index 28bfd9e4..ef2d0472 100644 --- a/versions/13/src/index.ts +++ b/versions/13/src/index.ts @@ -56,7 +56,7 @@ export const parse = awaitInit(async (query: string) => { try { resultPtr = wasmModule._wasm_parse_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } return JSON.parse(resultStr); @@ -74,7 +74,7 @@ export function parseSync(query: string) { try { resultPtr = wasmModule._wasm_parse_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } return JSON.parse(resultStr); diff --git a/versions/14/src/index.ts b/versions/14/src/index.ts index 28bfd9e4..ef2d0472 100644 --- a/versions/14/src/index.ts +++ b/versions/14/src/index.ts @@ -56,7 +56,7 @@ export const parse = awaitInit(async (query: string) => { try { resultPtr = wasmModule._wasm_parse_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } return JSON.parse(resultStr); @@ -74,7 +74,7 @@ export function parseSync(query: string) { try { resultPtr = wasmModule._wasm_parse_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } return JSON.parse(resultStr); diff --git a/versions/15/src/index.ts b/versions/15/src/index.ts index 28bfd9e4..ef2d0472 100644 --- a/versions/15/src/index.ts +++ b/versions/15/src/index.ts @@ -56,7 +56,7 @@ export const parse = awaitInit(async (query: string) => { try { resultPtr = wasmModule._wasm_parse_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } return JSON.parse(resultStr); @@ -74,7 +74,7 @@ export function parseSync(query: string) { try { resultPtr = wasmModule._wasm_parse_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } return JSON.parse(resultStr); diff --git a/versions/16/src/index.ts b/versions/16/src/index.ts index 28bfd9e4..ef2d0472 100644 --- a/versions/16/src/index.ts +++ b/versions/16/src/index.ts @@ -56,7 +56,7 @@ export const parse = awaitInit(async (query: string) => { try { resultPtr = wasmModule._wasm_parse_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } return JSON.parse(resultStr); @@ -74,7 +74,7 @@ export function parseSync(query: string) { try { resultPtr = wasmModule._wasm_parse_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } return JSON.parse(resultStr); diff --git a/versions/17/src/index.ts b/versions/17/src/index.ts index 28bfd9e4..ef2d0472 100644 --- a/versions/17/src/index.ts +++ b/versions/17/src/index.ts @@ -56,7 +56,7 @@ export const parse = awaitInit(async (query: string) => { try { resultPtr = wasmModule._wasm_parse_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } return JSON.parse(resultStr); @@ -74,7 +74,7 @@ export function parseSync(query: string) { try { resultPtr = wasmModule._wasm_parse_query(queryPtr); const resultStr = ptrToString(resultPtr); - if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.includes('ERROR')) { + if (resultStr.startsWith('syntax error') || resultStr.startsWith('deparse error') || resultStr.startsWith('ERROR')) { throw new Error(resultStr); } return JSON.parse(resultStr);