From d5b70b765dd940b611265c5f7ea46c11c40bb5f7 Mon Sep 17 00:00:00 2001 From: Valentin Nemcev Date: Fri, 15 Nov 2024 19:06:55 +0200 Subject: [PATCH] Update pg-query-emscripten to 5.1.0 --- package-lock.json | 6 +++-- package.json | 2 +- src/kinds/parseViewDefinition.test.ts | 28 +++++++++++------------ src/kinds/parseViewDefinition.ts | 33 ++++++++++++++++++--------- src/pg-query-emscripten.d.ts | 2 +- 5 files changed, 42 insertions(+), 29 deletions(-) diff --git a/package-lock.json b/package-lock.json index d45c6f2e..69bff07f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "jsonpath": "^1.1.1", "knex": "3.1.0", "pg": "8.13.0", - "pg-query-emscripten": "^0.1.0", + "pg-query-emscripten": "^5.1.0", "ramda": "^0.30.0", "tagged-comment-parser": "^1.3.3" }, @@ -10651,7 +10651,9 @@ "license": "MIT" }, "node_modules/pg-query-emscripten": { - "version": "0.1.0", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/pg-query-emscripten/-/pg-query-emscripten-5.1.0.tgz", + "integrity": "sha512-H1ZWOzLRddmHuE4GZqFjjo55hA9zMiePz/WDDGANA/EnvILCJps9pcRucyGd+MFvapeYOy6TWSYz6DbtBOaxRQ==", "license": "MIT" }, "node_modules/pg-types": { diff --git a/package.json b/package.json index 0ae87a90..cf696e16 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "jsonpath": "^1.1.1", "knex": "3.1.0", "pg": "8.13.0", - "pg-query-emscripten": "^0.1.0", + "pg-query-emscripten": "^5.1.0", "ramda": "^0.30.0", "tagged-comment-parser": "^1.3.3" }, diff --git a/src/kinds/parseViewDefinition.test.ts b/src/kinds/parseViewDefinition.test.ts index 125bc915..3cbfd074 100644 --- a/src/kinds/parseViewDefinition.test.ts +++ b/src/kinds/parseViewDefinition.test.ts @@ -3,10 +3,10 @@ import { describe, expect, it } from "vitest"; import parseViewDefinition from "./parseViewDefinition"; describe("parseViewDefinition", () => { - it("should understand a trivial select", () => { + it("should understand a trivial select", async () => { const query = `SELECT id FROM service`; - const def = parseViewDefinition(query, "public"); + const def = await parseViewDefinition(query, "public"); expect(def).toEqual([ { viewColumn: "id", @@ -19,10 +19,10 @@ describe("parseViewDefinition", () => { ]); }); - it("should understand a select with explicit schema", () => { + it("should understand a select with explicit schema", async () => { const query = `SELECT id FROM store.service`; - const def = parseViewDefinition(query, "public"); + const def = await parseViewDefinition(query, "public"); expect(def).toEqual([ { viewColumn: "id", @@ -35,7 +35,7 @@ describe("parseViewDefinition", () => { ]); }); - it("should understand a select with join", () => { + it("should understand a select with join", async () => { const query = `SELECT service.id, service."createdAt", service.name, @@ -43,7 +43,7 @@ describe("parseViewDefinition", () => { FROM service LEFT JOIN "oauthConnection" ON service."oauthConnectionId" = "oauthConnection".id;`; - const def = parseViewDefinition(query, "public"); + const def = await parseViewDefinition(query, "public"); expect(def).toEqual([ { viewColumn: "id", @@ -80,14 +80,14 @@ describe("parseViewDefinition", () => { ]); }); - it("should work with multiple schemas and with aliases", () => { + it("should work with multiple schemas and with aliases", async () => { const query = ` select u.id as uid, um.id as umid from test1.users u join test2.user_managers um on um.user_id = u.id;`; - const def = parseViewDefinition(query, "public"); + const def = await parseViewDefinition(query, "public"); expect(def).toEqual([ { viewColumn: "uid", @@ -108,7 +108,7 @@ describe("parseViewDefinition", () => { ]); }); - it("should return undefined for unresolvable columns", () => { + it("should return undefined for unresolvable columns", async () => { const query = ` SELECT cu.customer_id AS id, (cu.first_name::text || ' '::text) || cu.last_name::text AS name, @@ -127,7 +127,7 @@ describe("parseViewDefinition", () => { JOIN city ON a.city_id = city.city_id JOIN country ON city.country_id = country.country_id;`; - const def = parseViewDefinition(query, "public"); + const def = await parseViewDefinition(query, "public"); expect(def).toEqual([ { viewColumn: "id", @@ -196,7 +196,7 @@ describe("parseViewDefinition", () => { ]); }); - it("should work with a minimalistic WITH clause", () => { + it("should work with a minimalistic WITH clause", async () => { const query = ` WITH RECURSIVE hierarchy_cte AS ( SELECT posting.date, @@ -211,7 +211,7 @@ describe("parseViewDefinition", () => { FROM hierarchy_cte; `; - const def = parseViewDefinition(query, "public"); + const def = await parseViewDefinition(query, "public"); expect(def).toEqual([ { @@ -241,7 +241,7 @@ describe("parseViewDefinition", () => { ]); }); - it("should resolve kanel#481", () => { + it("should resolve kanel#481", async () => { const query = ` WITH RECURSIVE hierarchy_cte AS ( SELECT posting.date, @@ -262,7 +262,7 @@ describe("parseViewDefinition", () => { FROM hierarchy_cte; `; - const def = parseViewDefinition(query, "public"); + const def = await parseViewDefinition(query, "public"); expect(def).toEqual([ { diff --git a/src/kinds/parseViewDefinition.ts b/src/kinds/parseViewDefinition.ts index 782e8cd1..ba6bc10b 100644 --- a/src/kinds/parseViewDefinition.ts +++ b/src/kinds/parseViewDefinition.ts @@ -1,7 +1,17 @@ import jp from "jsonpath"; -import pgQuery from "pg-query-emscripten"; import { last } from "ramda"; +let pgQueryInstance: any; +const getPgQuery = async () => { + if (!pgQueryInstance) { + const { default: pgQueryModule } = await import( + "pg-query-emscripten/pg_query_wasm" + ); + pgQueryInstance = await new pgQueryModule(); + } + return pgQueryInstance; +}; + export type ViewReference = { viewColumn: string; source: @@ -21,8 +31,8 @@ function parseSelectStmt( if (selectAst.larg && selectAst.rarg) { // This is a UNION, INTERSECT, or EXCEPT operation return [ - ...parseSelectStmt(selectAst.larg.SelectStmt, defaultSchema, aliases), - ...parseSelectStmt(selectAst.rarg.SelectStmt, defaultSchema, aliases), + ...parseSelectStmt(selectAst.larg, defaultSchema, aliases), + ...parseSelectStmt(selectAst.rarg, defaultSchema, aliases), ]; } @@ -34,7 +44,7 @@ function parseSelectStmt( const selectTargets = jp.query(selectAst, "$.targetList[*].ResTarget"); selectTargets.forEach((selectTarget: any) => { - const fields = jp.query(selectTarget, "$.val[*].fields[*].String.str"); + const fields = jp.query(selectTarget, "$.val[*].fields[*].String.sval"); let sourceTable = fromTable?.relname; let sourceSchema = fromTable?.schemaname; if (fields.length === 2) { @@ -65,12 +75,13 @@ function parseSelectStmt( return viewReferences; } -function parseViewDefinition( +async function parseViewDefinition( selectStatement: string, defaultSchema: string, -): ViewReference[] { - const ast = pgQuery.parse(selectStatement).parse_tree[0]; - const selectAst = ast.RawStmt?.stmt?.SelectStmt; +): Promise { + const pgQuery = await getPgQuery(); + const ast = pgQuery.parse(selectStatement).parse_tree.stmts[0]; + const selectAst = ast?.stmt?.SelectStmt; if (!selectAst) { throw new Error( @@ -80,17 +91,17 @@ function parseViewDefinition( const aliasDefinitions = jp.query( ast, - "$.RawStmt.stmt.SelectStmt.fromClause..[?(@.alias)]", + "$.stmt.SelectStmt.fromClause..[?(@.alias)]", ); const aliases = Object.fromEntries( aliasDefinitions.map(({ schemaname, relname, alias }) => [ - alias.Alias.aliasname, + alias.aliasname, { schema: schemaname, table: relname }, ]), ); - const withClauses = selectAst.withClause?.WithClause?.ctes || []; + const withClauses = selectAst.withClause?.ctes || []; const cteAliases: Record = {}; diff --git a/src/pg-query-emscripten.d.ts b/src/pg-query-emscripten.d.ts index a29118c8..3593be4d 100644 --- a/src/pg-query-emscripten.d.ts +++ b/src/pg-query-emscripten.d.ts @@ -1 +1 @@ -declare module "pg-query-emscripten"; +declare module "pg-query-emscripten/pg_query_wasm";