plpgsql-parse 0.2.6 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/deparse.js CHANGED
@@ -10,7 +10,7 @@
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
11
  exports.deparseSync = deparseSync;
12
12
  exports.deparse = deparse;
13
- const parser_1 = require("@libpg-query/parser");
13
+ const libpg_query_1 = require("libpg-query");
14
14
  const pgsql_parse_1 = require("pgsql-parse");
15
15
  const pgsql_deparser_1 = require("pgsql-deparser");
16
16
  const plpgsql_deparser_1 = require("plpgsql-deparser");
@@ -88,7 +88,7 @@ function deparseWithBodyComments(rawStmt, fnComments, pretty) {
88
88
  if (!cleanSql)
89
89
  return null;
90
90
  // Parse PL/pgSQL from the clean SQL
91
- const plpgsqlRaw = (0, parser_1.parsePlPgSQLSync)(cleanSql);
91
+ const plpgsqlRaw = (0, libpg_query_1.parsePlPgSQLSync)(cleanSql);
92
92
  const { ast: hydrated } = (0, plpgsql_deparser_1.hydratePlpgsqlAst)(plpgsqlRaw);
93
93
  const dehydrated = (0, plpgsql_deparser_1.dehydratePlpgsqlAst)(hydrated);
94
94
  const plpgsqlFunc = dehydrated.plpgsql_funcs?.[0]?.PLpgSQL_function;
@@ -152,10 +152,21 @@ function reinjectBodyComments(originalBody, deparsedBody, comments, plpgsqlAst)
152
152
  const stmtKeywords = buildStmtKeywords(plpgsqlAst);
153
153
  let stmtKeyIdx = 0;
154
154
  const usedAnchors = new Set();
155
+ // Track DECLARE sections: lines between DECLARE and the following BEGIN
156
+ // are variable declarations, not statements, and must not consume
157
+ // statement keyword matches (e.g. a declaration `v_x int;` would
158
+ // otherwise match an assignment to `v_x`).
159
+ let inDeclare = false;
155
160
  for (const line of depLines) {
156
161
  const trimmed = line.trim().toUpperCase();
162
+ if (trimmed === 'DECLARE') {
163
+ inDeclare = true;
164
+ }
165
+ else if (inDeclare && trimmed.startsWith('BEGIN')) {
166
+ inDeclare = false;
167
+ }
157
168
  // Try to match this line to the next expected statement
158
- if (stmtKeyIdx < stmtKeywords.length) {
169
+ if (!inDeclare && stmtKeyIdx < stmtKeywords.length) {
159
170
  const { lineno, keywords } = stmtKeywords[stmtKeyIdx];
160
171
  if (lineMatchesKeywords(trimmed, keywords)) {
161
172
  // Insert comments anchored to this statement
@@ -505,19 +516,24 @@ function findLastEndLine(lines) {
505
516
  }
506
517
  /**
507
518
  * Replace the function body in a CREATE FUNCTION AST node.
519
+ * The body is padded with newlines so it renders as
520
+ * `AS $$\n<body>\n$$` rather than gluing onto the dollar quotes.
508
521
  */
509
522
  function stitchBodyIntoAst(createFunctionStmt, newBody) {
510
523
  if (!createFunctionStmt?.options)
511
524
  return;
525
+ const padded = (newBody.startsWith('\n') ? '' : '\n') +
526
+ newBody +
527
+ (newBody.endsWith('\n') ? '' : '\n');
512
528
  for (const opt of createFunctionStmt.options) {
513
529
  if (opt?.DefElem?.defname === 'as') {
514
530
  const arg = opt.DefElem.arg;
515
531
  if (arg?.List?.items?.[0]?.String) {
516
- arg.List.items[0].String.sval = newBody;
532
+ arg.List.items[0].String.sval = padded;
517
533
  return;
518
534
  }
519
535
  if (arg?.String) {
520
- arg.String.sval = newBody;
536
+ arg.String.sval = padded;
521
537
  return;
522
538
  }
523
539
  }
package/esm/deparse.js CHANGED
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * This module does NOT modify plpgsql-deparser or pgsql-deparser.
8
8
  */
9
- import { parsePlPgSQLSync, } from '@libpg-query/parser';
9
+ import { parsePlPgSQLSync, } from 'libpg-query';
10
10
  import { isRawComment, isRawWhitespace, isRawStmt, } from 'pgsql-parse';
11
11
  import { Deparser } from 'pgsql-deparser';
12
12
  import { hydratePlpgsqlAst, dehydratePlpgsqlAst, deparseFunctionSync, } from 'plpgsql-deparser';
@@ -148,10 +148,21 @@ function reinjectBodyComments(originalBody, deparsedBody, comments, plpgsqlAst)
148
148
  const stmtKeywords = buildStmtKeywords(plpgsqlAst);
149
149
  let stmtKeyIdx = 0;
150
150
  const usedAnchors = new Set();
151
+ // Track DECLARE sections: lines between DECLARE and the following BEGIN
152
+ // are variable declarations, not statements, and must not consume
153
+ // statement keyword matches (e.g. a declaration `v_x int;` would
154
+ // otherwise match an assignment to `v_x`).
155
+ let inDeclare = false;
151
156
  for (const line of depLines) {
152
157
  const trimmed = line.trim().toUpperCase();
158
+ if (trimmed === 'DECLARE') {
159
+ inDeclare = true;
160
+ }
161
+ else if (inDeclare && trimmed.startsWith('BEGIN')) {
162
+ inDeclare = false;
163
+ }
153
164
  // Try to match this line to the next expected statement
154
- if (stmtKeyIdx < stmtKeywords.length) {
165
+ if (!inDeclare && stmtKeyIdx < stmtKeywords.length) {
155
166
  const { lineno, keywords } = stmtKeywords[stmtKeyIdx];
156
167
  if (lineMatchesKeywords(trimmed, keywords)) {
157
168
  // Insert comments anchored to this statement
@@ -501,19 +512,24 @@ function findLastEndLine(lines) {
501
512
  }
502
513
  /**
503
514
  * Replace the function body in a CREATE FUNCTION AST node.
515
+ * The body is padded with newlines so it renders as
516
+ * `AS $$\n<body>\n$$` rather than gluing onto the dollar quotes.
504
517
  */
505
518
  function stitchBodyIntoAst(createFunctionStmt, newBody) {
506
519
  if (!createFunctionStmt?.options)
507
520
  return;
521
+ const padded = (newBody.startsWith('\n') ? '' : '\n') +
522
+ newBody +
523
+ (newBody.endsWith('\n') ? '' : '\n');
508
524
  for (const opt of createFunctionStmt.options) {
509
525
  if (opt?.DefElem?.defname === 'as') {
510
526
  const arg = opt.DefElem.arg;
511
527
  if (arg?.List?.items?.[0]?.String) {
512
- arg.List.items[0].String.sval = newBody;
528
+ arg.List.items[0].String.sval = padded;
513
529
  return;
514
530
  }
515
531
  if (arg?.String) {
516
- arg.String.sval = newBody;
532
+ arg.String.sval = padded;
517
533
  return;
518
534
  }
519
535
  }
package/esm/parse.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * This module does NOT modify plpgsql-parser or pgsql-parse — it
7
7
  * composes them and adds body-comment metadata on top.
8
8
  */
9
- import { parseSync as parseSqlSync, loadModule, } from '@libpg-query/parser';
9
+ import { parseSync as parseSqlSync, loadModule, } from 'libpg-query';
10
10
  import { parseSync as pgsqlParseSync } from 'pgsql-parse';
11
11
  import { scanBodyComments } from './body-scanner';
12
12
  export { loadModule };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plpgsql-parse",
3
- "version": "0.2.6",
3
+ "version": "1.0.0",
4
4
  "author": "Constructive <developers@constructive.io>",
5
5
  "description": "Comment and whitespace preserving PL/pgSQL parser",
6
6
  "main": "index.js",
@@ -41,14 +41,14 @@
41
41
  "round-trip"
42
42
  ],
43
43
  "dependencies": {
44
- "@libpg-query/parser": "^17.6.10",
45
- "@pgsql/types": "^17.6.2",
46
- "pgsql-deparser": "17.18.5",
47
- "pgsql-parse": "0.2.2",
48
- "plpgsql-deparser": "0.7.13"
44
+ "@pgsql/types": "^18.0.0",
45
+ "libpg-query": "18.1.1",
46
+ "pgsql-deparser": "18.0.0",
47
+ "pgsql-parse": "1.0.0",
48
+ "plpgsql-deparser": "1.0.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "makage": "^0.1.8"
52
52
  },
53
- "gitHead": "346e2f48387747c8e8543ffcfe1ddf7883cf6bbb"
53
+ "gitHead": "f700ee16d18aeacd2788eeb4410d73928cd11a5f"
54
54
  }
package/parse.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * This module does NOT modify plpgsql-parser or pgsql-parse — it
7
7
  * composes them and adds body-comment metadata on top.
8
8
  */
9
- import { loadModule } from '@libpg-query/parser';
9
+ import { loadModule } from 'libpg-query';
10
10
  import type { PlpgsqlParseResult } from './types';
11
11
  export { loadModule };
12
12
  /**
package/parse.js CHANGED
@@ -11,8 +11,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
11
11
  exports.loadModule = void 0;
12
12
  exports.parseSync = parseSync;
13
13
  exports.parse = parse;
14
- const parser_1 = require("@libpg-query/parser");
15
- Object.defineProperty(exports, "loadModule", { enumerable: true, get: function () { return parser_1.loadModule; } });
14
+ const libpg_query_1 = require("libpg-query");
15
+ Object.defineProperty(exports, "loadModule", { enumerable: true, get: function () { return libpg_query_1.loadModule; } });
16
16
  const pgsql_parse_1 = require("pgsql-parse");
17
17
  const body_scanner_1 = require("./body-scanner");
18
18
  /**
@@ -68,7 +68,7 @@ function parseSync(sql) {
68
68
  // 1. Outer SQL: use pgsql-parse for comment/whitespace preservation
69
69
  const enhanced = (0, pgsql_parse_1.parseSync)(sql);
70
70
  // 2. Also parse with the standard SQL parser to get statement ASTs
71
- const sqlResult = (0, parser_1.parseSync)(sql);
71
+ const sqlResult = (0, libpg_query_1.parseSync)(sql);
72
72
  const stmts = sqlResult.stmts ?? [];
73
73
  // 3. For each PL/pgSQL function, extract body comments
74
74
  const functions = [];