pgsql-deparser 17.7.2 → 17.8.1

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/deparser.js CHANGED
@@ -51,7 +51,7 @@ class Deparser {
51
51
  tree;
52
52
  options;
53
53
  constructor(tree, opts = {}) {
54
- this.formatter = new sql_formatter_1.SqlFormatter(opts.newline, opts.tab);
54
+ this.formatter = new sql_formatter_1.SqlFormatter(opts.newline, opts.tab, opts.pretty);
55
55
  // Set default options
56
56
  this.options = {
57
57
  functionDelimiter: '$$',
@@ -184,7 +184,9 @@ class Deparser {
184
184
  }
185
185
  if (!node.op || node.op === 'SETOP_NONE') {
186
186
  if (node.valuesLists == null) {
187
- output.push('SELECT');
187
+ if (!this.formatter.isPretty() || !node.targetList) {
188
+ output.push('SELECT');
189
+ }
188
190
  }
189
191
  }
190
192
  else {
@@ -230,41 +232,82 @@ class Deparser {
230
232
  output.push(rightStmt);
231
233
  }
232
234
  }
235
+ // Handle DISTINCT clause - in pretty mode, we'll include it in the SELECT clause
236
+ let distinctPart = '';
233
237
  if (node.distinctClause) {
234
238
  const distinctClause = list_utils_1.ListUtils.unwrapList(node.distinctClause);
235
239
  if (distinctClause.length > 0 && Object.keys(distinctClause[0]).length > 0) {
236
- output.push('DISTINCT ON');
237
240
  const clause = distinctClause
238
241
  .map(e => this.visit(e, { ...context, select: true }))
239
242
  .join(', ');
240
- output.push(this.formatter.parens(clause));
243
+ distinctPart = ' DISTINCT ON ' + this.formatter.parens(clause);
241
244
  }
242
245
  else {
243
- output.push('DISTINCT');
246
+ distinctPart = ' DISTINCT';
247
+ }
248
+ if (!this.formatter.isPretty()) {
249
+ if (distinctClause.length > 0 && Object.keys(distinctClause[0]).length > 0) {
250
+ output.push('DISTINCT ON');
251
+ const clause = distinctClause
252
+ .map(e => this.visit(e, { ...context, select: true }))
253
+ .join(', ');
254
+ output.push(this.formatter.parens(clause));
255
+ }
256
+ else {
257
+ output.push('DISTINCT');
258
+ }
244
259
  }
245
260
  }
246
261
  if (node.targetList) {
247
262
  const targetList = list_utils_1.ListUtils.unwrapList(node.targetList);
248
- const targets = targetList
249
- .map(e => this.visit(e, { ...context, select: true }))
250
- .join(', ');
251
- output.push(targets);
263
+ if (this.formatter.isPretty()) {
264
+ const targetStrings = targetList
265
+ .map(e => {
266
+ const targetStr = this.visit(e, { ...context, select: true });
267
+ if (this.containsMultilineStringLiteral(targetStr)) {
268
+ return targetStr;
269
+ }
270
+ return this.formatter.indent(targetStr);
271
+ });
272
+ const formattedTargets = targetStrings.join(',' + this.formatter.newline());
273
+ output.push('SELECT' + distinctPart);
274
+ output.push(formattedTargets);
275
+ }
276
+ else {
277
+ const targets = targetList
278
+ .map(e => this.visit(e, { ...context, select: true }))
279
+ .join(', ');
280
+ output.push(targets);
281
+ }
252
282
  }
253
283
  if (node.intoClause) {
254
284
  output.push('INTO');
255
285
  output.push(this.IntoClause(node.intoClause, context));
256
286
  }
257
287
  if (node.fromClause) {
258
- output.push('FROM');
259
288
  const fromList = list_utils_1.ListUtils.unwrapList(node.fromClause);
260
289
  const fromItems = fromList
261
290
  .map(e => this.deparse(e, { ...context, from: true }))
262
291
  .join(', ');
263
- output.push(fromItems);
292
+ output.push('FROM ' + fromItems.trim());
264
293
  }
265
294
  if (node.whereClause) {
266
- output.push('WHERE');
267
- output.push(this.visit(node.whereClause, context));
295
+ if (this.formatter.isPretty()) {
296
+ output.push('WHERE');
297
+ const whereExpr = this.visit(node.whereClause, context);
298
+ const lines = whereExpr.split(this.formatter.newline());
299
+ const indentedLines = lines.map((line, index) => {
300
+ if (index === 0) {
301
+ return this.formatter.indent(line);
302
+ }
303
+ return line;
304
+ });
305
+ output.push(indentedLines.join(this.formatter.newline()));
306
+ }
307
+ else {
308
+ output.push('WHERE');
309
+ output.push(this.visit(node.whereClause, context));
310
+ }
268
311
  }
269
312
  if (node.valuesLists) {
270
313
  output.push('VALUES');
@@ -275,16 +318,43 @@ class Deparser {
275
318
  output.push(lists.join(', '));
276
319
  }
277
320
  if (node.groupClause) {
278
- output.push('GROUP BY');
279
321
  const groupList = list_utils_1.ListUtils.unwrapList(node.groupClause);
280
- const groupItems = groupList
281
- .map(e => this.visit(e, { ...context, group: true }))
282
- .join(', ');
283
- output.push(groupItems);
322
+ if (this.formatter.isPretty()) {
323
+ const groupItems = groupList
324
+ .map(e => {
325
+ const groupStr = this.visit(e, { ...context, group: true });
326
+ if (this.containsMultilineStringLiteral(groupStr)) {
327
+ return groupStr;
328
+ }
329
+ return this.formatter.indent(groupStr);
330
+ })
331
+ .join(',' + this.formatter.newline());
332
+ output.push('GROUP BY');
333
+ output.push(groupItems);
334
+ }
335
+ else {
336
+ output.push('GROUP BY');
337
+ const groupItems = groupList
338
+ .map(e => this.visit(e, { ...context, group: true }))
339
+ .join(', ');
340
+ output.push(groupItems);
341
+ }
284
342
  }
285
343
  if (node.havingClause) {
286
- output.push('HAVING');
287
- output.push(this.visit(node.havingClause, context));
344
+ if (this.formatter.isPretty()) {
345
+ output.push('HAVING');
346
+ const havingStr = this.visit(node.havingClause, context);
347
+ if (this.containsMultilineStringLiteral(havingStr)) {
348
+ output.push(havingStr);
349
+ }
350
+ else {
351
+ output.push(this.formatter.indent(havingStr));
352
+ }
353
+ }
354
+ else {
355
+ output.push('HAVING');
356
+ output.push(this.visit(node.havingClause, context));
357
+ }
288
358
  }
289
359
  if (node.windowClause) {
290
360
  output.push('WINDOW');
@@ -295,20 +365,33 @@ class Deparser {
295
365
  output.push(windowClauses);
296
366
  }
297
367
  if (node.sortClause) {
298
- output.push('ORDER BY');
299
368
  const sortList = list_utils_1.ListUtils.unwrapList(node.sortClause);
300
- const sortItems = sortList
301
- .map(e => this.visit(e, { ...context, sort: true }))
302
- .join(', ');
303
- output.push(sortItems);
369
+ if (this.formatter.isPretty()) {
370
+ const sortItems = sortList
371
+ .map(e => {
372
+ const sortStr = this.visit(e, { ...context, sort: true });
373
+ if (this.containsMultilineStringLiteral(sortStr)) {
374
+ return sortStr;
375
+ }
376
+ return this.formatter.indent(sortStr);
377
+ })
378
+ .join(',' + this.formatter.newline());
379
+ output.push('ORDER BY');
380
+ output.push(sortItems);
381
+ }
382
+ else {
383
+ output.push('ORDER BY');
384
+ const sortItems = sortList
385
+ .map(e => this.visit(e, { ...context, sort: true }))
386
+ .join(', ');
387
+ output.push(sortItems);
388
+ }
304
389
  }
305
390
  if (node.limitCount) {
306
- output.push('LIMIT');
307
- output.push(this.visit(node.limitCount, context));
391
+ output.push('LIMIT ' + this.visit(node.limitCount, context));
308
392
  }
309
393
  if (node.limitOffset) {
310
- output.push('OFFSET');
311
- output.push(this.visit(node.limitOffset, context));
394
+ output.push('OFFSET ' + this.visit(node.limitOffset, context));
312
395
  }
313
396
  if (node.lockingClause) {
314
397
  const lockingList = list_utils_1.ListUtils.unwrapList(node.lockingClause);
@@ -317,6 +400,10 @@ class Deparser {
317
400
  .join(' ');
318
401
  output.push(lockingClauses);
319
402
  }
403
+ if (this.formatter.isPretty()) {
404
+ const filteredOutput = output.filter(item => item.trim() !== '');
405
+ return filteredOutput.join(this.formatter.newline());
406
+ }
320
407
  return output.join(' ');
321
408
  }
322
409
  A_Expr(node, context) {
@@ -806,9 +893,24 @@ class Deparser {
806
893
  if (node.recursive) {
807
894
  output.push('RECURSIVE');
808
895
  }
809
- const ctes = list_utils_1.ListUtils.unwrapList(node.ctes);
810
- const cteStrs = ctes.map(cte => this.visit(cte, context));
811
- output.push(cteStrs.join(', '));
896
+ if (node.ctes && node.ctes.length > 0) {
897
+ const ctes = list_utils_1.ListUtils.unwrapList(node.ctes);
898
+ if (this.formatter.isPretty()) {
899
+ const cteStrings = ctes.map((cte, index) => {
900
+ const cteStr = this.visit(cte, context);
901
+ const prefix = index === 0 ? this.formatter.newline() : ',' + this.formatter.newline();
902
+ if (this.containsMultilineStringLiteral(cteStr)) {
903
+ return prefix + cteStr;
904
+ }
905
+ return prefix + this.formatter.indent(cteStr);
906
+ });
907
+ output.push(cteStrings.join(''));
908
+ }
909
+ else {
910
+ const cteStrings = ctes.map(cte => this.visit(cte, context));
911
+ output.push(cteStrings.join(', '));
912
+ }
913
+ }
812
914
  return output.join(' ');
813
915
  }
814
916
  ResTarget(node, context) {
@@ -892,11 +994,23 @@ class Deparser {
892
994
  // return formatStr.replace('%s', () => andArgs); // ✅ Function callback prevents interpretation
893
995
  switch (boolop) {
894
996
  case 'AND_EXPR':
895
- const andArgs = args.map(arg => this.visit(arg, boolContext)).join(' AND ');
896
- return formatStr.replace('%s', () => andArgs);
997
+ if (this.formatter.isPretty() && args.length > 1) {
998
+ const andArgs = args.map(arg => this.visit(arg, boolContext)).join(this.formatter.newline() + ' AND ');
999
+ return formatStr.replace('%s', () => andArgs);
1000
+ }
1001
+ else {
1002
+ const andArgs = args.map(arg => this.visit(arg, boolContext)).join(' AND ');
1003
+ return formatStr.replace('%s', () => andArgs);
1004
+ }
897
1005
  case 'OR_EXPR':
898
- const orArgs = args.map(arg => this.visit(arg, boolContext)).join(' OR ');
899
- return formatStr.replace('%s', () => orArgs);
1006
+ if (this.formatter.isPretty() && args.length > 1) {
1007
+ const orArgs = args.map(arg => this.visit(arg, boolContext)).join(this.formatter.newline() + ' OR ');
1008
+ return formatStr.replace('%s', () => orArgs);
1009
+ }
1010
+ else {
1011
+ const orArgs = args.map(arg => this.visit(arg, boolContext)).join(' OR ');
1012
+ return formatStr.replace('%s', () => orArgs);
1013
+ }
900
1014
  case 'NOT_EXPR':
901
1015
  return `NOT (${this.visit(args[0], context)})`;
902
1016
  default:
@@ -1098,7 +1212,13 @@ class Deparser {
1098
1212
  windowParts.push(frameClause);
1099
1213
  }
1100
1214
  if (windowParts.length > 0) {
1101
- result += ` OVER (${windowParts.join(' ')})`;
1215
+ if (this.formatter.isPretty() && windowParts.length > 1) {
1216
+ const formattedParts = windowParts.map(part => this.formatter.indent(part));
1217
+ result += ` OVER (${this.formatter.newline()}${formattedParts.join(this.formatter.newline())}${this.formatter.newline()})`;
1218
+ }
1219
+ else {
1220
+ result += ` OVER (${windowParts.join(' ')})`;
1221
+ }
1102
1222
  }
1103
1223
  else {
1104
1224
  result += ` OVER ()`;
@@ -1722,15 +1842,39 @@ class Deparser {
1722
1842
  output.push(this.visit(node.arg, context));
1723
1843
  }
1724
1844
  const args = list_utils_1.ListUtils.unwrapList(node.args);
1725
- for (const arg of args) {
1726
- output.push(this.visit(arg, context));
1845
+ if (this.formatter.isPretty() && args.length > 0) {
1846
+ for (const arg of args) {
1847
+ const whenClause = this.visit(arg, context);
1848
+ if (this.containsMultilineStringLiteral(whenClause)) {
1849
+ output.push(this.formatter.newline() + whenClause);
1850
+ }
1851
+ else {
1852
+ output.push(this.formatter.newline() + this.formatter.indent(whenClause));
1853
+ }
1854
+ }
1855
+ if (node.defresult) {
1856
+ const elseResult = this.visit(node.defresult, context);
1857
+ if (this.containsMultilineStringLiteral(elseResult)) {
1858
+ output.push(this.formatter.newline() + 'ELSE ' + elseResult);
1859
+ }
1860
+ else {
1861
+ output.push(this.formatter.newline() + this.formatter.indent('ELSE ' + elseResult));
1862
+ }
1863
+ }
1864
+ output.push(this.formatter.newline() + 'END');
1865
+ return output.join(' ');
1727
1866
  }
1728
- if (node.defresult) {
1729
- output.push('ELSE');
1730
- output.push(this.visit(node.defresult, context));
1867
+ else {
1868
+ for (const arg of args) {
1869
+ output.push(this.visit(arg, context));
1870
+ }
1871
+ if (node.defresult) {
1872
+ output.push('ELSE');
1873
+ output.push(this.visit(node.defresult, context));
1874
+ }
1875
+ output.push('END');
1876
+ return output.join(' ');
1731
1877
  }
1732
- output.push('END');
1733
- return output.join(' ');
1734
1878
  }
1735
1879
  CoalesceExpr(node, context) {
1736
1880
  const args = list_utils_1.ListUtils.unwrapList(node.args);
@@ -1943,7 +2087,13 @@ class Deparser {
1943
2087
  const elementStrs = elements.map(el => {
1944
2088
  return this.deparse(el, context);
1945
2089
  });
1946
- output.push(this.formatter.parens(elementStrs.join(', ')));
2090
+ if (this.formatter.isPretty()) {
2091
+ const formattedElements = elementStrs.map(el => this.formatter.indent(el)).join(',' + this.formatter.newline());
2092
+ output.push('(' + this.formatter.newline() + formattedElements + this.formatter.newline() + ')');
2093
+ }
2094
+ else {
2095
+ output.push(this.formatter.parens(elementStrs.join(', ')));
2096
+ }
1947
2097
  }
1948
2098
  else if (!node.partbound) {
1949
2099
  output.push(this.formatter.parens(''));
@@ -2228,38 +2378,52 @@ class Deparser {
2228
2378
  }
2229
2379
  }
2230
2380
  if (node.fk_upd_action && node.fk_upd_action !== 'a') {
2231
- output.push('ON UPDATE');
2381
+ let updateClause = 'ON UPDATE ';
2232
2382
  switch (node.fk_upd_action) {
2233
2383
  case 'r':
2234
- output.push('RESTRICT');
2384
+ updateClause += 'RESTRICT';
2235
2385
  break;
2236
2386
  case 'c':
2237
- output.push('CASCADE');
2387
+ updateClause += 'CASCADE';
2238
2388
  break;
2239
2389
  case 'n':
2240
- output.push('SET NULL');
2390
+ updateClause += 'SET NULL';
2241
2391
  break;
2242
2392
  case 'd':
2243
- output.push('SET DEFAULT');
2393
+ updateClause += 'SET DEFAULT';
2244
2394
  break;
2245
2395
  }
2396
+ if (this.formatter.isPretty()) {
2397
+ output.push('\n' + this.formatter.indent(updateClause));
2398
+ }
2399
+ else {
2400
+ output.push('ON UPDATE');
2401
+ output.push(updateClause.replace('ON UPDATE ', ''));
2402
+ }
2246
2403
  }
2247
2404
  if (node.fk_del_action && node.fk_del_action !== 'a') {
2248
- output.push('ON DELETE');
2405
+ let deleteClause = 'ON DELETE ';
2249
2406
  switch (node.fk_del_action) {
2250
2407
  case 'r':
2251
- output.push('RESTRICT');
2408
+ deleteClause += 'RESTRICT';
2252
2409
  break;
2253
2410
  case 'c':
2254
- output.push('CASCADE');
2411
+ deleteClause += 'CASCADE';
2255
2412
  break;
2256
2413
  case 'n':
2257
- output.push('SET NULL');
2414
+ deleteClause += 'SET NULL';
2258
2415
  break;
2259
2416
  case 'd':
2260
- output.push('SET DEFAULT');
2417
+ deleteClause += 'SET DEFAULT';
2261
2418
  break;
2262
2419
  }
2420
+ if (this.formatter.isPretty()) {
2421
+ output.push('\n' + this.formatter.indent(deleteClause));
2422
+ }
2423
+ else {
2424
+ output.push('ON DELETE');
2425
+ output.push(deleteClause.replace('ON DELETE ', ''));
2426
+ }
2263
2427
  }
2264
2428
  // Handle NOT VALID for foreign key constraints - only for table constraints, not domain constraints
2265
2429
  if (node.skip_validation && !context.isDomainConstraint) {
@@ -2317,17 +2481,48 @@ class Deparser {
2317
2481
  // Handle deferrable constraints for all constraint types that support it
2318
2482
  if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN') {
2319
2483
  if (node.deferrable) {
2320
- output.push('DEFERRABLE');
2321
- if (node.initdeferred === true) {
2322
- output.push('INITIALLY DEFERRED');
2484
+ if (this.formatter.isPretty() && node.contype === 'CONSTR_FOREIGN') {
2485
+ output.push('\n' + this.formatter.indent('DEFERRABLE'));
2486
+ if (node.initdeferred === true) {
2487
+ output.push('\n' + this.formatter.indent('INITIALLY DEFERRED'));
2488
+ }
2489
+ else if (node.initdeferred === false) {
2490
+ output.push('\n' + this.formatter.indent('INITIALLY IMMEDIATE'));
2491
+ }
2323
2492
  }
2324
- else if (node.initdeferred === false) {
2325
- output.push('INITIALLY IMMEDIATE');
2493
+ else {
2494
+ output.push('DEFERRABLE');
2495
+ if (node.initdeferred === true) {
2496
+ output.push('INITIALLY DEFERRED');
2497
+ }
2498
+ else if (node.initdeferred === false) {
2499
+ output.push('INITIALLY IMMEDIATE');
2500
+ }
2326
2501
  }
2327
2502
  }
2328
2503
  else if (node.deferrable === false) {
2329
- output.push('NOT DEFERRABLE');
2504
+ if (this.formatter.isPretty() && node.contype === 'CONSTR_FOREIGN') {
2505
+ output.push('\n' + this.formatter.indent('NOT DEFERRABLE'));
2506
+ }
2507
+ else {
2508
+ output.push('NOT DEFERRABLE');
2509
+ }
2510
+ }
2511
+ }
2512
+ if (this.formatter.isPretty() && node.contype === 'CONSTR_FOREIGN') {
2513
+ let result = '';
2514
+ for (let i = 0; i < output.length; i++) {
2515
+ if (output[i].startsWith('\n')) {
2516
+ result += output[i];
2517
+ }
2518
+ else {
2519
+ if (i > 0 && !output[i - 1].startsWith('\n')) {
2520
+ result += ' ';
2521
+ }
2522
+ result += output[i];
2523
+ }
2330
2524
  }
2525
+ return result;
2331
2526
  }
2332
2527
  return output.join(' ');
2333
2528
  }
@@ -3051,11 +3246,9 @@ class Deparser {
3051
3246
  }
3052
3247
  switch (node.jointype) {
3053
3248
  case 'JOIN_INNER':
3054
- // Handle NATURAL JOIN first - it has isNatural=true (NATURAL already added above)
3055
3249
  if (node.isNatural) {
3056
3250
  joinStr += 'JOIN';
3057
3251
  }
3058
- // Handle CROSS JOIN case - when there's no quals, no usingClause, and not natural
3059
3252
  else if (!node.quals && (!node.usingClause || node.usingClause.length === 0)) {
3060
3253
  joinStr += 'CROSS JOIN';
3061
3254
  }
@@ -3075,26 +3268,63 @@ class Deparser {
3075
3268
  default:
3076
3269
  joinStr += 'JOIN';
3077
3270
  }
3078
- output.push(joinStr);
3079
3271
  if (node.rarg) {
3080
3272
  let rargStr = this.visit(node.rarg, context);
3081
3273
  if (node.rarg && 'JoinExpr' in node.rarg && !node.rarg.JoinExpr.alias) {
3082
3274
  rargStr = `(${rargStr})`;
3083
3275
  }
3084
- output.push(rargStr);
3276
+ if (this.formatter.isPretty()) {
3277
+ output.push(this.formatter.newline() + joinStr + ' ' + rargStr);
3278
+ }
3279
+ else {
3280
+ output.push(joinStr + ' ' + rargStr);
3281
+ }
3282
+ }
3283
+ else {
3284
+ if (this.formatter.isPretty()) {
3285
+ output.push(this.formatter.newline() + joinStr);
3286
+ }
3287
+ else {
3288
+ output.push(joinStr);
3289
+ }
3085
3290
  }
3086
3291
  if (node.usingClause && node.usingClause.length > 0) {
3087
- output.push('USING');
3088
3292
  const usingList = list_utils_1.ListUtils.unwrapList(node.usingClause);
3089
3293
  const columnNames = usingList.map(col => this.visit(col, context));
3090
- output.push(`(${columnNames.join(', ')})`);
3294
+ if (this.formatter.isPretty()) {
3295
+ output.push(` USING (${columnNames.join(', ')})`);
3296
+ }
3297
+ else {
3298
+ output.push(`USING (${columnNames.join(', ')})`);
3299
+ }
3091
3300
  }
3092
3301
  else if (node.quals) {
3093
- output.push('ON');
3094
- output.push(this.visit(node.quals, context));
3302
+ const qualsStr = this.visit(node.quals, context);
3303
+ if (this.formatter.isPretty()) {
3304
+ // For complex JOIN conditions, format with proper indentation
3305
+ if (qualsStr.includes('AND') || qualsStr.includes('OR') || qualsStr.length > 50) {
3306
+ if (this.containsMultilineStringLiteral(qualsStr)) {
3307
+ output.push(` ON ${qualsStr}`);
3308
+ }
3309
+ else {
3310
+ output.push(` ON${this.formatter.newline()}${this.formatter.indent(qualsStr)}`);
3311
+ }
3312
+ }
3313
+ else {
3314
+ output.push(` ON ${qualsStr}`);
3315
+ }
3316
+ }
3317
+ else {
3318
+ output.push(`ON ${qualsStr}`);
3319
+ }
3320
+ }
3321
+ let result;
3322
+ if (this.formatter.isPretty()) {
3323
+ result = output.join('');
3324
+ }
3325
+ else {
3326
+ result = output.join(' ');
3095
3327
  }
3096
- let result = output.join(' ');
3097
- // Handle join_using_alias first (for USING clause aliases like "AS x")
3098
3328
  if (node.join_using_alias && node.join_using_alias.aliasname) {
3099
3329
  let aliasStr = node.join_using_alias.aliasname;
3100
3330
  if (node.join_using_alias.colnames && node.join_using_alias.colnames.length > 0) {
@@ -3104,7 +3334,6 @@ class Deparser {
3104
3334
  }
3105
3335
  result += ` AS ${aliasStr}`;
3106
3336
  }
3107
- // Handle regular alias (for outer table aliases like "y")
3108
3337
  if (node.alias && node.alias.aliasname) {
3109
3338
  let aliasStr = node.alias.aliasname;
3110
3339
  if (node.alias.colnames && node.alias.colnames.length > 0) {
@@ -5823,38 +6052,82 @@ class Deparser {
5823
6052
  return output.join(' ');
5824
6053
  }
5825
6054
  CreatePolicyStmt(node, context) {
5826
- const output = ['CREATE', 'POLICY'];
6055
+ const output = [];
6056
+ const initialParts = ['CREATE', 'POLICY'];
5827
6057
  if (node.policy_name) {
5828
- output.push(`"${node.policy_name}"`);
6058
+ initialParts.push(`"${node.policy_name}"`);
5829
6059
  }
5830
- output.push('ON');
6060
+ output.push(initialParts.join(' '));
6061
+ // Add ON clause on new line in pretty mode
5831
6062
  if (node.table) {
5832
- output.push(this.RangeVar(node.table, context));
6063
+ if (this.formatter.isPretty()) {
6064
+ output.push(this.formatter.newline() + this.formatter.indent(`ON ${this.RangeVar(node.table, context)}`));
6065
+ }
6066
+ else {
6067
+ output.push('ON');
6068
+ output.push(this.RangeVar(node.table, context));
6069
+ }
5833
6070
  }
5834
6071
  // Handle AS RESTRICTIVE/PERMISSIVE clause
5835
6072
  if (node.permissive === undefined) {
5836
- output.push('AS', 'RESTRICTIVE');
6073
+ if (this.formatter.isPretty()) {
6074
+ output.push(this.formatter.newline() + this.formatter.indent('AS RESTRICTIVE'));
6075
+ }
6076
+ else {
6077
+ output.push('AS', 'RESTRICTIVE');
6078
+ }
5837
6079
  }
5838
6080
  else if (node.permissive === true) {
5839
- output.push('AS', 'PERMISSIVE');
6081
+ if (this.formatter.isPretty()) {
6082
+ output.push(this.formatter.newline() + this.formatter.indent('AS PERMISSIVE'));
6083
+ }
6084
+ else {
6085
+ output.push('AS', 'PERMISSIVE');
6086
+ }
5840
6087
  }
5841
6088
  if (node.cmd_name) {
5842
- output.push('FOR', node.cmd_name.toUpperCase());
6089
+ if (this.formatter.isPretty()) {
6090
+ output.push(this.formatter.newline() + this.formatter.indent(`FOR ${node.cmd_name.toUpperCase()}`));
6091
+ }
6092
+ else {
6093
+ output.push('FOR', node.cmd_name.toUpperCase());
6094
+ }
5843
6095
  }
5844
6096
  if (node.roles && node.roles.length > 0) {
5845
- output.push('TO');
5846
6097
  const roles = list_utils_1.ListUtils.unwrapList(node.roles).map(role => this.visit(role, context));
5847
- output.push(roles.join(', '));
6098
+ if (this.formatter.isPretty()) {
6099
+ output.push(this.formatter.newline() + this.formatter.indent(`TO ${roles.join(', ')}`));
6100
+ }
6101
+ else {
6102
+ output.push('TO');
6103
+ output.push(roles.join(', '));
6104
+ }
5848
6105
  }
5849
6106
  if (node.qual) {
5850
- output.push('USING');
5851
- output.push(`(${this.visit(node.qual, context)})`);
6107
+ if (this.formatter.isPretty()) {
6108
+ const qualExpr = this.visit(node.qual, context);
6109
+ output.push(this.formatter.newline() + this.formatter.indent('USING ('));
6110
+ output.push(this.formatter.newline() + this.formatter.indent(this.formatter.indent(qualExpr)));
6111
+ output.push(this.formatter.newline() + this.formatter.indent(')'));
6112
+ }
6113
+ else {
6114
+ output.push('USING');
6115
+ output.push(`(${this.visit(node.qual, context)})`);
6116
+ }
5852
6117
  }
5853
6118
  if (node.with_check) {
5854
- output.push('WITH CHECK');
5855
- output.push(`(${this.visit(node.with_check, context)})`);
6119
+ if (this.formatter.isPretty()) {
6120
+ const checkExpr = this.visit(node.with_check, context);
6121
+ output.push(this.formatter.newline() + this.formatter.indent('WITH CHECK ('));
6122
+ output.push(this.formatter.newline() + this.formatter.indent(this.formatter.indent(checkExpr)));
6123
+ output.push(this.formatter.newline() + this.formatter.indent(')'));
6124
+ }
6125
+ else {
6126
+ output.push('WITH CHECK');
6127
+ output.push(`(${this.visit(node.with_check, context)})`);
6128
+ }
5856
6129
  }
5857
- return output.join(' ');
6130
+ return this.formatter.isPretty() ? output.join('') : output.join(' ');
5858
6131
  }
5859
6132
  AlterPolicyStmt(node, context) {
5860
6133
  const output = ['ALTER', 'POLICY'];
@@ -9720,5 +9993,9 @@ class Deparser {
9720
9993
  }
9721
9994
  return output.join(' ');
9722
9995
  }
9996
+ containsMultilineStringLiteral(content) {
9997
+ const stringLiteralRegex = /'[^']*\n[^']*'/g;
9998
+ return stringLiteralRegex.test(content);
9999
+ }
9723
10000
  }
9724
10001
  exports.Deparser = Deparser;