pgsql-deparser 16.0.0 → 17.1.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.
Files changed (35) hide show
  1. package/README.md +45 -88
  2. package/deparser.d.ts +253 -0
  3. package/{deparser/deparser.js → deparser.js} +180 -579
  4. package/esm/{deparser/deparser.js → deparser.js} +180 -579
  5. package/esm/index.js +3 -15
  6. package/esm/utils/index.js +90 -0
  7. package/esm/{deparser/utils → utils}/list-utils.js +0 -4
  8. package/esm/{deparser/utils → utils}/quote-utils.js +0 -34
  9. package/esm/utils/sql-formatter.js +23 -0
  10. package/esm/{deparser/visitors → visitors}/base.js +0 -4
  11. package/index.d.ts +3 -9
  12. package/index.js +4 -16
  13. package/package.json +27 -14
  14. package/utils/index.d.ts +4 -0
  15. package/utils/index.js +97 -0
  16. package/{deparser/utils → utils}/list-utils.d.ts +0 -4
  17. package/{deparser/utils → utils}/list-utils.js +0 -4
  18. package/utils/quote-utils.d.ts +5 -0
  19. package/{deparser/utils → utils}/quote-utils.js +0 -34
  20. package/{deparser/utils → utils}/sql-formatter.d.ts +1 -7
  21. package/{deparser/utils → utils}/sql-formatter.js +2 -15
  22. package/{deparser/visitors → visitors}/base.d.ts +5 -8
  23. package/{deparser/visitors → visitors}/base.js +0 -4
  24. package/deparser/deparser.d.ts +0 -301
  25. package/deparser/index.d.ts +0 -9
  26. package/deparser/index.js +0 -17
  27. package/deparser/utils/quote-utils.d.ts +0 -24
  28. package/esm/deparser/index.js +0 -13
  29. package/esm/deparser/utils/sql-formatter.js +0 -36
  30. package/esm/v16-to-v17-direct.js +0 -44
  31. package/esm/v16-to-v17.js +0 -1488
  32. package/v16-to-v17-direct.d.ts +0 -21
  33. package/v16-to-v17-direct.js +0 -48
  34. package/v16-to-v17.d.ts +0 -638
  35. package/v16-to-v17.js +0 -1492
@@ -1,119 +1,30 @@
1
1
  "use strict";
2
- /**
3
- * Auto-generated file with types stripped for better tree-shaking
4
- * DO NOT EDIT - Generated by strip-deparser-types.ts
5
- */
6
2
  Object.defineProperty(exports, "__esModule", { value: true });
7
3
  exports.Deparser = void 0;
8
4
  const sql_formatter_1 = require("./utils/sql-formatter");
9
5
  const quote_utils_1 = require("./utils/quote-utils");
10
6
  const list_utils_1 = require("./utils/list-utils");
11
- // Type guards for better type safety
12
- function isParseResult(obj) {
13
- // A ParseResult is an object that could have stmts (but not required)
14
- // and is not already wrapped as a Node
15
- // IMPORTANT: ParseResult.stmts is "repeated RawStmt" in protobuf, meaning
16
- // the array contains RawStmt objects inline (not wrapped as { RawStmt: ... })
17
- // Example: { version: 170004, stmts: [{ stmt: {...}, stmt_len: 32 }] }
18
- return obj && typeof obj === 'object' &&
19
- !Array.isArray(obj) &&
20
- !('ParseResult' in obj) &&
21
- !('RawStmt' in obj) &&
22
- // Check if it looks like a ParseResult (has stmts or version)
23
- ('stmts' in obj || 'version' in obj);
24
- }
25
- function isWrappedParseResult(obj) {
26
- return obj && typeof obj === 'object' && 'ParseResult' in obj;
27
- }
28
- /**
29
- * Deparser - Converts PostgreSQL AST nodes back to SQL strings
30
- *
31
- * Entry Points:
32
- * 1. ParseResult (from libpg-query) - The complete parse result
33
- * Structure: { version: number, stmts: RawStmt[] }
34
- * Note: stmts is "repeated RawStmt" in protobuf, so array contains RawStmt
35
- * objects inline (not wrapped as { RawStmt: ... } nodes)
36
- * Example: { version: 170004, stmts: [{ stmt: {...}, stmt_len: 32 }] }
37
- *
38
- * 2. Wrapped ParseResult - When explicitly wrapped as a Node
39
- * Structure: { ParseResult: { version: number, stmts: RawStmt[] } }
40
- *
41
- * 3. Wrapped RawStmt - When explicitly wrapped as a Node
42
- * Structure: { RawStmt: { stmt: Node, stmt_len?: number } }
43
- *
44
- * 4. Array of Nodes - Multiple statements to deparse
45
- * Can be: Node[] (e.g., SelectStmt, InsertStmt, etc.)
46
- *
47
- * 5. Single Node - Individual statement node
48
- * Example: { SelectStmt: {...} }, { InsertStmt: {...} }, etc.
49
- *
50
- * The deparser automatically detects bare ParseResult objects for backward
51
- * compatibility and wraps them internally for consistent processing.
52
- */
53
7
  class Deparser {
54
8
  formatter;
55
9
  tree;
56
- options;
57
10
  constructor(tree, opts = {}) {
58
- this.formatter = new sql_formatter_1.SqlFormatter(opts.newline, opts.tab, opts.pretty);
59
- // Set default options
60
- this.options = {
61
- functionDelimiter: '$$',
62
- functionDelimiterFallback: '$EOFCODE$',
63
- ...opts
64
- };
65
- // Handle different input types
66
- if (isParseResult(tree)) {
67
- // Duck-typed ParseResult (backward compatibility)
68
- // Wrap it as a proper Node for consistent handling
69
- this.tree = [{ ParseResult: tree }];
70
- }
71
- else if (Array.isArray(tree)) {
72
- // Array of Nodes
73
- this.tree = tree;
11
+ this.formatter = new sql_formatter_1.SqlFormatter(opts.newline, opts.tab);
12
+ // Handle parsed query objects that contain both version and stmts
13
+ if (tree && typeof tree === 'object' && !Array.isArray(tree) && 'stmts' in tree) {
14
+ this.tree = tree.stmts;
74
15
  }
75
16
  else {
76
- // Single Node (including wrapped ParseResult)
77
- this.tree = [tree];
78
- }
79
- }
80
- /**
81
- * Static method to deparse PostgreSQL AST nodes to SQL
82
- * @param query - Can be:
83
- * - ParseResult from libpg-query (e.g., { version: 170004, stmts: [...] })
84
- * - Wrapped ParseResult node (e.g., { ParseResult: {...} })
85
- * - Wrapped RawStmt node (e.g., { RawStmt: {...} })
86
- * - Array of Nodes
87
- * - Single Node (e.g., { SelectStmt: {...} })
88
- * @param opts - Deparser options for formatting
89
- * @returns The deparsed SQL string
90
- */
17
+ this.tree = Array.isArray(tree) ? tree : [tree];
18
+ }
19
+ }
91
20
  static deparse(query, opts = {}) {
92
21
  return new Deparser(query, opts).deparseQuery();
93
22
  }
94
23
  deparseQuery() {
95
24
  return this.tree
96
- .map(node => {
97
- // All nodes should go through the standard deparse method
98
- // which will route to the appropriate handler
99
- const result = this.deparse(node);
100
- return result || '';
101
- })
102
- .filter(result => result !== '')
25
+ .map(node => this.deparse(node))
103
26
  .join(this.formatter.newline() + this.formatter.newline());
104
27
  }
105
- /**
106
- * Get the appropriate function delimiter based on the body content
107
- * @param body The function body to check
108
- * @returns The delimiter to use
109
- */
110
- getFunctionDelimiter(body) {
111
- const delimiter = this.options.functionDelimiter || '$$';
112
- if (body.includes(delimiter)) {
113
- return this.options.functionDelimiterFallback || '$EOFCODE$';
114
- }
115
- return delimiter;
116
- }
117
28
  deparse(node, context = { parentNodeTypes: [] }) {
118
29
  if (node == null) {
119
30
  return null;
@@ -131,10 +42,6 @@ class Deparser {
131
42
  }
132
43
  visit(node, context = { parentNodeTypes: [] }) {
133
44
  const nodeType = this.getNodeType(node);
134
- // Handle empty objects
135
- if (!nodeType) {
136
- return '';
137
- }
138
45
  const nodeData = this.getNodeData(node);
139
46
  const methodName = nodeType;
140
47
  if (typeof this[methodName] === 'function') {
@@ -157,29 +64,24 @@ class Deparser {
157
64
  }
158
65
  return node;
159
66
  }
160
- ParseResult(node, context) {
161
- if (!node.stmts || node.stmts.length === 0) {
162
- return '';
163
- }
164
- // Deparse each RawStmt in the ParseResult
165
- // Note: node.stmts is "repeated RawStmt" so contains RawStmt objects inline
166
- // Each element has structure: { stmt: Node, stmt_len?: number, stmt_location?: number }
167
- return node.stmts
168
- .filter((rawStmt) => rawStmt != null)
169
- .map((rawStmt) => this.RawStmt(rawStmt, context))
170
- .filter((result) => result !== '')
171
- .join(this.formatter.newline() + this.formatter.newline());
172
- }
173
67
  RawStmt(node, context) {
174
- if (!node.stmt) {
175
- return '';
176
- }
177
- const deparsedStmt = this.deparse(node.stmt, context);
178
- // Add semicolon if stmt_len is provided (indicates it had one in original)
179
68
  if (node.stmt_len) {
180
- return deparsedStmt + ';';
69
+ return this.deparse(node.stmt, context) + ';';
70
+ }
71
+ return this.deparse(node.stmt, context);
72
+ }
73
+ stmt(node, context = { parentNodeTypes: [] }) {
74
+ // Handle stmt wrapper nodes that contain the actual statement
75
+ const keys = Object.keys(node);
76
+ if (keys.length === 1) {
77
+ const statementType = keys[0];
78
+ const methodName = statementType;
79
+ if (typeof this[methodName] === 'function') {
80
+ return this[methodName](node[statementType], context);
81
+ }
82
+ throw new Error(`Deparser does not handle statement type: ${statementType}`);
181
83
  }
182
- return deparsedStmt;
84
+ return '';
183
85
  }
184
86
  SelectStmt(node, context) {
185
87
  const output = [];
@@ -188,25 +90,23 @@ class Deparser {
188
90
  }
189
91
  if (!node.op || node.op === 'SETOP_NONE') {
190
92
  if (node.valuesLists == null) {
191
- if (!this.formatter.isPretty() || !node.targetList) {
192
- output.push('SELECT');
193
- }
93
+ output.push('SELECT');
194
94
  }
195
95
  }
196
96
  else {
197
97
  const leftStmt = this.SelectStmt(node.larg, context);
198
98
  const rightStmt = this.SelectStmt(node.rarg, context);
199
99
  // Add parentheses if the operand is a set operation OR has ORDER BY/LIMIT clauses OR has WITH clause
200
- const leftNeedsParens = node.larg && (((node.larg).op && (node.larg).op !== 'SETOP_NONE') ||
201
- (node.larg).sortClause ||
202
- (node.larg).limitCount ||
203
- (node.larg).limitOffset ||
204
- (node.larg).withClause);
205
- const rightNeedsParens = node.rarg && (((node.rarg).op && (node.rarg).op !== 'SETOP_NONE') ||
206
- (node.rarg).sortClause ||
207
- (node.rarg).limitCount ||
208
- (node.rarg).limitOffset ||
209
- (node.rarg).withClause);
100
+ const leftNeedsParens = node.larg && ((node.larg.op && node.larg.op !== 'SETOP_NONE') ||
101
+ node.larg.sortClause ||
102
+ node.larg.limitCount ||
103
+ node.larg.limitOffset ||
104
+ node.larg.withClause);
105
+ const rightNeedsParens = node.rarg && ((node.rarg.op && node.rarg.op !== 'SETOP_NONE') ||
106
+ node.rarg.sortClause ||
107
+ node.rarg.limitCount ||
108
+ node.rarg.limitOffset ||
109
+ node.rarg.withClause);
210
110
  if (leftNeedsParens) {
211
111
  output.push(this.formatter.parens(leftStmt));
212
112
  }
@@ -236,82 +136,41 @@ class Deparser {
236
136
  output.push(rightStmt);
237
137
  }
238
138
  }
239
- // Handle DISTINCT clause - in pretty mode, we'll include it in the SELECT clause
240
- let distinctPart = '';
241
139
  if (node.distinctClause) {
242
140
  const distinctClause = list_utils_1.ListUtils.unwrapList(node.distinctClause);
243
141
  if (distinctClause.length > 0 && Object.keys(distinctClause[0]).length > 0) {
142
+ output.push('DISTINCT ON');
244
143
  const clause = distinctClause
245
144
  .map(e => this.visit(e, { ...context, select: true }))
246
145
  .join(', ');
247
- distinctPart = ' DISTINCT ON ' + this.formatter.parens(clause);
146
+ output.push(this.formatter.parens(clause));
248
147
  }
249
148
  else {
250
- distinctPart = ' DISTINCT';
251
- }
252
- if (!this.formatter.isPretty()) {
253
- if (distinctClause.length > 0 && Object.keys(distinctClause[0]).length > 0) {
254
- output.push('DISTINCT ON');
255
- const clause = distinctClause
256
- .map(e => this.visit(e, { ...context, select: true }))
257
- .join(', ');
258
- output.push(this.formatter.parens(clause));
259
- }
260
- else {
261
- output.push('DISTINCT');
262
- }
149
+ output.push('DISTINCT');
263
150
  }
264
151
  }
265
152
  if (node.targetList) {
266
153
  const targetList = list_utils_1.ListUtils.unwrapList(node.targetList);
267
- if (this.formatter.isPretty()) {
268
- const targetStrings = targetList
269
- .map(e => {
270
- const targetStr = this.visit(e, { ...context, select: true });
271
- if (this.containsMultilineStringLiteral(targetStr)) {
272
- return targetStr;
273
- }
274
- return this.formatter.indent(targetStr);
275
- });
276
- const formattedTargets = targetStrings.join(',' + this.formatter.newline());
277
- output.push('SELECT' + distinctPart);
278
- output.push(formattedTargets);
279
- }
280
- else {
281
- const targets = targetList
282
- .map(e => this.visit(e, { ...context, select: true }))
283
- .join(', ');
284
- output.push(targets);
285
- }
154
+ const targets = targetList
155
+ .map(e => this.visit(e, { ...context, select: true }))
156
+ .join(', ');
157
+ output.push(targets);
286
158
  }
287
159
  if (node.intoClause) {
288
160
  output.push('INTO');
289
161
  output.push(this.IntoClause(node.intoClause, context));
290
162
  }
291
163
  if (node.fromClause) {
164
+ output.push('FROM');
292
165
  const fromList = list_utils_1.ListUtils.unwrapList(node.fromClause);
293
166
  const fromItems = fromList
294
167
  .map(e => this.deparse(e, { ...context, from: true }))
295
168
  .join(', ');
296
- output.push('FROM ' + fromItems.trim());
169
+ output.push(fromItems);
297
170
  }
298
171
  if (node.whereClause) {
299
- if (this.formatter.isPretty()) {
300
- output.push('WHERE');
301
- const whereExpr = this.visit(node.whereClause, context);
302
- const lines = whereExpr.split(this.formatter.newline());
303
- const indentedLines = lines.map((line, index) => {
304
- if (index === 0) {
305
- return this.formatter.indent(line);
306
- }
307
- return line;
308
- });
309
- output.push(indentedLines.join(this.formatter.newline()));
310
- }
311
- else {
312
- output.push('WHERE');
313
- output.push(this.visit(node.whereClause, context));
314
- }
172
+ output.push('WHERE');
173
+ output.push(this.visit(node.whereClause, context));
315
174
  }
316
175
  if (node.valuesLists) {
317
176
  output.push('VALUES');
@@ -322,43 +181,16 @@ class Deparser {
322
181
  output.push(lists.join(', '));
323
182
  }
324
183
  if (node.groupClause) {
184
+ output.push('GROUP BY');
325
185
  const groupList = list_utils_1.ListUtils.unwrapList(node.groupClause);
326
- if (this.formatter.isPretty()) {
327
- const groupItems = groupList
328
- .map(e => {
329
- const groupStr = this.visit(e, { ...context, group: true });
330
- if (this.containsMultilineStringLiteral(groupStr)) {
331
- return groupStr;
332
- }
333
- return this.formatter.indent(groupStr);
334
- })
335
- .join(',' + this.formatter.newline());
336
- output.push('GROUP BY');
337
- output.push(groupItems);
338
- }
339
- else {
340
- output.push('GROUP BY');
341
- const groupItems = groupList
342
- .map(e => this.visit(e, { ...context, group: true }))
343
- .join(', ');
344
- output.push(groupItems);
345
- }
186
+ const groupItems = groupList
187
+ .map(e => this.visit(e, { ...context, group: true }))
188
+ .join(', ');
189
+ output.push(groupItems);
346
190
  }
347
191
  if (node.havingClause) {
348
- if (this.formatter.isPretty()) {
349
- output.push('HAVING');
350
- const havingStr = this.visit(node.havingClause, context);
351
- if (this.containsMultilineStringLiteral(havingStr)) {
352
- output.push(havingStr);
353
- }
354
- else {
355
- output.push(this.formatter.indent(havingStr));
356
- }
357
- }
358
- else {
359
- output.push('HAVING');
360
- output.push(this.visit(node.havingClause, context));
361
- }
192
+ output.push('HAVING');
193
+ output.push(this.visit(node.havingClause, context));
362
194
  }
363
195
  if (node.windowClause) {
364
196
  output.push('WINDOW');
@@ -369,33 +201,20 @@ class Deparser {
369
201
  output.push(windowClauses);
370
202
  }
371
203
  if (node.sortClause) {
204
+ output.push('ORDER BY');
372
205
  const sortList = list_utils_1.ListUtils.unwrapList(node.sortClause);
373
- if (this.formatter.isPretty()) {
374
- const sortItems = sortList
375
- .map(e => {
376
- const sortStr = this.visit(e, { ...context, sort: true });
377
- if (this.containsMultilineStringLiteral(sortStr)) {
378
- return sortStr;
379
- }
380
- return this.formatter.indent(sortStr);
381
- })
382
- .join(',' + this.formatter.newline());
383
- output.push('ORDER BY');
384
- output.push(sortItems);
385
- }
386
- else {
387
- output.push('ORDER BY');
388
- const sortItems = sortList
389
- .map(e => this.visit(e, { ...context, sort: true }))
390
- .join(', ');
391
- output.push(sortItems);
392
- }
206
+ const sortItems = sortList
207
+ .map(e => this.visit(e, { ...context, sort: true }))
208
+ .join(', ');
209
+ output.push(sortItems);
393
210
  }
394
211
  if (node.limitCount) {
395
- output.push('LIMIT ' + this.visit(node.limitCount, context));
212
+ output.push('LIMIT');
213
+ output.push(this.visit(node.limitCount, context));
396
214
  }
397
215
  if (node.limitOffset) {
398
- output.push('OFFSET ' + this.visit(node.limitOffset, context));
216
+ output.push('OFFSET');
217
+ output.push(this.visit(node.limitOffset, context));
399
218
  }
400
219
  if (node.lockingClause) {
401
220
  const lockingList = list_utils_1.ListUtils.unwrapList(node.lockingClause);
@@ -404,10 +223,6 @@ class Deparser {
404
223
  .join(' ');
405
224
  output.push(lockingClauses);
406
225
  }
407
- if (this.formatter.isPretty()) {
408
- const filteredOutput = output.filter(item => item.trim() !== '');
409
- return filteredOutput.join(this.formatter.newline());
410
- }
411
226
  return output.join(' ');
412
227
  }
413
228
  A_Expr(node, context) {
@@ -472,38 +287,18 @@ class Deparser {
472
287
  'ALL',
473
288
  this.formatter.parens(this.visit(rexpr, context))
474
289
  ]);
475
- case 'AEXPR_DISTINCT': {
476
- let leftExpr = this.visit(lexpr, context);
477
- let rightExpr = this.visit(rexpr, context);
478
- // Add parentheses for complex expressions
479
- if (lexpr && this.isComplexExpression(lexpr)) {
480
- leftExpr = this.formatter.parens(leftExpr);
481
- }
482
- if (rexpr && this.isComplexExpression(rexpr)) {
483
- rightExpr = this.formatter.parens(rightExpr);
484
- }
290
+ case 'AEXPR_DISTINCT':
485
291
  return this.formatter.format([
486
- leftExpr,
292
+ this.visit(lexpr, context),
487
293
  'IS DISTINCT FROM',
488
- rightExpr
294
+ this.visit(rexpr, context)
489
295
  ]);
490
- }
491
- case 'AEXPR_NOT_DISTINCT': {
492
- let leftExpr = this.visit(lexpr, context);
493
- let rightExpr = this.visit(rexpr, context);
494
- // Add parentheses for complex expressions
495
- if (lexpr && this.isComplexExpression(lexpr)) {
496
- leftExpr = this.formatter.parens(leftExpr);
497
- }
498
- if (rexpr && this.isComplexExpression(rexpr)) {
499
- rightExpr = this.formatter.parens(rightExpr);
500
- }
296
+ case 'AEXPR_NOT_DISTINCT':
501
297
  return this.formatter.format([
502
- leftExpr,
298
+ this.visit(lexpr, context),
503
299
  'IS NOT DISTINCT FROM',
504
- rightExpr
300
+ this.visit(rexpr, context)
505
301
  ]);
506
- }
507
302
  case 'AEXPR_NULLIF':
508
303
  return this.formatter.format([
509
304
  'NULLIF',
@@ -897,24 +692,9 @@ class Deparser {
897
692
  if (node.recursive) {
898
693
  output.push('RECURSIVE');
899
694
  }
900
- if (node.ctes && node.ctes.length > 0) {
901
- const ctes = list_utils_1.ListUtils.unwrapList(node.ctes);
902
- if (this.formatter.isPretty()) {
903
- const cteStrings = ctes.map((cte, index) => {
904
- const cteStr = this.visit(cte, context);
905
- const prefix = index === 0 ? this.formatter.newline() : ',' + this.formatter.newline();
906
- if (this.containsMultilineStringLiteral(cteStr)) {
907
- return prefix + cteStr;
908
- }
909
- return prefix + this.formatter.indent(cteStr);
910
- });
911
- output.push(cteStrings.join(''));
912
- }
913
- else {
914
- const cteStrings = ctes.map(cte => this.visit(cte, context));
915
- output.push(cteStrings.join(', '));
916
- }
917
- }
695
+ const ctes = list_utils_1.ListUtils.unwrapList(node.ctes);
696
+ const cteStrs = ctes.map(cte => this.visit(cte, context));
697
+ output.push(cteStrs.join(', '));
918
698
  return output.join(' ');
919
699
  }
920
700
  ResTarget(node, context) {
@@ -993,28 +773,13 @@ class Deparser {
993
773
  formatStr = '(%s)';
994
774
  }
995
775
  const boolContext = { ...context, bool: true };
996
- // explanation of our syntax/fix below:
997
- // return formatStr.replace('%s', andArgs); // ❌ Interprets $ as special syntax
998
- // return formatStr.replace('%s', () => andArgs); // ✅ Function callback prevents interpretation
999
776
  switch (boolop) {
1000
777
  case 'AND_EXPR':
1001
- if (this.formatter.isPretty() && args.length > 1) {
1002
- const andArgs = args.map(arg => this.visit(arg, boolContext)).join(this.formatter.newline() + ' AND ');
1003
- return formatStr.replace('%s', () => andArgs);
1004
- }
1005
- else {
1006
- const andArgs = args.map(arg => this.visit(arg, boolContext)).join(' AND ');
1007
- return formatStr.replace('%s', () => andArgs);
1008
- }
778
+ const andArgs = args.map(arg => this.visit(arg, boolContext)).join(' AND ');
779
+ return formatStr.replace('%s', andArgs);
1009
780
  case 'OR_EXPR':
1010
- if (this.formatter.isPretty() && args.length > 1) {
1011
- const orArgs = args.map(arg => this.visit(arg, boolContext)).join(this.formatter.newline() + ' OR ');
1012
- return formatStr.replace('%s', () => orArgs);
1013
- }
1014
- else {
1015
- const orArgs = args.map(arg => this.visit(arg, boolContext)).join(' OR ');
1016
- return formatStr.replace('%s', () => orArgs);
1017
- }
781
+ const orArgs = args.map(arg => this.visit(arg, boolContext)).join(' OR ');
782
+ return formatStr.replace('%s', orArgs);
1018
783
  case 'NOT_EXPR':
1019
784
  return `NOT (${this.visit(args[0], context)})`;
1020
785
  default:
@@ -1216,13 +981,7 @@ class Deparser {
1216
981
  windowParts.push(frameClause);
1217
982
  }
1218
983
  if (windowParts.length > 0) {
1219
- if (this.formatter.isPretty() && windowParts.length > 1) {
1220
- const formattedParts = windowParts.map(part => this.formatter.indent(part));
1221
- result += ` OVER (${this.formatter.newline()}${formattedParts.join(this.formatter.newline())}${this.formatter.newline()})`;
1222
- }
1223
- else {
1224
- result += ` OVER (${windowParts.join(' ')})`;
1225
- }
984
+ result += ` OVER (${windowParts.join(' ')})`;
1226
985
  }
1227
986
  else {
1228
987
  result += ` OVER ()`;
@@ -1279,23 +1038,23 @@ class Deparser {
1279
1038
  else if (nodeAny.sval !== undefined) {
1280
1039
  if (typeof nodeAny.sval === 'object' && nodeAny.sval !== null) {
1281
1040
  if (nodeAny.sval.sval !== undefined) {
1282
- return quote_utils_1.QuoteUtils.formatEString(nodeAny.sval.sval);
1041
+ return quote_utils_1.QuoteUtils.escape(nodeAny.sval.sval);
1283
1042
  }
1284
1043
  else if (nodeAny.sval.String && nodeAny.sval.String.sval !== undefined) {
1285
- return quote_utils_1.QuoteUtils.formatEString(nodeAny.sval.String.sval);
1044
+ return quote_utils_1.QuoteUtils.escape(nodeAny.sval.String.sval);
1286
1045
  }
1287
1046
  else if (Object.keys(nodeAny.sval).length === 0) {
1288
1047
  return "''";
1289
1048
  }
1290
1049
  else {
1291
- return quote_utils_1.QuoteUtils.formatEString(nodeAny.sval.toString());
1050
+ return quote_utils_1.QuoteUtils.escape(nodeAny.sval.toString());
1292
1051
  }
1293
1052
  }
1294
1053
  else if (nodeAny.sval === null) {
1295
1054
  return 'NULL';
1296
1055
  }
1297
1056
  else {
1298
- return quote_utils_1.QuoteUtils.formatEString(nodeAny.sval);
1057
+ return quote_utils_1.QuoteUtils.escape(nodeAny.sval);
1299
1058
  }
1300
1059
  }
1301
1060
  else if (nodeAny.boolval !== undefined) {
@@ -1434,7 +1193,7 @@ class Deparser {
1434
1193
  }
1435
1194
  let args = null;
1436
1195
  if (node.typmods) {
1437
- const isInterval = names.some((name) => {
1196
+ const isInterval = names.some(name => {
1438
1197
  const nameStr = typeof name === 'string' ? name : (name.String?.sval || name.String?.str);
1439
1198
  return nameStr === 'interval';
1440
1199
  });
@@ -1603,14 +1362,7 @@ class Deparser {
1603
1362
  output.push('ONLY');
1604
1363
  }
1605
1364
  let tableName = '';
1606
- if (node.catalogname) {
1607
- tableName = quote_utils_1.QuoteUtils.quote(node.catalogname);
1608
- if (node.schemaname) {
1609
- tableName += '.' + quote_utils_1.QuoteUtils.quote(node.schemaname);
1610
- }
1611
- tableName += '.' + quote_utils_1.QuoteUtils.quote(node.relname);
1612
- }
1613
- else if (node.schemaname) {
1365
+ if (node.schemaname) {
1614
1366
  tableName = quote_utils_1.QuoteUtils.quote(node.schemaname) + '.' + quote_utils_1.QuoteUtils.quote(node.relname);
1615
1367
  }
1616
1368
  else {
@@ -1846,39 +1598,15 @@ class Deparser {
1846
1598
  output.push(this.visit(node.arg, context));
1847
1599
  }
1848
1600
  const args = list_utils_1.ListUtils.unwrapList(node.args);
1849
- if (this.formatter.isPretty() && args.length > 0) {
1850
- for (const arg of args) {
1851
- const whenClause = this.visit(arg, context);
1852
- if (this.containsMultilineStringLiteral(whenClause)) {
1853
- output.push(this.formatter.newline() + whenClause);
1854
- }
1855
- else {
1856
- output.push(this.formatter.newline() + this.formatter.indent(whenClause));
1857
- }
1858
- }
1859
- if (node.defresult) {
1860
- const elseResult = this.visit(node.defresult, context);
1861
- if (this.containsMultilineStringLiteral(elseResult)) {
1862
- output.push(this.formatter.newline() + 'ELSE ' + elseResult);
1863
- }
1864
- else {
1865
- output.push(this.formatter.newline() + this.formatter.indent('ELSE ' + elseResult));
1866
- }
1867
- }
1868
- output.push(this.formatter.newline() + 'END');
1869
- return output.join(' ');
1601
+ for (const arg of args) {
1602
+ output.push(this.visit(arg, context));
1870
1603
  }
1871
- else {
1872
- for (const arg of args) {
1873
- output.push(this.visit(arg, context));
1874
- }
1875
- if (node.defresult) {
1876
- output.push('ELSE');
1877
- output.push(this.visit(node.defresult, context));
1878
- }
1879
- output.push('END');
1880
- return output.join(' ');
1604
+ if (node.defresult) {
1605
+ output.push('ELSE');
1606
+ output.push(this.visit(node.defresult, context));
1881
1607
  }
1608
+ output.push('END');
1609
+ return output.join(' ');
1882
1610
  }
1883
1611
  CoalesceExpr(node, context) {
1884
1612
  const args = list_utils_1.ListUtils.unwrapList(node.args);
@@ -2013,7 +1741,7 @@ class Deparser {
2013
1741
  }
2014
1742
  String(node, context) {
2015
1743
  if (context.isStringLiteral || context.isEnumValue) {
2016
- return quote_utils_1.QuoteUtils.formatEString(node.sval || '');
1744
+ return `'${node.sval || ''}'`;
2017
1745
  }
2018
1746
  const value = node.sval || '';
2019
1747
  if (context.parentNodeTypes.includes('DefElem') ||
@@ -2091,13 +1819,7 @@ class Deparser {
2091
1819
  const elementStrs = elements.map(el => {
2092
1820
  return this.deparse(el, context);
2093
1821
  });
2094
- if (this.formatter.isPretty()) {
2095
- const formattedElements = elementStrs.map(el => this.formatter.indent(el)).join(',' + this.formatter.newline());
2096
- output.push('(' + this.formatter.newline() + formattedElements + this.formatter.newline() + ')');
2097
- }
2098
- else {
2099
- output.push(this.formatter.parens(elementStrs.join(', ')));
2100
- }
1822
+ output.push(this.formatter.parens(elementStrs.join(', ')));
2101
1823
  }
2102
1824
  else if (!node.partbound) {
2103
1825
  output.push(this.formatter.parens(''));
@@ -2336,9 +2058,6 @@ class Deparser {
2336
2058
  break;
2337
2059
  case 'CONSTR_UNIQUE':
2338
2060
  output.push('UNIQUE');
2339
- if (node.nulls_not_distinct) {
2340
- output.push('NULLS NOT DISTINCT');
2341
- }
2342
2061
  if (node.keys && node.keys.length > 0) {
2343
2062
  const keyList = list_utils_1.ListUtils.unwrapList(node.keys)
2344
2063
  .map(key => this.visit(key, context))
@@ -2382,52 +2101,38 @@ class Deparser {
2382
2101
  }
2383
2102
  }
2384
2103
  if (node.fk_upd_action && node.fk_upd_action !== 'a') {
2385
- let updateClause = 'ON UPDATE ';
2104
+ output.push('ON UPDATE');
2386
2105
  switch (node.fk_upd_action) {
2387
2106
  case 'r':
2388
- updateClause += 'RESTRICT';
2107
+ output.push('RESTRICT');
2389
2108
  break;
2390
2109
  case 'c':
2391
- updateClause += 'CASCADE';
2110
+ output.push('CASCADE');
2392
2111
  break;
2393
2112
  case 'n':
2394
- updateClause += 'SET NULL';
2113
+ output.push('SET NULL');
2395
2114
  break;
2396
2115
  case 'd':
2397
- updateClause += 'SET DEFAULT';
2116
+ output.push('SET DEFAULT');
2398
2117
  break;
2399
2118
  }
2400
- if (this.formatter.isPretty()) {
2401
- output.push('\n' + this.formatter.indent(updateClause));
2402
- }
2403
- else {
2404
- output.push('ON UPDATE');
2405
- output.push(updateClause.replace('ON UPDATE ', ''));
2406
- }
2407
2119
  }
2408
2120
  if (node.fk_del_action && node.fk_del_action !== 'a') {
2409
- let deleteClause = 'ON DELETE ';
2121
+ output.push('ON DELETE');
2410
2122
  switch (node.fk_del_action) {
2411
2123
  case 'r':
2412
- deleteClause += 'RESTRICT';
2124
+ output.push('RESTRICT');
2413
2125
  break;
2414
2126
  case 'c':
2415
- deleteClause += 'CASCADE';
2127
+ output.push('CASCADE');
2416
2128
  break;
2417
2129
  case 'n':
2418
- deleteClause += 'SET NULL';
2130
+ output.push('SET NULL');
2419
2131
  break;
2420
2132
  case 'd':
2421
- deleteClause += 'SET DEFAULT';
2133
+ output.push('SET DEFAULT');
2422
2134
  break;
2423
2135
  }
2424
- if (this.formatter.isPretty()) {
2425
- output.push('\n' + this.formatter.indent(deleteClause));
2426
- }
2427
- else {
2428
- output.push('ON DELETE');
2429
- output.push(deleteClause.replace('ON DELETE ', ''));
2430
- }
2431
2136
  }
2432
2137
  // Handle NOT VALID for foreign key constraints - only for table constraints, not domain constraints
2433
2138
  if (node.skip_validation && !context.isDomainConstraint) {
@@ -2485,48 +2190,17 @@ class Deparser {
2485
2190
  // Handle deferrable constraints for all constraint types that support it
2486
2191
  if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN') {
2487
2192
  if (node.deferrable) {
2488
- if (this.formatter.isPretty() && node.contype === 'CONSTR_FOREIGN') {
2489
- output.push('\n' + this.formatter.indent('DEFERRABLE'));
2490
- if (node.initdeferred === true) {
2491
- output.push('\n' + this.formatter.indent('INITIALLY DEFERRED'));
2492
- }
2493
- else if (node.initdeferred === false) {
2494
- output.push('\n' + this.formatter.indent('INITIALLY IMMEDIATE'));
2495
- }
2193
+ output.push('DEFERRABLE');
2194
+ if (node.initdeferred === true) {
2195
+ output.push('INITIALLY DEFERRED');
2496
2196
  }
2497
- else {
2498
- output.push('DEFERRABLE');
2499
- if (node.initdeferred === true) {
2500
- output.push('INITIALLY DEFERRED');
2501
- }
2502
- else if (node.initdeferred === false) {
2503
- output.push('INITIALLY IMMEDIATE');
2504
- }
2197
+ else if (node.initdeferred === false) {
2198
+ output.push('INITIALLY IMMEDIATE');
2505
2199
  }
2506
2200
  }
2507
2201
  else if (node.deferrable === false) {
2508
- if (this.formatter.isPretty() && node.contype === 'CONSTR_FOREIGN') {
2509
- output.push('\n' + this.formatter.indent('NOT DEFERRABLE'));
2510
- }
2511
- else {
2512
- output.push('NOT DEFERRABLE');
2513
- }
2514
- }
2515
- }
2516
- if (this.formatter.isPretty() && node.contype === 'CONSTR_FOREIGN') {
2517
- let result = '';
2518
- for (let i = 0; i < output.length; i++) {
2519
- if (output[i].startsWith('\n')) {
2520
- result += output[i];
2521
- }
2522
- else {
2523
- if (i > 0 && !output[i - 1].startsWith('\n')) {
2524
- result += ' ';
2525
- }
2526
- result += output[i];
2527
- }
2202
+ output.push('NOT DEFERRABLE');
2528
2203
  }
2529
- return result;
2530
2204
  }
2531
2205
  return output.join(' ');
2532
2206
  }
@@ -3250,9 +2924,11 @@ class Deparser {
3250
2924
  }
3251
2925
  switch (node.jointype) {
3252
2926
  case 'JOIN_INNER':
2927
+ // Handle NATURAL JOIN first - it has isNatural=true (NATURAL already added above)
3253
2928
  if (node.isNatural) {
3254
2929
  joinStr += 'JOIN';
3255
2930
  }
2931
+ // Handle CROSS JOIN case - when there's no quals, no usingClause, and not natural
3256
2932
  else if (!node.quals && (!node.usingClause || node.usingClause.length === 0)) {
3257
2933
  joinStr += 'CROSS JOIN';
3258
2934
  }
@@ -3272,63 +2948,26 @@ class Deparser {
3272
2948
  default:
3273
2949
  joinStr += 'JOIN';
3274
2950
  }
2951
+ output.push(joinStr);
3275
2952
  if (node.rarg) {
3276
2953
  let rargStr = this.visit(node.rarg, context);
3277
2954
  if (node.rarg && 'JoinExpr' in node.rarg && !node.rarg.JoinExpr.alias) {
3278
2955
  rargStr = `(${rargStr})`;
3279
2956
  }
3280
- if (this.formatter.isPretty()) {
3281
- output.push(this.formatter.newline() + joinStr + ' ' + rargStr);
3282
- }
3283
- else {
3284
- output.push(joinStr + ' ' + rargStr);
3285
- }
3286
- }
3287
- else {
3288
- if (this.formatter.isPretty()) {
3289
- output.push(this.formatter.newline() + joinStr);
3290
- }
3291
- else {
3292
- output.push(joinStr);
3293
- }
2957
+ output.push(rargStr);
3294
2958
  }
3295
2959
  if (node.usingClause && node.usingClause.length > 0) {
2960
+ output.push('USING');
3296
2961
  const usingList = list_utils_1.ListUtils.unwrapList(node.usingClause);
3297
2962
  const columnNames = usingList.map(col => this.visit(col, context));
3298
- if (this.formatter.isPretty()) {
3299
- output.push(` USING (${columnNames.join(', ')})`);
3300
- }
3301
- else {
3302
- output.push(`USING (${columnNames.join(', ')})`);
3303
- }
2963
+ output.push(`(${columnNames.join(', ')})`);
3304
2964
  }
3305
2965
  else if (node.quals) {
3306
- const qualsStr = this.visit(node.quals, context);
3307
- if (this.formatter.isPretty()) {
3308
- // For complex JOIN conditions, format with proper indentation
3309
- if (qualsStr.includes('AND') || qualsStr.includes('OR') || qualsStr.length > 50) {
3310
- if (this.containsMultilineStringLiteral(qualsStr)) {
3311
- output.push(` ON ${qualsStr}`);
3312
- }
3313
- else {
3314
- output.push(` ON${this.formatter.newline()}${this.formatter.indent(qualsStr)}`);
3315
- }
3316
- }
3317
- else {
3318
- output.push(` ON ${qualsStr}`);
3319
- }
3320
- }
3321
- else {
3322
- output.push(`ON ${qualsStr}`);
3323
- }
3324
- }
3325
- let result;
3326
- if (this.formatter.isPretty()) {
3327
- result = output.join('');
3328
- }
3329
- else {
3330
- result = output.join(' ');
2966
+ output.push('ON');
2967
+ output.push(this.visit(node.quals, context));
3331
2968
  }
2969
+ let result = output.join(' ');
2970
+ // Handle join_using_alias first (for USING clause aliases like "AS x")
3332
2971
  if (node.join_using_alias && node.join_using_alias.aliasname) {
3333
2972
  let aliasStr = node.join_using_alias.aliasname;
3334
2973
  if (node.join_using_alias.colnames && node.join_using_alias.colnames.length > 0) {
@@ -3338,6 +2977,7 @@ class Deparser {
3338
2977
  }
3339
2978
  result += ` AS ${aliasStr}`;
3340
2979
  }
2980
+ // Handle regular alias (for outer table aliases like "y")
3341
2981
  if (node.alias && node.alias.aliasname) {
3342
2982
  let aliasStr = node.alias.aliasname;
3343
2983
  if (node.alias.colnames && node.alias.colnames.length > 0) {
@@ -5149,17 +4789,17 @@ class Deparser {
5149
4789
  }
5150
4790
  if (context.parentNodeTypes.includes('DoStmt')) {
5151
4791
  if (node.defname === 'as') {
5152
- const defElemContext = { ...context, parentNodeTypes: [...context.parentNodeTypes, 'DefElem'] };
5153
- const argValue = node.arg ? this.visit(node.arg, defElemContext) : '';
5154
4792
  if (Array.isArray(argValue)) {
5155
4793
  const bodyParts = argValue;
5156
- const body = bodyParts.join('');
5157
- const delimiter = this.getFunctionDelimiter(body);
5158
- return `${delimiter}${body}${delimiter}`;
4794
+ if (bodyParts.length === 1) {
4795
+ return `$$${bodyParts[0]}$$`;
4796
+ }
4797
+ else {
4798
+ return `$$${bodyParts.join('')}$$`;
4799
+ }
5159
4800
  }
5160
4801
  else {
5161
- const delimiter = this.getFunctionDelimiter(argValue);
5162
- return `${delimiter}${argValue}${delimiter}`;
4802
+ return `$$${argValue}$$`;
5163
4803
  }
5164
4804
  }
5165
4805
  return '';
@@ -5178,14 +4818,16 @@ class Deparser {
5178
4818
  });
5179
4819
  if (bodyParts.length === 1) {
5180
4820
  const body = bodyParts[0];
5181
- const delimiter = this.getFunctionDelimiter(body);
5182
- return `AS ${delimiter}${body}${delimiter}`;
4821
+ // Check if body contains $$ to avoid conflicts
4822
+ if (body.includes('$$')) {
4823
+ return `AS '${body.replace(/'/g, "''")}'`;
4824
+ }
4825
+ else {
4826
+ return `AS $$${body}$$`;
4827
+ }
5183
4828
  }
5184
4829
  else {
5185
- return `AS ${bodyParts.map((part) => {
5186
- const delimiter = this.getFunctionDelimiter(part);
5187
- return `${delimiter}${part}${delimiter}`;
5188
- }).join(', ')}`;
4830
+ return `AS ${bodyParts.map((part) => `$$${part}$$`).join(', ')}`;
5189
4831
  }
5190
4832
  }
5191
4833
  // Handle Array type (legacy support)
@@ -5193,20 +4835,27 @@ class Deparser {
5193
4835
  const bodyParts = argValue;
5194
4836
  if (bodyParts.length === 1) {
5195
4837
  const body = bodyParts[0];
5196
- const delimiter = this.getFunctionDelimiter(body);
5197
- return `AS ${delimiter}${body}${delimiter}`;
4838
+ // Check if body contains $$ to avoid conflicts
4839
+ if (body.includes('$$')) {
4840
+ return `AS '${body.replace(/'/g, "''")}'`;
4841
+ }
4842
+ else {
4843
+ return `AS $$${body}$$`;
4844
+ }
5198
4845
  }
5199
4846
  else {
5200
- return `AS ${bodyParts.map(part => {
5201
- const delimiter = this.getFunctionDelimiter(part);
5202
- return `${delimiter}${part}${delimiter}`;
5203
- }).join(', ')}`;
4847
+ return `AS ${bodyParts.map(part => `$$${part}$$`).join(', ')}`;
5204
4848
  }
5205
4849
  }
5206
4850
  // Handle String type (single function body)
5207
4851
  else {
5208
- const delimiter = this.getFunctionDelimiter(argValue);
5209
- return `AS ${delimiter}${argValue}${delimiter}`;
4852
+ // Check if argValue contains $$ to avoid conflicts
4853
+ if (argValue.includes('$$')) {
4854
+ return `AS '${argValue.replace(/'/g, "''")}'`;
4855
+ }
4856
+ else {
4857
+ return `AS $$${argValue}$$`;
4858
+ }
5210
4859
  }
5211
4860
  }
5212
4861
  if (node.defname === 'language') {
@@ -5320,18 +4969,6 @@ class Deparser {
5320
4969
  : argValue;
5321
4970
  return `${node.defname} = ${quotedValue}`;
5322
4971
  }
5323
- // Handle CopyStmt WITH clause options - uppercase format without quotes
5324
- if (context.parentNodeTypes.includes('CopyStmt')) {
5325
- if (node.defname === 'format' && node.arg && this.getNodeType(node.arg) === 'String') {
5326
- const stringData = this.getNodeData(node.arg);
5327
- return `FORMAT ${stringData.sval.toUpperCase()}`;
5328
- }
5329
- // Handle other COPY options with uppercase defname
5330
- if (node.arg) {
5331
- return `${node.defname.toUpperCase()} ${argValue}`;
5332
- }
5333
- return node.defname.toUpperCase();
5334
- }
5335
4972
  // Handle CREATE OPERATOR and CREATE TYPE context
5336
4973
  if (context.parentNodeTypes.includes('DefineStmt')) {
5337
4974
  const preservedName = this.preserveOperatorDefElemCase(node.defname);
@@ -6022,7 +5659,8 @@ class Deparser {
6022
5659
  output.push('NULL');
6023
5660
  }
6024
5661
  else if (node.comment) {
6025
- output.push(quote_utils_1.QuoteUtils.formatEString(node.comment));
5662
+ const escapedComment = node.comment.replace(/'/g, "''");
5663
+ output.push(`'${escapedComment}'`);
6026
5664
  }
6027
5665
  return output.join(' ');
6028
5666
  }
@@ -6056,82 +5694,38 @@ class Deparser {
6056
5694
  return output.join(' ');
6057
5695
  }
6058
5696
  CreatePolicyStmt(node, context) {
6059
- const output = [];
6060
- const initialParts = ['CREATE', 'POLICY'];
5697
+ const output = ['CREATE', 'POLICY'];
6061
5698
  if (node.policy_name) {
6062
- initialParts.push(`"${node.policy_name}"`);
5699
+ output.push(`"${node.policy_name}"`);
6063
5700
  }
6064
- output.push(initialParts.join(' '));
6065
- // Add ON clause on new line in pretty mode
5701
+ output.push('ON');
6066
5702
  if (node.table) {
6067
- if (this.formatter.isPretty()) {
6068
- output.push(this.formatter.newline() + this.formatter.indent(`ON ${this.RangeVar(node.table, context)}`));
6069
- }
6070
- else {
6071
- output.push('ON');
6072
- output.push(this.RangeVar(node.table, context));
6073
- }
5703
+ output.push(this.RangeVar(node.table, context));
6074
5704
  }
6075
5705
  // Handle AS RESTRICTIVE/PERMISSIVE clause
6076
5706
  if (node.permissive === undefined) {
6077
- if (this.formatter.isPretty()) {
6078
- output.push(this.formatter.newline() + this.formatter.indent('AS RESTRICTIVE'));
6079
- }
6080
- else {
6081
- output.push('AS', 'RESTRICTIVE');
6082
- }
5707
+ output.push('AS', 'RESTRICTIVE');
6083
5708
  }
6084
5709
  else if (node.permissive === true) {
6085
- if (this.formatter.isPretty()) {
6086
- output.push(this.formatter.newline() + this.formatter.indent('AS PERMISSIVE'));
6087
- }
6088
- else {
6089
- output.push('AS', 'PERMISSIVE');
6090
- }
5710
+ output.push('AS', 'PERMISSIVE');
6091
5711
  }
6092
5712
  if (node.cmd_name) {
6093
- if (this.formatter.isPretty()) {
6094
- output.push(this.formatter.newline() + this.formatter.indent(`FOR ${node.cmd_name.toUpperCase()}`));
6095
- }
6096
- else {
6097
- output.push('FOR', node.cmd_name.toUpperCase());
6098
- }
5713
+ output.push('FOR', node.cmd_name.toUpperCase());
6099
5714
  }
6100
5715
  if (node.roles && node.roles.length > 0) {
5716
+ output.push('TO');
6101
5717
  const roles = list_utils_1.ListUtils.unwrapList(node.roles).map(role => this.visit(role, context));
6102
- if (this.formatter.isPretty()) {
6103
- output.push(this.formatter.newline() + this.formatter.indent(`TO ${roles.join(', ')}`));
6104
- }
6105
- else {
6106
- output.push('TO');
6107
- output.push(roles.join(', '));
6108
- }
5718
+ output.push(roles.join(', '));
6109
5719
  }
6110
5720
  if (node.qual) {
6111
- if (this.formatter.isPretty()) {
6112
- const qualExpr = this.visit(node.qual, context);
6113
- output.push(this.formatter.newline() + this.formatter.indent('USING ('));
6114
- output.push(this.formatter.newline() + this.formatter.indent(this.formatter.indent(qualExpr)));
6115
- output.push(this.formatter.newline() + this.formatter.indent(')'));
6116
- }
6117
- else {
6118
- output.push('USING');
6119
- output.push(`(${this.visit(node.qual, context)})`);
6120
- }
5721
+ output.push('USING');
5722
+ output.push(`(${this.visit(node.qual, context)})`);
6121
5723
  }
6122
5724
  if (node.with_check) {
6123
- if (this.formatter.isPretty()) {
6124
- const checkExpr = this.visit(node.with_check, context);
6125
- output.push(this.formatter.newline() + this.formatter.indent('WITH CHECK ('));
6126
- output.push(this.formatter.newline() + this.formatter.indent(this.formatter.indent(checkExpr)));
6127
- output.push(this.formatter.newline() + this.formatter.indent(')'));
6128
- }
6129
- else {
6130
- output.push('WITH CHECK');
6131
- output.push(`(${this.visit(node.with_check, context)})`);
6132
- }
5725
+ output.push('WITH CHECK');
5726
+ output.push(`(${this.visit(node.with_check, context)})`);
6133
5727
  }
6134
- return this.formatter.isPretty() ? output.join('') : output.join(' ');
5728
+ return output.join(' ');
6135
5729
  }
6136
5730
  AlterPolicyStmt(node, context) {
6137
5731
  const output = ['ALTER', 'POLICY'];
@@ -6371,12 +5965,12 @@ class Deparser {
6371
5965
  processedArgs.push(`LANGUAGE ${langValue}`);
6372
5966
  }
6373
5967
  else if (defElem.defname === 'as') {
6374
- // Handle code block with configurable delimiter
5968
+ // Handle code block with dollar quoting
6375
5969
  const argNodeType = this.getNodeType(defElem.arg);
6376
5970
  if (argNodeType === 'String') {
6377
5971
  const stringNode = this.getNodeData(defElem.arg);
6378
- const delimiter = this.getFunctionDelimiter(stringNode.sval);
6379
- processedArgs.push(`${delimiter}${stringNode.sval}${delimiter}`);
5972
+ const dollarTag = this.generateUniqueDollarTag(stringNode.sval);
5973
+ processedArgs.push(`${dollarTag}${stringNode.sval}${dollarTag}`);
6380
5974
  }
6381
5975
  else {
6382
5976
  processedArgs.push(this.visit(defElem.arg, doContext));
@@ -6410,11 +6004,9 @@ class Deparser {
6410
6004
  }
6411
6005
  InlineCodeBlock(node, context) {
6412
6006
  if (node.source_text) {
6413
- const delimiter = this.getFunctionDelimiter(node.source_text);
6414
- return `${delimiter}${node.source_text}${delimiter}`;
6007
+ return `$$${node.source_text}$$`;
6415
6008
  }
6416
- const delimiter = this.options.functionDelimiter || '$$';
6417
- return `${delimiter}${delimiter}`;
6009
+ return '$$$$';
6418
6010
  }
6419
6011
  CallContext(node, context) {
6420
6012
  if (node.atomic !== undefined) {
@@ -9997,9 +9589,18 @@ class Deparser {
9997
9589
  }
9998
9590
  return output.join(' ');
9999
9591
  }
10000
- containsMultilineStringLiteral(content) {
10001
- const stringLiteralRegex = /'[^']*\n[^']*'/g;
10002
- return stringLiteralRegex.test(content);
9592
+ version(node, context) {
9593
+ // Handle version node - typically just return the version number
9594
+ if (typeof node === 'number') {
9595
+ return node.toString();
9596
+ }
9597
+ if (typeof node === 'string') {
9598
+ return node;
9599
+ }
9600
+ if (node && typeof node === 'object' && node.version) {
9601
+ return node.version.toString();
9602
+ }
9603
+ return '';
10003
9604
  }
10004
9605
  }
10005
9606
  exports.Deparser = Deparser;