pgsql-deparser 13.15.0 → 14.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.
Files changed (62) hide show
  1. package/README.md +88 -45
  2. package/dist/README.md +160 -0
  3. package/dist/deparser/deparser.d.ts +301 -0
  4. package/dist/deparser/deparser.js +10005 -0
  5. package/dist/deparser/index.d.ts +9 -0
  6. package/dist/deparser/index.js +17 -0
  7. package/dist/deparser/utils/list-utils.d.ts +8 -0
  8. package/dist/deparser/utils/list-utils.js +30 -0
  9. package/dist/deparser/utils/quote-utils.d.ts +24 -0
  10. package/dist/deparser/utils/quote-utils.js +89 -0
  11. package/dist/deparser/utils/sql-formatter.d.ts +16 -0
  12. package/dist/deparser/utils/sql-formatter.js +40 -0
  13. package/dist/deparser/visitors/base.d.ts +21 -0
  14. package/dist/deparser/visitors/base.js +34 -0
  15. package/dist/esm/deparser/deparser.js +10001 -0
  16. package/dist/esm/deparser/index.js +13 -0
  17. package/dist/esm/deparser/utils/list-utils.js +26 -0
  18. package/dist/esm/deparser/utils/quote-utils.js +85 -0
  19. package/dist/esm/deparser/utils/sql-formatter.js +36 -0
  20. package/dist/esm/deparser/visitors/base.js +30 -0
  21. package/dist/esm/index.js +15 -0
  22. package/dist/esm/v14-to-v15.js +1220 -0
  23. package/dist/esm/v14-to-v17-direct.js +67 -0
  24. package/dist/esm/v15-to-v16.js +2881 -0
  25. package/dist/esm/v16-to-v17.js +1488 -0
  26. package/dist/index.d.ts +9 -0
  27. package/dist/index.js +19 -0
  28. package/dist/package.json +42 -0
  29. package/dist/v14-to-v15.d.ts +616 -0
  30. package/dist/v14-to-v15.js +1224 -0
  31. package/dist/v14-to-v17-direct.d.ts +23 -0
  32. package/dist/v14-to-v17-direct.js +71 -0
  33. package/dist/v15-to-v16.d.ts +627 -0
  34. package/dist/v15-to-v16.js +2885 -0
  35. package/dist/v16-to-v17.d.ts +638 -0
  36. package/dist/v16-to-v17.js +1492 -0
  37. package/package.json +26 -73
  38. package/src/deparser/deparser.ts +10026 -0
  39. package/src/deparser/index.ts +14 -0
  40. package/src/deparser/utils/list-utils.ts +27 -0
  41. package/src/deparser/utils/quote-utils.ts +86 -0
  42. package/src/deparser/utils/sql-formatter.ts +37 -0
  43. package/src/deparser/visitors/base.ts +40 -0
  44. package/src/index.ts +27 -3
  45. package/src/v14-to-v15.ts +1621 -0
  46. package/src/v14-to-v17-direct.ts +68 -0
  47. package/src/v15-to-v16.ts +3290 -0
  48. package/src/v16-to-v17.ts +1897 -0
  49. package/tsconfig.esm.json +8 -0
  50. package/tsconfig.json +26 -0
  51. package/main/deparser.js +0 -3481
  52. package/main/index.js +0 -10
  53. package/main/utils/index.js +0 -97
  54. package/module/deparser.js +0 -3478
  55. package/module/index.js +0 -3
  56. package/module/utils/index.js +0 -90
  57. package/src/deparser.ts +0 -4220
  58. package/src/utils/index.ts +0 -92
  59. package/types/deparser.d.ts +0 -119
  60. package/types/index.d.ts +0 -3
  61. package/types/utils/index.d.ts +0 -4
  62. /package/{LICENSE → dist/LICENSE} +0 -0
@@ -1,3478 +0,0 @@
1
- // @ts-nocheck
2
- import { format } from 'util';
3
- import { objtypeName, getConstraintFromConstrType } from 'pgsql-enums';
4
- let TAB_CHAR = '\t';
5
- let NEWLINE_CHAR = '\n';
6
- const isEmptyObject = (obj) => {
7
- return !obj || (typeof obj === 'object' && !Object.keys(obj).length);
8
- };
9
- const dotty = require('dotty');
10
- const fail = (type, node) => {
11
- throw new Error(format('Unhandled %s node: %s', type, JSON.stringify(node)));
12
- };
13
- // select word from pg_get_keywords() where catcode = 'R';
14
- const RESERVED_WORDS = new Set([
15
- 'all',
16
- 'analyse',
17
- 'analyze',
18
- 'and',
19
- 'any',
20
- 'array',
21
- 'as',
22
- 'asc',
23
- 'asymmetric',
24
- 'both',
25
- 'case',
26
- 'cast',
27
- 'check',
28
- 'collate',
29
- 'column',
30
- 'constraint',
31
- 'create',
32
- 'current_catalog',
33
- 'current_date',
34
- 'current_role',
35
- 'current_time',
36
- 'current_timestamp',
37
- 'current_user',
38
- 'default',
39
- 'deferrable',
40
- 'desc',
41
- 'distinct',
42
- 'do',
43
- 'else',
44
- 'end',
45
- 'except',
46
- 'false',
47
- 'fetch',
48
- 'for',
49
- 'foreign',
50
- 'from',
51
- 'grant',
52
- 'group',
53
- 'having',
54
- 'in',
55
- 'initially',
56
- 'intersect',
57
- 'into',
58
- 'lateral',
59
- 'leading',
60
- 'limit',
61
- 'localtime',
62
- 'localtimestamp',
63
- 'not',
64
- 'null',
65
- 'offset',
66
- 'on',
67
- 'only',
68
- 'or',
69
- 'order',
70
- 'placing',
71
- 'primary',
72
- 'references',
73
- 'returning',
74
- 'select',
75
- 'session_user',
76
- 'some',
77
- 'symmetric',
78
- 'table',
79
- 'then',
80
- 'to',
81
- 'trailing',
82
- 'true',
83
- 'union',
84
- 'unique',
85
- 'user',
86
- 'using',
87
- 'variadic',
88
- 'when',
89
- 'where',
90
- 'window',
91
- 'with'
92
- ]);
93
- // https://github.com/pganalyze/libpg_query/blob/b2790f8140721ff7f047167ecd7d44267b0a3880/src/postgres/include/storage/lockdefs.h
94
- const LOCK_MODES = {
95
- 1: 'ACCESS SHARE',
96
- 2: 'ROW SHARE',
97
- 3: 'ROW EXCLUSIVE',
98
- 4: 'SHARE UPDATE EXCLUSIVE',
99
- 5: 'SHARE',
100
- 6: 'SHARE ROW',
101
- 7: 'EXCLUSIVE',
102
- 8: 'ACCESS EXCLUSIVE'
103
- };
104
- const isReserved = (value) => RESERVED_WORDS.has(value.toLowerCase());
105
- // has uppercase and lowercase, or non word characters
106
- const needsQuotesRegex = /[a-z]+[\W\w]*[A-Z]+|[A-Z]+[\W\w]*[a-z]+|\W/;
107
- // usually the AST lowercases all the things, so if we
108
- // have both, the author most likely used double quotes
109
- const needsQuotes = (value) => needsQuotesRegex.test(value) || isReserved(value);
110
- const compact = (o) => o.filter((e) => {
111
- const isFalsy = !e;
112
- return !isFalsy && e.toString().length;
113
- });
114
- const flatten = (o) => {
115
- const flattened = [];
116
- for (let i = 0; i < o.length; i++) {
117
- if (Array.isArray(o[i])) {
118
- for (let j = 0; j < o[i].length; j++) {
119
- flattened.push(o[i][j]);
120
- }
121
- }
122
- else {
123
- flattened.push(o[i]);
124
- }
125
- }
126
- return flattened;
127
- };
128
- const inverted = (o) => {
129
- const objInverted = {};
130
- const keys = Object.keys(o);
131
- for (let i = 0; i < keys.length; i++) {
132
- const key = keys[i];
133
- objInverted[o[key]] = key;
134
- }
135
- return objInverted;
136
- };
137
- const parens = (string) => {
138
- return '(' + string + ')';
139
- };
140
- const indent = (text, count = 1) => text;
141
- const unwrapList = (obj) => obj !== undefined && obj.List !== undefined ? obj.List.items : obj;
142
- export default class Deparser {
143
- static deparse(query, opts) {
144
- return new Deparser(query, opts).deparseQuery();
145
- }
146
- constructor(tree, opts = {}) {
147
- this.tree = tree;
148
- if (opts.hasOwnProperty('newline')) {
149
- NEWLINE_CHAR = opts.newline;
150
- }
151
- if (opts.hasOwnProperty('tab')) {
152
- TAB_CHAR = opts.tab;
153
- }
154
- if (!Array.isArray(this.tree))
155
- this.tree = [this.tree];
156
- }
157
- deparseQuery() {
158
- return this.tree
159
- .map((node) => this.deparse(node))
160
- .join(NEWLINE_CHAR + NEWLINE_CHAR);
161
- }
162
- deparseNodes(nodes, context) {
163
- return unwrapList(nodes).map((node) => {
164
- const unwrapped = unwrapList(node);
165
- return Array.isArray(unwrapped)
166
- ? this.list(unwrapped, ', ', '', context)
167
- : this.deparse(node, context);
168
- });
169
- }
170
- deparseReturningList(list, context) {
171
- return unwrapList(list)
172
- .map((returning) => this.deparse(returning.ResTarget.val, context) +
173
- (returning.ResTarget.name
174
- ? ' AS ' + this.quote(returning.ResTarget.name)
175
- : ''))
176
- .join(',');
177
- }
178
- list(nodes, separator = ', ', prefix = '', context) {
179
- if (!nodes) {
180
- return '';
181
- }
182
- return this.deparseNodes(nodes, context)
183
- .map((l) => `${prefix}${l}`)
184
- .join(separator);
185
- }
186
- listQuotes(nodes, separator = ', ') {
187
- return this.list(unwrapList(nodes), separator)
188
- .split(separator)
189
- .map((a) => this.quote(a.trim()))
190
- .join(separator);
191
- }
192
- quote(value) {
193
- if (value == null) {
194
- return null;
195
- }
196
- const unwrapped = unwrapList(value);
197
- if (Array.isArray(unwrapped)) {
198
- return unwrapped.map((o) => this.quote(o));
199
- }
200
- if (needsQuotes(value)) {
201
- return '"' + value + '"';
202
- }
203
- return value;
204
- }
205
- // SELECT encode(E'''123\\000\\001', 'base64')
206
- escape(literal) {
207
- return "'" + literal.replace(/'/g, "''") + "'";
208
- }
209
- getPgCatalogTypeName(typeName, size) {
210
- switch (typeName) {
211
- case 'bpchar':
212
- if (size != null) {
213
- return 'char';
214
- }
215
- // return `pg_catalog.bpchar` below so that the following is symmetric
216
- // SELECT char 'c' = char 'c' AS true
217
- return 'pg_catalog.bpchar';
218
- case 'varchar':
219
- return 'varchar';
220
- case 'numeric':
221
- return 'numeric';
222
- case 'bool':
223
- return 'boolean';
224
- case 'int2':
225
- return 'smallint';
226
- case 'int4':
227
- return 'int';
228
- case 'int8':
229
- return 'bigint';
230
- case 'real':
231
- return 'pg_catalog.float4';
232
- case 'time':
233
- return 'time';
234
- case 'timestamp':
235
- return 'timestamp';
236
- case 'interval':
237
- return 'interval';
238
- case 'bit':
239
- return 'bit';
240
- default:
241
- return 'pg_catalog.' + typeName;
242
- }
243
- }
244
- type(names, args) {
245
- const catalogAndType = unwrapList(names).map((name) => this.deparse(name));
246
- const catalog = catalogAndType[0];
247
- const type = catalogAndType[1];
248
- const mods = (name, size) => {
249
- if (size != null) {
250
- return name + '(' + size + ')';
251
- }
252
- return name;
253
- };
254
- // handle the special "char" (in quotes) type
255
- if (catalog === 'char' && !type) {
256
- return mods('"char"', args);
257
- }
258
- if (catalog === 'pg_catalog' && type === 'char') {
259
- return mods('pg_catalog."char"', args);
260
- }
261
- if (catalog !== 'pg_catalog') {
262
- return mods(this.listQuotes(names, '.'), args);
263
- }
264
- const res = this.getPgCatalogTypeName(type, args);
265
- return mods(res, args);
266
- }
267
- deparse(item, context) {
268
- if (item == null) {
269
- return null;
270
- }
271
- if (typeof item === 'number' || item instanceof Number) {
272
- return item;
273
- }
274
- const type = Object.keys(item)[0];
275
- const node = item[type];
276
- if (this[type] == null) {
277
- throw new Error(type + ' is not implemented: ' + JSON.stringify(node));
278
- }
279
- return this[type](node, context);
280
- }
281
- RawStmt(node, context = {}) {
282
- if (node.stmt_len) {
283
- return this.deparse(node.stmt, context) + ';';
284
- }
285
- return this.deparse(node.stmt, context);
286
- }
287
- RuleStmt(node, context = {}) {
288
- const output = [];
289
- output.push('CREATE');
290
- output.push('RULE');
291
- if (node.rulename === '_RETURN') {
292
- // special rules
293
- output.push('"_RETURN"');
294
- }
295
- else {
296
- output.push(node.rulename);
297
- }
298
- output.push('AS');
299
- output.push('ON');
300
- switch (node.event) {
301
- case 'CMD_SELECT':
302
- output.push('SELECT');
303
- break;
304
- case 'CMD_UPDATE':
305
- output.push('UPDATE');
306
- break;
307
- case 'CMD_INSERT':
308
- output.push('INSERT');
309
- break;
310
- case 'CMD_DELETE':
311
- output.push('DELETE');
312
- break;
313
- default:
314
- throw new Error('event type not yet implemented for RuleStmt');
315
- }
316
- output.push('TO');
317
- output.push(this.RangeVar(node.relation, context));
318
- if (node.whereClause) {
319
- output.push('WHERE');
320
- output.push(this.deparse(node.whereClause, context));
321
- }
322
- output.push('DO');
323
- if (node.instead) {
324
- output.push('INSTEAD');
325
- }
326
- const actions = unwrapList(node.actions);
327
- if (!actions || !actions.length) {
328
- output.push('NOTHING');
329
- }
330
- else {
331
- // TODO how do multiple actions happen?
332
- output.push(this.deparse(actions[0], context));
333
- }
334
- return output.join(' ');
335
- }
336
- A_Expr(node, context = {}) {
337
- const output = [];
338
- const nodeName = unwrapList(node.name);
339
- switch (node.kind) {
340
- case 'AEXPR_OP': {
341
- let operator;
342
- if (node.lexpr) {
343
- // PARENS
344
- if (node.lexpr !== undefined && node.lexpr.A_Expr !== undefined) {
345
- output.push(parens(this.deparse(node.lexpr, context)));
346
- }
347
- else {
348
- output.push(this.deparse(node.lexpr, context));
349
- }
350
- }
351
- if (nodeName.length > 1) {
352
- const schema = this.deparse(nodeName[0], context);
353
- operator = this.deparse(nodeName[1], context);
354
- output.push(`OPERATOR(${schema}.${operator})`);
355
- }
356
- else {
357
- operator = this.deparse(nodeName[0], context);
358
- output.push(operator);
359
- }
360
- if (node.rexpr) {
361
- // PARENS
362
- if (node.rexpr !== undefined && node.rexpr.A_Expr !== undefined) {
363
- output.push(parens(this.deparse(node.rexpr, context)));
364
- }
365
- else {
366
- output.push(this.deparse(node.rexpr, context));
367
- }
368
- }
369
- if (output.length === 2) {
370
- return output.join('');
371
- }
372
- if (['->', '->>'].includes(operator)) {
373
- return output.join('');
374
- }
375
- return output.join(' ');
376
- }
377
- case 'AEXPR_OP_ANY':
378
- /* scalar op ANY (array) */
379
- output.push(this.deparse(node.lexpr, context));
380
- output.push(format('ANY (%s)', this.deparse(node.rexpr, context)));
381
- return output.join(` ${this.deparse(nodeName[0], context)} `);
382
- case 'AEXPR_OP_ALL':
383
- /* scalar op ALL (array) */
384
- output.push(this.deparse(node.lexpr, context));
385
- output.push(format('ALL (%s)', this.deparse(node.rexpr, context)));
386
- return output.join(` ${this.deparse(nodeName[0], context)} `);
387
- case 'AEXPR_DISTINCT':
388
- /* IS DISTINCT FROM - name must be "=" */
389
- return format('%s IS DISTINCT FROM %s', this.deparse(node.lexpr, context), this.deparse(node.rexpr, context));
390
- case 'AEXPR_NOT_DISTINCT':
391
- /* IS NOT DISTINCT FROM - name must be "=" */
392
- return format('%s IS NOT DISTINCT FROM %s', this.deparse(node.lexpr, context), this.deparse(node.rexpr, context));
393
- case 'AEXPR_NULLIF':
394
- /* NULLIF - name must be "=" */
395
- return format('NULLIF(%s, %s)', this.deparse(node.lexpr, context), this.deparse(node.rexpr, context));
396
- case 'AEXPR_OF': {
397
- /* IS [NOT] OF - name must be "=" or "<>" */
398
- const op = nodeName[0].String.str === '=' ? 'IS OF' : 'IS NOT OF';
399
- return format('%s %s (%s)', this.deparse(node.lexpr, context), op, this.list(node.rexpr, ', ', '', context));
400
- }
401
- case 'AEXPR_IN': {
402
- /* [NOT] IN - name must be "=" or "<>" */
403
- const operator = nodeName[0].String.str === '=' ? 'IN' : 'NOT IN';
404
- return format('%s %s (%s)', this.deparse(node.lexpr, context), operator, this.list(node.rexpr, ', ', '', context));
405
- }
406
- case 'AEXPR_LIKE':
407
- /* [NOT] LIKE - name must be "~~" or "!~~" */
408
- output.push(this.deparse(node.lexpr, context));
409
- if (nodeName[0].String.str === '!~~') {
410
- output.push(format('NOT LIKE (%s)', this.deparse(node.rexpr, context)));
411
- }
412
- else {
413
- output.push(format('LIKE (%s)', this.deparse(node.rexpr, context)));
414
- }
415
- return output.join(' ');
416
- case 'AEXPR_ILIKE':
417
- /* [NOT] ILIKE - name must be "~~*" or "!~~*" */
418
- output.push(this.deparse(node.lexpr, context));
419
- if (nodeName[0].String.str === '!~~*') {
420
- output.push(format('NOT ILIKE (%s)', this.deparse(node.rexpr, context)));
421
- }
422
- else {
423
- output.push(format('ILIKE (%s)', this.deparse(node.rexpr, context)));
424
- }
425
- return output.join(' ');
426
- case 'AEXPR_SIMILAR':
427
- // SIMILAR TO emits a similar_escape FuncCall node with the first argument
428
- output.push(this.deparse(node.lexpr, context));
429
- if (nodeName[0].String.str === '~') {
430
- if (unwrapList(node.rexpr.FuncCall.args).length > 1) {
431
- output.push(format('SIMILAR TO %s ESCAPE %s', this.deparse(unwrapList(node.rexpr.FuncCall.args)[0], context), this.deparse(unwrapList(node.rexpr.FuncCall.args)[1], context)));
432
- }
433
- else {
434
- output.push(format('SIMILAR TO %s', this.deparse(unwrapList(node.rexpr.FuncCall.args)[0], context)));
435
- }
436
- }
437
- else {
438
- if (unwrapList(node.rexpr.FuncCall.args).length > 1) {
439
- output.push(format('NOT SIMILAR TO %s ESCAPE %s', this.deparse(unwrapList(node.rexpr.FuncCall.args)[0], context), this.deparse(unwrapList(node.rexpr.FuncCall.args)[1], context)));
440
- }
441
- else {
442
- output.push(format('NOT SIMILAR TO %s', this.deparse(unwrapList(node.rexpr.FuncCall.args)[0], context)));
443
- }
444
- }
445
- return output.join(' ');
446
- case 'AEXPR_BETWEEN':
447
- output.push(this.deparse(node.lexpr, context));
448
- output.push(format('BETWEEN %s AND %s', this.deparse(unwrapList(node.rexpr)[0], context), this.deparse(unwrapList(node.rexpr)[1], context)));
449
- return output.join(' ');
450
- case 'AEXPR_NOT_BETWEEN':
451
- output.push(this.deparse(node.lexpr, context));
452
- output.push(format('NOT BETWEEN %s AND %s', this.deparse(unwrapList(node.rexpr)[0], context), this.deparse(unwrapList(node.rexpr)[1], context)));
453
- return output.join(' ');
454
- case 'AEXPR_BETWEEN_SYM':
455
- output.push(this.deparse(node.lexpr, context));
456
- output.push(format('BETWEEN SYMMETRIC %s AND %s', this.deparse(unwrapList(node.rexpr)[0], context), this.deparse(unwrapList(node.rexpr)[1], context)));
457
- return output.join(' ');
458
- case 'AEXPR_NOT_BETWEEN_SYM':
459
- output.push(this.deparse(node.lexpr, context));
460
- output.push(format('NOT BETWEEN SYMMETRIC %s AND %s', this.deparse(unwrapList(node.rexpr)[0], context), this.deparse(unwrapList(node.rexpr)[1], context)));
461
- return output.join(' ');
462
- // case 15:
463
- // AEXPR_PAREN
464
- default:
465
- return fail('A_Expr', node);
466
- }
467
- }
468
- Alias(node, context = {}) {
469
- const name = node.aliasname;
470
- const output = ['AS'];
471
- if (node.colnames) {
472
- output.push(this.quote(name) + parens(this.listQuotes(node.colnames)));
473
- }
474
- else {
475
- output.push(this.quote(name));
476
- }
477
- return output.join(' ');
478
- }
479
- A_ArrayExpr(node) {
480
- return format('ARRAY[%s]', this.list(node.elements));
481
- }
482
- A_Const(node, context = {}) {
483
- if (node.val.String) {
484
- return this.escape(this.deparse(node.val, context));
485
- }
486
- return this.deparse(node.val, context);
487
- }
488
- A_Indices(node, context = {}) {
489
- if (node.lidx) {
490
- return format('[%s:%s]', this.deparse(node.lidx, context), this.deparse(node.uidx, context));
491
- }
492
- return format('[%s]', this.deparse(node.uidx, context));
493
- }
494
- A_Indirection(node, context = {}) {
495
- const output = [`(${this.deparse(node.arg, context)})`];
496
- // TODO(zhm) figure out the actual rules for when a '.' is needed
497
- //
498
- // select a.b[0] from a;
499
- // select (select row(1)).*
500
- // select c2[2].f2 from comptable
501
- // select c2.a[2].f2[1].f3[0].a1 from comptable
502
- const indirection = unwrapList(node.indirection);
503
- for (let i = 0; i < indirection.length; i++) {
504
- const subnode = indirection[i];
505
- if (subnode.String || subnode.A_Star) {
506
- const value = subnode.A_Star ? '*' : this.quote(subnode.String.str);
507
- output.push(`.${value}`);
508
- }
509
- else {
510
- output.push(this.deparse(subnode, context));
511
- }
512
- }
513
- return output.join('');
514
- }
515
- A_Star(node) {
516
- return '*';
517
- }
518
- BitString(node) {
519
- const prefix = node.str[0];
520
- return `${prefix}'${node.str.substring(1)}'`;
521
- }
522
- BoolExpr(node, context = {}) {
523
- let fmt_str = '%s';
524
- if (context.bool) {
525
- fmt_str = '(%s)';
526
- }
527
- const ctx = Object.assign({}, context);
528
- ctx.bool = true;
529
- switch (node.boolop) {
530
- case 'AND_EXPR':
531
- return format(fmt_str, this.list(node.args, ' AND ', '', ctx));
532
- case 'OR_EXPR':
533
- return format(fmt_str, this.list(node.args, ' OR ', '', ctx));
534
- case 'NOT_EXPR':
535
- return format('NOT (%s)', this.deparse(unwrapList(node.args)[0], context));
536
- default:
537
- return fail('BoolExpr', node);
538
- }
539
- }
540
- BooleanTest(node, context = {}) {
541
- const output = [];
542
- const ctx = Object.assign({}, context);
543
- ctx.bool = true;
544
- output.push(this.deparse(node.arg, ctx));
545
- switch (node.booltesttype) {
546
- case 'IS_TRUE':
547
- output.push('IS TRUE');
548
- break;
549
- case 'IS_NOT_TRUE':
550
- output.push('IS NOT TRUE');
551
- break;
552
- case 'IS_FALSE':
553
- output.push('IS FALSE');
554
- break;
555
- case 'IS_NOT_FALSE':
556
- output.push('IS NOT FALSE');
557
- break;
558
- case 'IS_UNKNOWN':
559
- output.push('IS UNKNOWN');
560
- break;
561
- case 'IS_NOT_UNKNOWN':
562
- output.push('IS NOT UNKNOWN');
563
- break;
564
- }
565
- return output.join(' ');
566
- }
567
- CaseExpr(node, context = {}) {
568
- const output = ['CASE'];
569
- if (node.arg) {
570
- output.push(this.deparse(node.arg, context));
571
- }
572
- const args = unwrapList(node.args);
573
- for (let i = 0; i < args.length; i++) {
574
- output.push(this.deparse(args[i], context));
575
- }
576
- if (node.defresult) {
577
- output.push('ELSE');
578
- output.push(this.deparse(node.defresult, context));
579
- }
580
- output.push('END');
581
- return output.join(' ');
582
- }
583
- CoalesceExpr(node, context = {}) {
584
- return format('COALESCE(%s)', this.list(node.args, ', ', '', context));
585
- }
586
- CollateClause(node, context = {}) {
587
- const output = [];
588
- if (node.arg) {
589
- output.push(this.deparse(node.arg, context));
590
- }
591
- output.push('COLLATE');
592
- if (node.collname) {
593
- output.push(this.quote(this.deparseNodes(node.collname, context)));
594
- }
595
- return output.join(' ');
596
- }
597
- CompositeTypeStmt(node, context = {}) {
598
- const output = [];
599
- output.push('CREATE TYPE');
600
- output.push(this.RangeVar(node.typevar, context));
601
- output.push('AS');
602
- output.push('(');
603
- output.push(this.list(node.coldeflist, `,${NEWLINE_CHAR}`, TAB_CHAR, context));
604
- output.push(')');
605
- return output.join(' ');
606
- }
607
- RenameStmt(node, context = {}) {
608
- const output = [];
609
- if (node.renameType === 'OBJECT_FUNCTION' ||
610
- node.renameType === 'OBJECT_FOREIGN_TABLE' ||
611
- node.renameType === 'OBJECT_FDW' ||
612
- node.renameType === 'OBJECT_FOREIGN_SERVER') {
613
- output.push('ALTER');
614
- output.push(objtypeName(node.renameType));
615
- if (node.missing_ok) {
616
- output.push('IF EXISTS');
617
- }
618
- output.push(this.deparse(node.object, context));
619
- output.push('RENAME');
620
- output.push('TO');
621
- output.push(this.quote(node.newname));
622
- }
623
- else if (node.renameType === 'OBJECT_ATTRIBUTE') {
624
- output.push('ALTER');
625
- output.push(objtypeName(node.relationType));
626
- if (node.missing_ok) {
627
- output.push('IF EXISTS');
628
- }
629
- output.push(this.RangeVar(node.relation, context));
630
- output.push('RENAME');
631
- output.push(objtypeName(node.renameType));
632
- output.push(this.quote(node.subname));
633
- output.push('TO');
634
- output.push(this.quote(node.newname));
635
- }
636
- else if (node.renameType === 'OBJECT_DOMAIN' ||
637
- node.renameType === 'OBJECT_TYPE') {
638
- output.push('ALTER');
639
- output.push(objtypeName(node.renameType));
640
- if (node.missing_ok) {
641
- output.push('IF EXISTS');
642
- }
643
- const typObj = {
644
- TypeName: {
645
- names: node.object
646
- }
647
- };
648
- output.push(this.deparse(typObj, context));
649
- output.push('RENAME');
650
- output.push('TO');
651
- output.push(this.quote(node.newname));
652
- }
653
- else if (node.renameType === 'OBJECT_SCHEMA') {
654
- output.push('ALTER');
655
- output.push(objtypeName(node.renameType));
656
- if (node.missing_ok) {
657
- output.push('IF EXISTS');
658
- }
659
- output.push(this.quote(node.subname));
660
- output.push('RENAME');
661
- output.push('TO');
662
- output.push(this.quote(node.newname));
663
- }
664
- else if (node.renameType === 'OBJECT_DOMCONSTRAINT') {
665
- output.push('ALTER');
666
- output.push('DOMAIN');
667
- if (node.missing_ok) {
668
- output.push('IF EXISTS');
669
- }
670
- const typObj = {
671
- TypeName: {
672
- names: node.object
673
- }
674
- };
675
- output.push(this.deparse(typObj, context));
676
- output.push('RENAME CONSTRAINT');
677
- output.push(this.quote(node.subname));
678
- output.push('TO');
679
- output.push(this.quote(node.newname));
680
- }
681
- else {
682
- output.push('ALTER');
683
- output.push('TABLE');
684
- if (node.missing_ok) {
685
- output.push('IF EXISTS');
686
- }
687
- output.push(this.RangeVar(node.relation, context));
688
- output.push('RENAME');
689
- output.push(this.quote(node.subname));
690
- output.push('TO');
691
- output.push(this.quote(node.newname));
692
- }
693
- if (node.behavior === 'DROP_CASCADE') {
694
- output.push('CASCADE');
695
- }
696
- return output.join(' ');
697
- }
698
- AlterOwnerStmt(node, context = {}) {
699
- const output = [];
700
- output.push('ALTER');
701
- output.push(objtypeName(node.objectType));
702
- const unwrapped = unwrapList(node.object);
703
- if (Array.isArray(unwrapped)) {
704
- output.push(this.listQuotes(unwrapped, '.'));
705
- }
706
- else {
707
- output.push(this.deparse(node.object, context));
708
- }
709
- output.push('OWNER TO');
710
- output.push(this.RoleSpec(node.newowner, context));
711
- return output.join(' ');
712
- }
713
- AlterObjectSchemaStmt(node, context = {}) {
714
- const output = [];
715
- if (node.objectType === 'OBJECT_TABLE') {
716
- output.push('ALTER');
717
- output.push(objtypeName(node.objectType));
718
- if (node.missing_ok) {
719
- output.push('IF EXISTS');
720
- }
721
- output.push(this.RangeVar(node.relation, context));
722
- output.push('SET SCHEMA');
723
- output.push(this.quote(node.newschema));
724
- }
725
- else {
726
- output.push('ALTER');
727
- output.push(objtypeName(node.objectType));
728
- if (node.missing_ok) {
729
- output.push('IF EXISTS');
730
- }
731
- const unwrapped = unwrapList(node.object);
732
- if (Array.isArray(unwrapped)) {
733
- output.push(this.listQuotes(unwrapped, '.'));
734
- }
735
- else {
736
- output.push(this.deparse(node.object, context));
737
- }
738
- output.push('SET SCHEMA');
739
- output.push(this.quote(node.newschema));
740
- }
741
- return output.join(' ');
742
- }
743
- ColumnDef(node, context = {}) {
744
- const output = [this.quote(node.colname)];
745
- output.push(this.TypeName(node.typeName, context));
746
- if (node.raw_default) {
747
- output.push('USING');
748
- output.push(this.deparse(node.raw_default, context));
749
- }
750
- if (node.constraints) {
751
- output.push(this.list(node.constraints, ' ', '', context));
752
- }
753
- if (node.collClause) {
754
- output.push('COLLATE');
755
- const str = unwrapList(node.collClause.collname)[0].String.str;
756
- output.push(this.quote(str));
757
- }
758
- return compact(output).join(' ');
759
- }
760
- SQLValueFunction(node) {
761
- if (node.op === 'SVFOP_CURRENT_DATE') {
762
- return 'CURRENT_DATE';
763
- }
764
- if (node.op === 'SVFOP_CURRENT_TIMESTAMP') {
765
- return 'CURRENT_TIMESTAMP';
766
- }
767
- if (node.op === 'SVFOP_CURRENT_USER') {
768
- return 'CURRENT_USER';
769
- }
770
- if (node.op === 'SVFOP_SESSION_USER') {
771
- return 'SESSION_USER';
772
- }
773
- throw new Error(`op=${node.op} SQLValueFunction not implemented`);
774
- }
775
- ColumnRef(node, context = {}) {
776
- const KEYWORDS = ['old', 'new'];
777
- const fields = unwrapList(node.fields).map((field) => {
778
- if (field.String) {
779
- const value = this.deparse(field, context);
780
- if (context === 'trigger' && KEYWORDS.includes(value.toLowerCase())) {
781
- return value.toUpperCase();
782
- }
783
- return this.quote(value);
784
- }
785
- return this.deparse(field, context);
786
- });
787
- return fields.join('.');
788
- }
789
- CommentStmt(node, context = {}) {
790
- const output = [];
791
- output.push('COMMENT');
792
- output.push('ON');
793
- output.push(objtypeName(node.objtype));
794
- const object = unwrapList(node.object);
795
- if (node.objtype === 'OBJECT_CAST') {
796
- output.push('(');
797
- output.push(this.deparse(object[0], context));
798
- output.push('AS');
799
- output.push(this.deparse(object[1], context));
800
- output.push(')');
801
- }
802
- else if (node.objtype === 'OBJECT_DOMCONSTRAINT') {
803
- output.push(this.deparse(object[1], context));
804
- output.push('ON');
805
- output.push('DOMAIN');
806
- output.push(this.deparse(object[0], context));
807
- }
808
- else if (node.objtype === 'OBJECT_OPCLASS' ||
809
- node.objtype === 'OBJECT_OPFAMILY') {
810
- output.push(this.deparse(object[1], context));
811
- output.push('USING');
812
- output.push(this.deparse(object[0], context));
813
- }
814
- else if (node.objtype === 'OBJECT_OPERATOR') {
815
- output.push(this.deparse(object, 'noquotes'));
816
- }
817
- else if (node.objtype === 'OBJECT_POLICY') {
818
- output.push(this.deparse(object[1], context));
819
- output.push('ON');
820
- output.push(this.deparse(object[0], context));
821
- }
822
- else if (node.objtype === 'OBJECT_ROLE') {
823
- output.push(this.deparse(object, context));
824
- }
825
- else if (node.objtype === 'OBJECT_RULE') {
826
- output.push(this.deparse(object[1], context));
827
- output.push('ON');
828
- output.push(this.deparse(object[0], context));
829
- }
830
- else if (node.objtype === 'OBJECT_TABCONSTRAINT') {
831
- if (object.length === 3) {
832
- output.push(this.deparse(object[2], context));
833
- output.push('ON');
834
- output.push(this.deparse(object[0], context) +
835
- '.' +
836
- this.deparse(object[1], context));
837
- }
838
- else {
839
- output.push(this.deparse(object[1], context));
840
- output.push('ON');
841
- output.push(this.deparse(object[0], context));
842
- }
843
- }
844
- else if (node.objtype === 'OBJECT_TRANSFORM') {
845
- output.push('FOR');
846
- output.push(this.deparse(object[0], context));
847
- output.push('LANGUAGE');
848
- output.push(this.deparse(object[1], context));
849
- }
850
- else if (node.objtype === 'OBJECT_TRIGGER') {
851
- output.push(this.deparse(object[1], context));
852
- output.push('ON');
853
- output.push(this.deparse(object[0], context));
854
- }
855
- else {
856
- if (node.objtype === 'OBJECT_LARGEOBJECT') {
857
- output.push(dotty.get(node, 'object.Integer.ival'));
858
- }
859
- else if (object instanceof Array) {
860
- output.push(this.listQuotes(object, '.'));
861
- }
862
- else {
863
- output.push(this.deparse(object, context));
864
- }
865
- if (node.objargs) {
866
- output.push('(');
867
- output.push(this.list(node.objargs, ', ', '', context));
868
- output.push(')');
869
- }
870
- }
871
- output.push('IS');
872
- const escapeComment = (str) => {
873
- return str.replace(/\\/g, '\\');
874
- };
875
- if (node.comment) {
876
- if (/[^a-zA-Z0-9]/.test(node.comment)) {
877
- // special chars we care about...
878
- output.push(`E'${escapeComment(node.comment)}'`);
879
- }
880
- else {
881
- // find a double \\n or \\ something...
882
- output.push(`'${node.comment}'`);
883
- }
884
- }
885
- else {
886
- output.push('NULL');
887
- }
888
- return output.join(' ');
889
- }
890
- CommonTableExpr(node, context = {}) {
891
- const output = [];
892
- output.push(node.ctename);
893
- if (node.aliascolnames) {
894
- const colnames = this.quote(this.deparseNodes(node.aliascolnames, context));
895
- output.push(`(${colnames.join(', ')})`);
896
- }
897
- output.push('AS');
898
- if (node.ctematerialized === 'CTEMaterializeAlways') {
899
- output.push('MATERIALIZED');
900
- }
901
- else if (node.ctematerialized === 'CTEMaterializeNever') {
902
- output.push('NOT MATERIALIZED');
903
- }
904
- output.push(format('(%s)', this.deparse(node.ctequery)));
905
- return output.join(' ');
906
- }
907
- DefineStmt(node, context = {}) {
908
- const output = [];
909
- output.push('CREATE');
910
- if (node.replace) {
911
- output.push('OR REPLACE');
912
- }
913
- switch (node.kind) {
914
- case 'OBJECT_AGGREGATE':
915
- output.push('AGGREGATE');
916
- break;
917
- case 'OBJECT_OPERATOR':
918
- output.push('OPERATOR');
919
- break;
920
- case 'OBJECT_TYPE':
921
- output.push('TYPE');
922
- break;
923
- case 'OBJECT_TSPARSER':
924
- output.push('TEXT SEARCH PARSER');
925
- break;
926
- case 'OBJECT_TSDICTIONARY':
927
- output.push('TEXT SEARCH DICTIONARY');
928
- break;
929
- case 'OBJECT_TSTEMPLATE':
930
- output.push('TEXT SEARCH TEMPLATE');
931
- break;
932
- case 'OBJECT_TSCONFIGURATION':
933
- output.push('TEXT SEARCH CONFIGURATION');
934
- break;
935
- case 'OBJECT_COLLATION':
936
- output.push('COLLATION');
937
- break;
938
- default:
939
- throw new Error('DefineStmt not recognized');
940
- }
941
- if (node.if_not_exists) {
942
- output.push('IF NOT EXISTS');
943
- }
944
- switch (node.kind) {
945
- case 'OBJECT_AGGREGATE':
946
- // output.push(this.deparse(node.defnames));
947
- output.push(this.list(node.defnames, '.', '', context));
948
- break;
949
- case 'OBJECT_OPERATOR':
950
- output.push(this.list(node.defnames, '.', '', context));
951
- // output.push(this.deparse(node.defnames));
952
- break;
953
- case 'OBJECT_TYPE':
954
- case 'OBJECT_TSPARSER':
955
- case 'OBJECT_TSDICTIONARY':
956
- case 'OBJECT_TSTEMPLATE':
957
- case 'OBJECT_TSCONFIGURATION':
958
- case 'OBJECT_COLLATION':
959
- output.push(this.deparse(node.defnames));
960
- break;
961
- default:
962
- throw new Error('DefineStmt not recognized');
963
- }
964
- if (!node.oldstyle && node.kind == 'OBJECT_AGGREGATE') {
965
- output.push('(');
966
- output.push(`${this.listQuotes(node.args[0], ',')}`);
967
- output.push(')');
968
- }
969
- const definition = unwrapList(node.definition);
970
- if (definition.length > 0) {
971
- output.push('(');
972
- for (let n = 0; n < definition.length; n++) {
973
- const defElement = definition[n].DefElem;
974
- output.push(defElement.defname);
975
- if (defElement.arg) {
976
- output.push('=');
977
- output.push(this.deparse(defElement.arg));
978
- }
979
- if (n !== definition.length - 1) {
980
- output.push(',');
981
- }
982
- }
983
- output.push(')');
984
- }
985
- return output.join(' ');
986
- }
987
- DefElem(node, context = {}) {
988
- if (node.defname === 'transaction_isolation') {
989
- return format('ISOLATION LEVEL %s', node.arg.A_Const.val.String.str.toUpperCase());
990
- }
991
- if (node.defname === 'transaction_read_only') {
992
- return node.arg.A_Const.val.Integer.ival === 0
993
- ? 'READ WRITE'
994
- : 'READ ONLY';
995
- }
996
- if (node.defname === 'transaction_deferrable') {
997
- return node.arg.A_Const.val.Integer.ival === 0
998
- ? 'NOT DEFERRABLE'
999
- : 'DEFERRABLE';
1000
- }
1001
- if (node.defname === 'set') {
1002
- return this.deparse(node.arg, context);
1003
- }
1004
- let name = node.defname;
1005
- if (node.defnamespace) {
1006
- name = `${node.defnamespace}.${node.defname}`;
1007
- }
1008
- if (context === 'generated' || context === 'sequence') {
1009
- switch (name) {
1010
- case 'start': {
1011
- const start = this.deparse(node.arg, context);
1012
- return `START WITH ${start}`;
1013
- }
1014
- case 'increment': {
1015
- const inc = this.deparse(node.arg, context);
1016
- if (context === 'sequence') {
1017
- // we need 'simple' so it doesn't wrap negative numbers in parens
1018
- return `${name} ${this.deparse(node.arg, 'simple')}`;
1019
- }
1020
- return `INCREMENT BY ${inc}`;
1021
- }
1022
- case 'sequence_name': {
1023
- return `SEQUENCE NAME ${this.listQuotes(node.arg, '.')}`;
1024
- }
1025
- case 'cycle': {
1026
- const on = this.deparse(node.arg, context) + '' === '1';
1027
- return on ? 'CYCLE' : 'NO CYCLE';
1028
- }
1029
- case 'minvalue': {
1030
- const off = !node.hasOwnProperty('arg');
1031
- return off
1032
- ? 'NO MINVALUE'
1033
- : `${name} ${this.deparse(node.arg, 'simple')}`;
1034
- }
1035
- case 'maxvalue': {
1036
- const off = !node.hasOwnProperty('arg');
1037
- return off
1038
- ? 'NO MAXVALUE'
1039
- : `${name} ${this.deparse(node.arg, 'simple')}`;
1040
- }
1041
- // alter
1042
- case 'owned_by': {
1043
- const output = [];
1044
- unwrapList(node.arg).forEach((opt) => {
1045
- output.push(this.quote(this.deparse(opt, context)));
1046
- });
1047
- return `OWNED BY ${output.join('.')}`;
1048
- }
1049
- // alter
1050
- case 'restart': {
1051
- if (node.arg) {
1052
- return `RESTART WITH ${this.deparse(node.arg, context)}`;
1053
- }
1054
- return `RESTART`;
1055
- }
1056
- default:
1057
- if (node.arg) {
1058
- // we need 'simple' so it doesn't wrap negative numbers in parens
1059
- return `${name} ${this.deparse(node.arg, 'simple')}`;
1060
- }
1061
- }
1062
- }
1063
- else if (context === 'explain') {
1064
- if (node.arg) {
1065
- return `${name} ${this.deparse(node.arg)}`;
1066
- }
1067
- }
1068
- else if (node.arg) {
1069
- return `${name} = ${this.deparse(node.arg, context)}`;
1070
- }
1071
- return name;
1072
- }
1073
- DoStmt(node) {
1074
- return `DO $$${NEWLINE_CHAR} ${dotty
1075
- .get(node, 'args.0.DefElem.arg.String.str')
1076
- .trim()} $$`;
1077
- }
1078
- Float(node) {
1079
- // wrap negative numbers in parens, SELECT (-2147483648)::int4 * (-1)::int4
1080
- if (node.str[0] === '-') {
1081
- return `(${node.str})`;
1082
- }
1083
- return node.str;
1084
- }
1085
- FuncCall(node, context = {}) {
1086
- const output = [];
1087
- let params = [];
1088
- if (node.args) {
1089
- params = unwrapList(node.args).map((item) => {
1090
- return this.deparse(item, context);
1091
- });
1092
- }
1093
- // COUNT(*)
1094
- if (node.agg_star) {
1095
- params.push('*');
1096
- }
1097
- const name = this.list(node.funcname, '.', '', context);
1098
- const order = [];
1099
- const withinGroup = node.agg_within_group;
1100
- if (node.agg_order) {
1101
- order.push('ORDER BY');
1102
- order.push(this.list(node.agg_order, ', ', '', context));
1103
- }
1104
- const call = [];
1105
- call.push(name + '(');
1106
- if (node.agg_distinct) {
1107
- call.push('DISTINCT ');
1108
- }
1109
- // prepend variadic before the last parameter
1110
- // SELECT CONCAT('|', VARIADIC ARRAY['1','2','3'])
1111
- if (node.func_variadic) {
1112
- params[params.length - 1] = 'VARIADIC ' + params[params.length - 1];
1113
- }
1114
- call.push(params.join(', '));
1115
- if (order.length && !withinGroup) {
1116
- call.push(' ');
1117
- call.push(order.join(' '));
1118
- }
1119
- call.push(')');
1120
- output.push(compact(call).join(''));
1121
- if (order.length && withinGroup) {
1122
- output.push('WITHIN GROUP');
1123
- output.push(parens(order.join(' ')));
1124
- }
1125
- if (node.agg_filter != null) {
1126
- output.push(format('FILTER (WHERE %s)', this.deparse(node.agg_filter, context)));
1127
- }
1128
- if (node.over != null) {
1129
- output.push(format('OVER %s', this.WindowDef(node.over, context)));
1130
- }
1131
- return output.join(' ');
1132
- }
1133
- GroupingFunc(node, context = {}) {
1134
- return 'GROUPING(' + this.list(node.args, ', ', '', context) + ')';
1135
- }
1136
- GroupingSet(node, context = {}) {
1137
- switch (node.kind) {
1138
- case 'GROUPING_SET_EMPTY':
1139
- return '()';
1140
- case 'GROUPING_SET_SIMPLE':
1141
- return fail('GroupingSet', node);
1142
- case 'GROUPING_SET_ROLLUP':
1143
- return 'ROLLUP (' + this.list(node.content, ', ', '', context) + ')';
1144
- case 'GROUPING_SET_CUBE':
1145
- return 'CUBE (' + this.list(node.content, ', ', '', context) + ')';
1146
- case 'GROUPING_SET_SETS':
1147
- return ('GROUPING SETS (' + this.list(node.content, ', ', '', context) + ')');
1148
- default:
1149
- return fail('GroupingSet', node);
1150
- }
1151
- }
1152
- IndexStmt(node, context = {}) {
1153
- const output = [];
1154
- output.push('CREATE');
1155
- if (node.unique) {
1156
- output.push('UNIQUE');
1157
- }
1158
- output.push('INDEX');
1159
- if (node.concurrent) {
1160
- output.push('CONCURRENTLY');
1161
- }
1162
- if (node.idxname) {
1163
- output.push(node.idxname);
1164
- }
1165
- output.push('ON');
1166
- output.push(this.RangeVar(node.relation, context));
1167
- if (node.accessMethod) {
1168
- const accessMethod = node.accessMethod.toUpperCase();
1169
- if (accessMethod !== 'BTREE') {
1170
- output.push('USING');
1171
- output.push(accessMethod);
1172
- }
1173
- }
1174
- if (node.indexParams) {
1175
- output.push('(');
1176
- output.push(this.list(node.indexParams, ', ', '', context));
1177
- output.push(')');
1178
- }
1179
- if (node.indexIncludingParams) {
1180
- output.push('INCLUDE (');
1181
- output.push(this.list(node.indexIncludingParams, ', ', '', context));
1182
- output.push(')');
1183
- }
1184
- if (node.whereClause) {
1185
- output.push('WHERE');
1186
- output.push(this.deparse(node.whereClause, context));
1187
- }
1188
- return output.join(' ');
1189
- }
1190
- IndexElem(node, context = {}) {
1191
- const output = [];
1192
- if (node.name) {
1193
- output.push(node.name);
1194
- if (node.ordering === 'SORTBY_DESC') {
1195
- output.push('DESC');
1196
- }
1197
- else if (node.ordering === 'SORTBY_ASC') {
1198
- output.push('ASC');
1199
- }
1200
- return output.join(' ');
1201
- }
1202
- if (node.expr) {
1203
- return this.deparse(node.expr, context);
1204
- }
1205
- return fail('IndexElem', node);
1206
- }
1207
- InsertStmt(node, context = {}) {
1208
- const output = [];
1209
- if (node.withClause) {
1210
- output.push(this.WithClause(node.withClause, context));
1211
- }
1212
- output.push('INSERT INTO');
1213
- output.push(this.RangeVar(node.relation, context));
1214
- const cols = unwrapList(node.cols);
1215
- if (cols && cols.length) {
1216
- output.push('(');
1217
- output.push(this.list(cols, ', ', '', context));
1218
- output.push(')');
1219
- }
1220
- if (node.selectStmt) {
1221
- output.push(this.deparse(node.selectStmt, context));
1222
- }
1223
- else {
1224
- output.push('DEFAULT VALUES');
1225
- }
1226
- if (node.onConflictClause) {
1227
- const clause = node.onConflictClause;
1228
- output.push('ON CONFLICT');
1229
- if (clause.infer.indexElems) {
1230
- output.push('(');
1231
- output.push(this.list(clause.infer.indexElems, ', ', '', context));
1232
- output.push(')');
1233
- }
1234
- else if (clause.infer.conname) {
1235
- output.push('ON CONSTRAINT');
1236
- output.push(clause.infer.conname);
1237
- }
1238
- switch (clause.action) {
1239
- case 'ONCONFLICT_NOTHING':
1240
- output.push('DO NOTHING');
1241
- break;
1242
- case 'ONCONFLICT_UPDATE':
1243
- output.push('DO');
1244
- output.push(this.UpdateStmt(clause, context));
1245
- break;
1246
- default:
1247
- throw new Error('unhandled CONFLICT CLAUSE');
1248
- }
1249
- }
1250
- if (node.returningList) {
1251
- output.push('RETURNING');
1252
- output.push(this.deparseReturningList(node.returningList, context));
1253
- }
1254
- return output.join(' ');
1255
- }
1256
- SetToDefault(node) {
1257
- return 'DEFAULT';
1258
- }
1259
- MultiAssignRef(node, context = {}) {
1260
- const output = [];
1261
- output.push(this.deparse(node.source, context));
1262
- return output.join(' ');
1263
- }
1264
- DeleteStmt(node, context = {}) {
1265
- const output = [''];
1266
- if (node.withClause) {
1267
- output.push(this.WithClause(node.withClause, context));
1268
- }
1269
- output.push('DELETE');
1270
- output.push('FROM');
1271
- output.push(this.RangeVar(node.relation, context));
1272
- if (node.usingClause) {
1273
- output.push('USING');
1274
- output.push(this.list(node.usingClause, ', ', '', context));
1275
- }
1276
- if (node.whereClause) {
1277
- output.push('WHERE');
1278
- output.push(this.deparse(node.whereClause, context));
1279
- }
1280
- if (node.returningList) {
1281
- output.push('RETURNING');
1282
- output.push(this.deparseReturningList(node.returningList, context));
1283
- }
1284
- return output.join(' ');
1285
- }
1286
- UpdateStmt(node, context = {}) {
1287
- const output = [];
1288
- if (node.withClause) {
1289
- output.push(this.WithClause(node.withClause, context));
1290
- }
1291
- output.push('UPDATE');
1292
- if (node.relation) {
1293
- // onConflictClause no relation..
1294
- output.push(this.RangeVar(node.relation, context));
1295
- }
1296
- output.push('SET');
1297
- const targetList = unwrapList(node.targetList);
1298
- if (targetList && targetList.length) {
1299
- if (targetList[0].ResTarget &&
1300
- targetList[0].ResTarget.val &&
1301
- targetList[0].ResTarget.val.MultiAssignRef) {
1302
- output.push('(');
1303
- output.push(targetList.map((target) => target.ResTarget.name).join(','));
1304
- output.push(')');
1305
- output.push('=');
1306
- output.push(this.deparse(targetList[0].ResTarget.val, context));
1307
- }
1308
- else {
1309
- output.push(targetList.map((target) => this.deparse(target, 'update')).join(','));
1310
- }
1311
- }
1312
- if (node.fromClause) {
1313
- output.push('FROM');
1314
- output.push(this.list(node.fromClause, ', ', '', context));
1315
- }
1316
- if (node.whereClause) {
1317
- output.push('WHERE');
1318
- output.push(this.deparse(node.whereClause, context));
1319
- }
1320
- if (node.returningList) {
1321
- output.push('RETURNING');
1322
- output.push(this.deparseReturningList(node.returningList, context));
1323
- }
1324
- return output.join(' ');
1325
- }
1326
- Integer(node, context = {}) {
1327
- if (node.ival < 0 && context !== 'simple') {
1328
- return `(${node.ival})`;
1329
- }
1330
- return node.ival.toString();
1331
- }
1332
- IntoClause(node, context = {}) {
1333
- return this.RangeVar(node.rel, context);
1334
- }
1335
- JoinExpr(node, context = {}) {
1336
- const output = [];
1337
- output.push(this.deparse(node.larg, context));
1338
- if (node.isNatural) {
1339
- output.push('NATURAL');
1340
- }
1341
- let join = null;
1342
- switch (true) {
1343
- case node.jointype === 'JOIN_INNER' && node.quals != null:
1344
- join = 'INNER JOIN';
1345
- break;
1346
- case node.jointype === 'JOIN_INNER' &&
1347
- !node.isNatural &&
1348
- !(node.quals != null) &&
1349
- !(node.usingClause != null):
1350
- join = 'CROSS JOIN';
1351
- break;
1352
- case node.jointype === 'JOIN_INNER':
1353
- join = 'JOIN';
1354
- break;
1355
- case node.jointype === 'JOIN_LEFT':
1356
- join = 'LEFT OUTER JOIN';
1357
- break;
1358
- case node.jointype === 'JOIN_FULL':
1359
- join = 'FULL OUTER JOIN';
1360
- break;
1361
- case node.jointype === 'JOIN_RIGHT':
1362
- join = 'RIGHT OUTER JOIN';
1363
- break;
1364
- default:
1365
- fail('JoinExpr', node);
1366
- break;
1367
- }
1368
- output.push(join);
1369
- if (node.rarg) {
1370
- // wrap nested join expressions in parens to make the following symmetric:
1371
- // select * from int8_tbl x cross join (int4_tbl x cross join lateral (select x.f1) ss)
1372
- if (node.rarg.JoinExpr != null && !(node.rarg.JoinExpr.alias != null)) {
1373
- output.push(`(${this.deparse(node.rarg, context)})`);
1374
- }
1375
- else {
1376
- output.push(this.deparse(node.rarg, context));
1377
- }
1378
- }
1379
- if (node.quals) {
1380
- output.push(`ON ${this.deparse(node.quals, context)}`);
1381
- }
1382
- if (node.usingClause) {
1383
- const using = this.quote(this.deparseNodes(node.usingClause, context)).join(', ');
1384
- output.push(`USING (${using})`);
1385
- }
1386
- const wrapped = node.rarg.JoinExpr != null || node.alias
1387
- ? '(' + output.join(' ') + ')'
1388
- : output.join(' ');
1389
- if (node.alias) {
1390
- return wrapped + ' ' + this.Alias(node.alias, context);
1391
- }
1392
- return wrapped;
1393
- }
1394
- LockingClause(node, context = {}) {
1395
- const output = [];
1396
- switch (node.strength) {
1397
- case 'LCS_NONE':
1398
- output.push('NONE');
1399
- break;
1400
- case 'LCS_FORKEYSHARE':
1401
- output.push('FOR KEY SHARE');
1402
- break;
1403
- case 'LCS_FORSHARE':
1404
- output.push('FOR SHARE');
1405
- break;
1406
- case 'LCS_FORNOKEYUPDATE':
1407
- output.push('FOR NO KEY UPDATE');
1408
- break;
1409
- case 'LCS_FORUPDATE':
1410
- output.push('FOR UPDATE');
1411
- break;
1412
- default:
1413
- return fail('LockingClause', node);
1414
- }
1415
- if (node.lockedRels) {
1416
- output.push('OF');
1417
- output.push(this.list(node.lockedRels, ', ', '', context));
1418
- }
1419
- return output.join(' ');
1420
- }
1421
- LockStmt(node, context = {}) {
1422
- const output = ['LOCK'];
1423
- output.push(this.list(node.relations, ', ', '', { lock: true }));
1424
- output.push('IN');
1425
- output.push(LOCK_MODES[node.mode]);
1426
- output.push('MODE');
1427
- if (node.nowait) {
1428
- output.push('NOWAIT');
1429
- }
1430
- return output.join(' ');
1431
- }
1432
- MinMaxExpr(node, context = {}) {
1433
- const output = [];
1434
- if (node.op === 'IS_GREATEST') {
1435
- output.push('GREATEST');
1436
- }
1437
- else {
1438
- output.push('LEAST');
1439
- }
1440
- output.push(parens(this.list(node.args, ', ', '', context)));
1441
- return output.join('');
1442
- }
1443
- NamedArgExpr(node, context = {}) {
1444
- const output = [];
1445
- output.push(node.name);
1446
- output.push(':=');
1447
- output.push(this.deparse(node.arg, context));
1448
- return output.join(' ');
1449
- }
1450
- Null(node) {
1451
- return 'NULL';
1452
- }
1453
- NullTest(node, context = {}) {
1454
- const output = [this.deparse(node.arg, context)];
1455
- if (node.nulltesttype === 'IS_NULL') {
1456
- output.push('IS NULL');
1457
- }
1458
- else if (node.nulltesttype === 'IS_NOT_NULL') {
1459
- output.push('IS NOT NULL');
1460
- }
1461
- return output.join(' ');
1462
- }
1463
- ParamRef(node) {
1464
- if (node.number >= 0) {
1465
- return ['$', node.number].join('');
1466
- }
1467
- return '?';
1468
- }
1469
- RangeFunction(node, context = {}) {
1470
- const output = [];
1471
- if (node.lateral) {
1472
- output.push('LATERAL');
1473
- }
1474
- const funcs = [];
1475
- const functions = unwrapList(node.functions);
1476
- for (let i = 0; i < functions.length; i++) {
1477
- const funcCall = unwrapList(functions[i]);
1478
- const call = [this.deparse(funcCall[0], context)];
1479
- const secondFuncCall = unwrapList(funcCall[1]);
1480
- if (secondFuncCall && secondFuncCall.length) {
1481
- call.push(format('AS (%s)', this.list(secondFuncCall, ', ', '', context)));
1482
- }
1483
- funcs.push(call.join(' '));
1484
- }
1485
- const calls = funcs.join(', ');
1486
- if (node.is_rowsfrom) {
1487
- output.push(`ROWS FROM (${calls})`);
1488
- }
1489
- else {
1490
- output.push(calls);
1491
- }
1492
- if (node.ordinality) {
1493
- output.push('WITH ORDINALITY');
1494
- }
1495
- if (node.alias) {
1496
- output.push(this.Alias(node.alias, context));
1497
- }
1498
- if (node.coldeflist) {
1499
- const defList = this.list(node.coldeflist, ', ', '', context);
1500
- if (!node.alias) {
1501
- output.push(` AS (${defList})`);
1502
- }
1503
- else {
1504
- output.push(`(${defList})`);
1505
- }
1506
- }
1507
- return output.join(' ');
1508
- }
1509
- RangeSubselect(node, context = {}) {
1510
- let output = '';
1511
- if (node.lateral) {
1512
- output += 'LATERAL ';
1513
- }
1514
- output += parens(this.deparse(node.subquery, context));
1515
- if (node.alias) {
1516
- return output + ' ' + this.Alias(node.alias, context);
1517
- }
1518
- return output;
1519
- }
1520
- RangeTableSample(node, context = {}) {
1521
- const output = [];
1522
- output.push(this.deparse(node.relation, context));
1523
- output.push('TABLESAMPLE');
1524
- output.push(this.deparse(unwrapList(node.method)[0], context));
1525
- if (node.args) {
1526
- output.push(parens(this.list(node.args, ', ', '', context)));
1527
- }
1528
- if (node.repeatable) {
1529
- output.push('REPEATABLE(' + this.deparse(node.repeatable, context) + ')');
1530
- }
1531
- return output.join(' ');
1532
- }
1533
- RangeVar(node, context = {}) {
1534
- const output = [];
1535
- if (node.inhOpt === 0) {
1536
- output.push('ONLY');
1537
- }
1538
- if (!node.inh && (context.lock || context === 'truncate')) {
1539
- output.push('ONLY');
1540
- }
1541
- if (node.relpersistence === 'u') {
1542
- output.push('UNLOGGED');
1543
- }
1544
- if (node.relpersistence === 't' && context !== 'view') {
1545
- output.push('TEMPORARY TABLE');
1546
- }
1547
- if (node.schemaname != null) {
1548
- output.push(`${this.quote(node.schemaname)}.${this.quote(node.relname)}`);
1549
- }
1550
- else {
1551
- output.push(this.quote(node.relname));
1552
- }
1553
- if (node.alias) {
1554
- output.push(this.Alias(node.alias, context));
1555
- }
1556
- return output.join(' ');
1557
- }
1558
- ResTarget(node, context = {}) {
1559
- if (context === 'select') {
1560
- return compact([
1561
- this.deparse(node.val, context),
1562
- this.quote(node.name)
1563
- ]).join(' AS ');
1564
- }
1565
- else if (context === 'update') {
1566
- return compact([node.name, this.deparse(node.val, context)]).join(' = ');
1567
- }
1568
- else if (!(node.val != null)) {
1569
- return this.quote(node.name);
1570
- }
1571
- return fail('ResTarget', node);
1572
- }
1573
- RowExpr(node, context = {}) {
1574
- if (node.row_format === 'COERCE_IMPLICIT_CAST') {
1575
- return parens(this.list(node.args, ', ', '', context));
1576
- }
1577
- return format('ROW(%s)', this.list(node.args, ', ', '', context));
1578
- }
1579
- ExplainStmt(node, context = {}) {
1580
- const output = [];
1581
- output.push('EXPLAIN');
1582
- if (node.options) {
1583
- output.push('(');
1584
- output.push(this.list(node.options, ', ', '', 'explain'));
1585
- output.push(')');
1586
- }
1587
- output.push(this.deparse(node.query, context));
1588
- return output.join(' ');
1589
- }
1590
- SelectStmt(node, context = {}) {
1591
- const output = [];
1592
- if (node.withClause) {
1593
- output.push(this.WithClause(node.withClause, context));
1594
- }
1595
- if (node.op === 'SETOP_NONE') {
1596
- // VALUES select's don't get SELECT
1597
- if (node.valuesLists == null) {
1598
- output.push('SELECT');
1599
- }
1600
- }
1601
- else {
1602
- output.push(parens(this.SelectStmt(node.larg, context)));
1603
- switch (node.op) {
1604
- case 'SETOP_NONE':
1605
- output.push('NONE');
1606
- break;
1607
- case 'SETOP_UNION':
1608
- output.push('UNION');
1609
- break;
1610
- case 'SETOP_INTERSECT':
1611
- output.push('INTERSECT');
1612
- break;
1613
- case 'SETOP_EXCEPT':
1614
- output.push('EXCEPT');
1615
- break;
1616
- default:
1617
- throw new Error('bad SelectStmt op');
1618
- }
1619
- if (node.all) {
1620
- output.push('ALL');
1621
- }
1622
- output.push(parens(this.SelectStmt(node.rarg, context)));
1623
- }
1624
- if (node.distinctClause) {
1625
- const distinctClause = unwrapList(node.distinctClause);
1626
- if (!isEmptyObject(distinctClause[0])
1627
- // new change distinctClause can be {}
1628
- ) {
1629
- output.push('DISTINCT ON');
1630
- const clause = distinctClause
1631
- .map((e) => this.deparse(e, 'select'))
1632
- .join(`,${NEWLINE_CHAR}`);
1633
- output.push(`(${clause})`);
1634
- }
1635
- else {
1636
- output.push('DISTINCT');
1637
- }
1638
- }
1639
- if (node.targetList) {
1640
- output.push(indent(unwrapList(node.targetList)
1641
- .map((e) => this.deparse(e, 'select'))
1642
- .join(`,${NEWLINE_CHAR}`)));
1643
- }
1644
- if (node.intoClause) {
1645
- output.push('INTO');
1646
- output.push(indent(this.IntoClause(node.intoClause, context)));
1647
- }
1648
- if (node.fromClause) {
1649
- output.push('FROM');
1650
- output.push(indent(unwrapList(node.fromClause)
1651
- .map((e) => this.deparse(e, 'from'))
1652
- .join(`,${NEWLINE_CHAR}`)));
1653
- }
1654
- if (node.whereClause) {
1655
- output.push('WHERE');
1656
- output.push(indent(this.deparse(node.whereClause, context)));
1657
- }
1658
- if (node.valuesLists) {
1659
- output.push('VALUES');
1660
- const lists = unwrapList(node.valuesLists).map((list) => {
1661
- return `(${this.list(list, ', ', '', context)})`;
1662
- });
1663
- output.push(lists.join(', '));
1664
- }
1665
- if (node.groupClause) {
1666
- output.push('GROUP BY');
1667
- output.push(indent(unwrapList(node.groupClause)
1668
- .map((e) => this.deparse(e, 'group'))
1669
- .join(`,${NEWLINE_CHAR}`)));
1670
- }
1671
- if (node.havingClause) {
1672
- output.push('HAVING');
1673
- output.push(indent(this.deparse(node.havingClause, context)));
1674
- }
1675
- if (node.windowClause) {
1676
- output.push('WINDOW');
1677
- const windows = [];
1678
- const windowClause = unwrapList(node.windowClause);
1679
- for (let i = 0; i < windowClause.length; i++) {
1680
- const w = windowClause[i];
1681
- const window = [];
1682
- if (w.WindowDef.name) {
1683
- window.push(this.quote(w.WindowDef.name) + ' AS');
1684
- }
1685
- window.push(parens(this.deparse(w, 'window')));
1686
- windows.push(window.join(' '));
1687
- }
1688
- output.push(windows.join(', '));
1689
- }
1690
- if (node.sortClause) {
1691
- output.push('ORDER BY');
1692
- output.push(indent(unwrapList(node.sortClause)
1693
- .map((e) => this.deparse(e, 'sort'))
1694
- .join(`,${NEWLINE_CHAR}`)));
1695
- }
1696
- if (node.limitCount) {
1697
- output.push('LIMIT');
1698
- output.push(indent(this.deparse(node.limitCount, context)));
1699
- }
1700
- if (node.limitOffset) {
1701
- output.push('OFFSET');
1702
- output.push(indent(this.deparse(node.limitOffset, context)));
1703
- }
1704
- if (node.lockingClause) {
1705
- node.lockingClause.forEach((item) => {
1706
- return output.push(this.deparse(item, context));
1707
- });
1708
- }
1709
- return output.join(' ');
1710
- }
1711
- TruncateStmt(node, context = {}) {
1712
- const output = ['TRUNCATE TABLE'];
1713
- output.push(this.list(node.relations, ', ', '', 'truncate'));
1714
- if (node.restart_seqs) {
1715
- output.push('RESTART IDENTITY');
1716
- }
1717
- if (node.behavior === 'DROP_CASCADE') {
1718
- output.push('CASCADE');
1719
- }
1720
- return output.join(' ');
1721
- }
1722
- AlterDefaultPrivilegesStmt(node, context = {}) {
1723
- const output = [];
1724
- output.push('ALTER DEFAULT PRIVILEGES');
1725
- const options = unwrapList(dotty.get(node, 'options'));
1726
- if (options) {
1727
- const elem = options.find((el) => el.hasOwnProperty('DefElem'));
1728
- const elemDefElemArg = unwrapList(elem.DefElem.arg);
1729
- if (elem.DefElem.defname === 'schemas') {
1730
- output.push('IN SCHEMA');
1731
- output.push(elemDefElemArg[0].String.str);
1732
- }
1733
- if (elem.DefElem.defname === 'roles') {
1734
- output.push('FOR ROLE');
1735
- const roleSpec = elemDefElemArg[0];
1736
- output.push(this.deparse(roleSpec, context));
1737
- }
1738
- output.push(NEWLINE_CHAR);
1739
- }
1740
- output.push(this.GrantStmt(node.action, context));
1741
- return output.join(' ');
1742
- }
1743
- AlterTableStmt(node, context = {}) {
1744
- const output = [];
1745
- const ctx = Object.assign({}, context);
1746
- output.push('ALTER');
1747
- if (node.relkind === 'OBJECT_TABLE') {
1748
- output.push('TABLE');
1749
- const inh = dotty.get(node, 'relation.inh');
1750
- if (!inh) {
1751
- output.push('ONLY');
1752
- }
1753
- }
1754
- else if (node.relkind === 'OBJECT_TYPE') {
1755
- output.push('TYPE');
1756
- }
1757
- else {
1758
- fail('AlterTableStmt', node);
1759
- }
1760
- if (node.missing_ok) {
1761
- output.push('IF EXISTS');
1762
- }
1763
- ctx.alterType = node.relkind;
1764
- output.push(this.RangeVar(node.relation, ctx));
1765
- output.push(this.list(node.cmds, ', ', '', ctx));
1766
- return output.join(' ');
1767
- }
1768
- AlterTableCmd(node, context = {}) {
1769
- const output = [];
1770
- let subType = 'COLUMN';
1771
- if (context && context.alterType === 'OBJECT_TYPE') {
1772
- subType = 'ATTRIBUTE';
1773
- }
1774
- if (node.subtype === 'AT_AddColumn') {
1775
- output.push('ADD');
1776
- output.push(subType);
1777
- if (node.missing_ok) {
1778
- output.push('IF NOT EXISTS');
1779
- }
1780
- output.push(this.quote(node.name));
1781
- output.push(this.deparse(node.def, context));
1782
- }
1783
- else if (node.subtype === 'AT_ColumnDefault') {
1784
- output.push('ALTER');
1785
- output.push(subType);
1786
- output.push(this.quote(node.name));
1787
- if (node.def) {
1788
- output.push('SET DEFAULT');
1789
- output.push(this.deparse(node.def, context));
1790
- }
1791
- else {
1792
- output.push('DROP DEFAULT');
1793
- }
1794
- }
1795
- else if (node.subtype === 'AT_DropNotNull') {
1796
- output.push('ALTER');
1797
- output.push(subType);
1798
- output.push(this.quote(node.name));
1799
- output.push('DROP NOT NULL');
1800
- }
1801
- else if (node.subtype === 'AT_SetNotNull') {
1802
- output.push('ALTER');
1803
- output.push(subType);
1804
- output.push(this.quote(node.name));
1805
- output.push('SET NOT NULL');
1806
- }
1807
- else if (node.subtype === 'AT_SetStatistics') {
1808
- output.push('ALTER');
1809
- output.push(this.quote(node.name));
1810
- output.push('SET STATISTICS');
1811
- output.push(dotty.get(node, 'def.Integer.ival'));
1812
- }
1813
- else if (node.subtype === 'AT_SetOptions') {
1814
- output.push('ALTER');
1815
- output.push(subType);
1816
- output.push(this.quote(node.name));
1817
- output.push('SET');
1818
- output.push('(');
1819
- output.push(this.list(node.def, ', ', '', context));
1820
- output.push(')');
1821
- }
1822
- else if (node.subtype === 'AT_SetStorage') {
1823
- output.push('ALTER');
1824
- output.push(this.quote(node.name));
1825
- output.push('SET STORAGE');
1826
- if (node.def) {
1827
- output.push(this.deparse(node.def, context));
1828
- }
1829
- else {
1830
- output.push('PLAIN');
1831
- }
1832
- }
1833
- else if (node.subtype === 'AT_DropColumn') {
1834
- output.push('DROP');
1835
- output.push(subType);
1836
- if (node.missing_ok) {
1837
- output.push('IF EXISTS');
1838
- }
1839
- output.push(this.quote(node.name));
1840
- }
1841
- else if (node.subtype === 'AT_AddConstraint') {
1842
- // output.push('ADD CONSTRAINT');
1843
- output.push('ADD');
1844
- output.push(this.deparse(node.def, context));
1845
- }
1846
- else if (node.subtype === 'AT_ValidateConstraint') {
1847
- output.push('VALIDATE CONSTRAINT');
1848
- output.push(this.quote(node.name, context));
1849
- }
1850
- else if (node.subtype === 'AT_DropConstraint') {
1851
- output.push('DROP CONSTRAINT');
1852
- if (node.missing_ok) {
1853
- output.push('IF EXISTS');
1854
- }
1855
- output.push(this.quote(node.name));
1856
- }
1857
- else if (node.subtype === 'AT_AlterColumnType') {
1858
- output.push('ALTER');
1859
- output.push(subType);
1860
- output.push(this.quote(node.name));
1861
- output.push('TYPE');
1862
- output.push(this.deparse(node.def, context));
1863
- }
1864
- else if (node.subtype === 'AT_ChangeOwner') {
1865
- output.push('OWNER');
1866
- output.push('TO');
1867
- output.push(this.RoleSpec(node.newowner, context));
1868
- }
1869
- else if (node.subtype === 'AT_ClusterOn') {
1870
- output.push('CLUSTER ON');
1871
- output.push(this.quote(node.name));
1872
- }
1873
- else if (node.subtype === 'AT_DropCluster') {
1874
- output.push('SET WITHOUT CLUSTER');
1875
- }
1876
- else if (node.subtype === 'AT_AddOids') {
1877
- output.push('SET WITH OIDS');
1878
- }
1879
- else if (node.subtype === 'AT_DropOids') {
1880
- output.push('SET WITHOUT OIDS');
1881
- }
1882
- else if (node.subtype === 'AT_SetRelOptions') {
1883
- output.push('SET');
1884
- output.push('(');
1885
- output.push(this.list(node.def, ', ', '', context));
1886
- output.push(')');
1887
- }
1888
- else if (node.subtype === 'AT_ResetRelOptions') {
1889
- output.push('RESET');
1890
- output.push('(');
1891
- output.push(this.list(node.def, ', ', '', context));
1892
- output.push(')');
1893
- }
1894
- else if (node.subtype === 'AT_AddIdentity') {
1895
- output.push('ALTER COLUMN');
1896
- output.push(this.quote(node.name));
1897
- output.push('ADD');
1898
- output.push(this.deparse(node.def, context));
1899
- }
1900
- else if (node.subtype === 'AT_AddInherit') {
1901
- output.push('INHERIT');
1902
- output.push(this.deparse(node.def, context));
1903
- }
1904
- else if (node.subtype === 'AT_DropInherit') {
1905
- output.push('NO INHERIT');
1906
- output.push(this.deparse(node.def, context));
1907
- }
1908
- else if (node.subtype === 'AT_AddOf') {
1909
- output.push('OF');
1910
- output.push(this.deparse(node.def, context));
1911
- }
1912
- else if (node.subtype === 'AT_DropOf') {
1913
- output.push('NOT OF');
1914
- //output.push(this.deparse(node.def));
1915
- }
1916
- else if (node.subtype === 'AT_EnableRowSecurity') {
1917
- output.push('ENABLE ROW LEVEL SECURITY');
1918
- }
1919
- else if (node.subtype === 'AT_DisableRowSecurity') {
1920
- output.push('DISABLE ROW LEVEL SECURITY');
1921
- }
1922
- else if (node.subtype === 'AT_ForceRowSecurity') {
1923
- output.push('FORCE ROW SECURITY');
1924
- }
1925
- else if (node.subtype === 'AT_NoForceRowSecurity') {
1926
- output.push('NO FORCE ROW SECURITY');
1927
- }
1928
- if (node.behavior === 'DROP_CASCADE') {
1929
- output.push('CASCADE');
1930
- }
1931
- return output.join(' ');
1932
- }
1933
- CreateEnumStmt(node, context = {}) {
1934
- const output = [];
1935
- output.push('CREATE TYPE');
1936
- output.push(this.list(node.typeName, '.', '', context));
1937
- output.push('AS ENUM');
1938
- output.push(`(${NEWLINE_CHAR}`);
1939
- const vals = unwrapList(node.vals).map((val) => {
1940
- return { String: { str: `'${val.String.str}'` } };
1941
- });
1942
- output.push(this.list(vals, `,${NEWLINE_CHAR}`, TAB_CHAR));
1943
- output.push(`${NEWLINE_CHAR})`);
1944
- return output.join(' ');
1945
- }
1946
- AlterEnumStmt(node, context = {}) {
1947
- const output = [];
1948
- output.push('ALTER TYPE');
1949
- const typObj = {
1950
- TypeName: {
1951
- names: node.typeName
1952
- }
1953
- };
1954
- output.push(this.deparse(typObj, context));
1955
- if (node.newVal) {
1956
- output.push('ADD VALUE');
1957
- const result = node.newVal.replace(/'/g, "''");
1958
- output.push(`'${result}'`);
1959
- }
1960
- if (node.newValNeighbor) {
1961
- if (node.newValIsAfter) {
1962
- output.push('AFTER');
1963
- }
1964
- else {
1965
- output.push('BEFORE');
1966
- }
1967
- const result = node.newValNeighbor.replace(/'/g, "''");
1968
- output.push(`'${result}'`);
1969
- }
1970
- if (node.behavior === 'DROP_CASCADE') {
1971
- output.push('CASCADE');
1972
- }
1973
- return output.join(' ');
1974
- }
1975
- AlterDomainStmt(node, context = {}) {
1976
- const output = [];
1977
- output.push('ALTER DOMAIN');
1978
- const typObj = {
1979
- TypeName: {
1980
- names: node.typeName
1981
- }
1982
- };
1983
- output.push(this.deparse(typObj, context));
1984
- if (node.subtype === 'C') {
1985
- output.push('ADD');
1986
- output.push(this.deparse(node.def, context));
1987
- }
1988
- else if (node.subtype === 'V') {
1989
- output.push('VALIDATE');
1990
- output.push('CONSTRAINT');
1991
- output.push(this.quote(node.name));
1992
- }
1993
- else if (node.subtype === 'X') {
1994
- output.push('DROP');
1995
- output.push('CONSTRAINT');
1996
- output.push(this.quote(node.name));
1997
- }
1998
- if (node.behavior === 'DROP_CASCADE') {
1999
- output.push('CASCADE');
2000
- }
2001
- return output.join(' ');
2002
- }
2003
- CreateExtensionStmt(node) {
2004
- const output = [];
2005
- output.push('CREATE EXTENSION');
2006
- if (node.if_not_exists) {
2007
- output.push('IF NOT EXISTS');
2008
- }
2009
- output.push(this.quote(node.extname));
2010
- if (node.options) {
2011
- node.options.forEach((opt) => {
2012
- if (opt.DefElem.defname === 'cascade' &&
2013
- opt.DefElem.arg.Integer.ival === 1) {
2014
- output.push('CASCADE');
2015
- }
2016
- if (opt.DefElem.defname === 'schema') {
2017
- output.push('WITH SCHEMA');
2018
- output.push(this.quote(this.deparse(opt.DefElem.arg)));
2019
- }
2020
- });
2021
- }
2022
- return output.join(' ');
2023
- }
2024
- DropStmt(node, context = {}) {
2025
- const output = [];
2026
- output.push('DROP');
2027
- output.push(objtypeName(node.removeType));
2028
- if (node.missing_ok) {
2029
- output.push('IF EXISTS');
2030
- }
2031
- const stmts = [];
2032
- const objects = unwrapList(node.objects);
2033
- for (let s = 0; s < objects.length; s++) {
2034
- const children = unwrapList(objects[s]);
2035
- const stmt = [];
2036
- if (node.removeType === 'OBJECT_TABLE' ||
2037
- node.removeType === 'OBJECT_CONVERSION' ||
2038
- node.removeType === 'OBJECT_COLLATION' ||
2039
- node.removeType === 'OBJECT_MATVIEW' ||
2040
- node.removeType === 'OBJECT_INDEX' ||
2041
- node.removeType === 'OBJECT_FOREIGN_TABLE') {
2042
- if (children.length === 1) {
2043
- stmt.push(this.quote(this.deparse(children[0])));
2044
- }
2045
- else if (children.length === 2) {
2046
- stmt.push(this.listQuotes(children, '.'));
2047
- }
2048
- else {
2049
- throw new Error('bad case 2 drop stmt' + JSON.stringify(node, null, 2));
2050
- }
2051
- }
2052
- else if (node.removeType === 'OBJECT_SCHEMA') {
2053
- stmt.push(this.quote(this.deparse(children)));
2054
- }
2055
- else if (node.removeType === 'OBJECT_SEQUENCE') {
2056
- stmt.push(this.listQuotes(children, '.'));
2057
- }
2058
- else if (node.removeType === 'OBJECT_POLICY') {
2059
- if (children.length === 2) {
2060
- stmt.push(this.quote(this.deparse(children[1], context)));
2061
- stmt.push('ON');
2062
- stmt.push(this.quote(this.deparse(children[0], context)));
2063
- }
2064
- else if (children.length === 3) {
2065
- stmt.push(this.quote(this.deparse(children[2], context)));
2066
- stmt.push('ON');
2067
- stmt.push(this.listQuotes([children[0], children[1]], '.'));
2068
- }
2069
- else {
2070
- throw new Error('bad drop policy stmt: ' + JSON.stringify(node, null, 2));
2071
- }
2072
- }
2073
- else if (node.removeType === 'OBJECT_TRIGGER') {
2074
- if (children.length === 2) {
2075
- stmt.push(this.quote(this.deparse(children[1], context)));
2076
- stmt.push('ON');
2077
- stmt.push(this.quote(this.deparse(children[0], context)));
2078
- }
2079
- else if (children.length === 3) {
2080
- stmt.push(this.quote(this.deparse(children[2], context)));
2081
- stmt.push('ON');
2082
- stmt.push(this.listQuotes([children[0], children[1]], '.'));
2083
- }
2084
- else {
2085
- throw new Error('bad drop trigger stmt: ' + JSON.stringify(node, null, 2));
2086
- }
2087
- }
2088
- else if (node.removeType === 'OBJECT_RULE') {
2089
- if (children.length === 2) {
2090
- stmt.push(this.quote(this.deparse(children[1], context)));
2091
- stmt.push('ON');
2092
- stmt.push(this.quote(this.deparse(children[0], context)));
2093
- }
2094
- else if (children.length === 3) {
2095
- stmt.push(this.quote(this.deparse(children[2], context)));
2096
- stmt.push('ON');
2097
- stmt.push(this.listQuotes([children[0], children[1]], '.'));
2098
- }
2099
- else {
2100
- throw new Error('bad drop rule stmt: ' + JSON.stringify(node, null, 2));
2101
- }
2102
- }
2103
- else if (node.removeType === 'OBJECT_VIEW') {
2104
- if (children.length === 1) {
2105
- stmt.push(this.quote(this.deparse(children[0], context)));
2106
- }
2107
- else if (children.length === 2) {
2108
- stmt.push(this.listQuotes(children, '.'));
2109
- }
2110
- else {
2111
- throw new Error('bad drop value stmt: ' + JSON.stringify(node, null, 2));
2112
- }
2113
- // } else if (node.removeType === 'OBJECT_OPERATOR') {
2114
- }
2115
- else if (node.removeType === 'OBJECT_CAST') {
2116
- stmt.push('(');
2117
- stmt.push(this.deparse(children[0], context));
2118
- stmt.push('AS');
2119
- stmt.push(this.deparse(children[1], context));
2120
- stmt.push(')');
2121
- // } else if (node.removeType === 'OBJECT_OPERATOR') {
2122
- // stmt.push(this.deparse(children, 'noquotes')); // in this case children is not an array
2123
- }
2124
- else if (node.removeType === 'OBJECT_AGGREGATE') {
2125
- stmt.push(this.deparse(children, context)); // in this case children is not an array
2126
- }
2127
- else if (node.removeType === 'OBJECT_FDW') {
2128
- stmt.push(this.deparse(children, context)); // in this case children is not an array
2129
- }
2130
- else if (node.removeType === 'OBJECT_FOREIGN_SERVER') {
2131
- stmt.push(this.deparse(children, context)); // in this case children is not an array
2132
- }
2133
- else if (node.removeType === 'OBJECT_EXTENSION') {
2134
- stmt.push(this.deparse(children, context)); // in this case children is not an array
2135
- }
2136
- else if (node.removeType === 'OBJECT_DOMAIN') {
2137
- stmt.push(this.deparse(children, context)); // in this case children is not an array
2138
- }
2139
- else if (node.removeType === 'OBJECT_FUNCTION') {
2140
- stmt.push(this.deparse(children, context)); // in this case children is not an array
2141
- }
2142
- else if (node.removeType === 'OBJECT_TYPE') {
2143
- stmt.push(this.deparse(children, context)); // in this case children is not an array
2144
- }
2145
- else {
2146
- throw new Error('bad drop stmt: ' + JSON.stringify(node, null, 2));
2147
- }
2148
- stmts.push(stmt.join(' '));
2149
- }
2150
- output.push(stmts.join(','));
2151
- if (node.behavior === 'DROP_CASCADE') {
2152
- output.push('CASCADE');
2153
- }
2154
- return output.join(' ');
2155
- }
2156
- CreatePolicyStmt(node, context = {}) {
2157
- const output = [];
2158
- output.push('CREATE POLICY');
2159
- output.push(this.quote(node.policy_name));
2160
- if (node.table) {
2161
- output.push('ON');
2162
- output.push(this.RangeVar(node.table, context));
2163
- }
2164
- if (node.permissive) {
2165
- // permissive is the default!
2166
- }
2167
- else {
2168
- output.push('AS');
2169
- output.push('RESTRICTIVE');
2170
- }
2171
- if (node.cmd_name) {
2172
- output.push('FOR');
2173
- output.push(node.cmd_name.toUpperCase());
2174
- }
2175
- output.push('TO');
2176
- output.push(this.list(node.roles));
2177
- if (node.qual) {
2178
- output.push('USING');
2179
- output.push('(');
2180
- output.push(this.deparse(node.qual, context));
2181
- output.push(')');
2182
- }
2183
- if (node.with_check) {
2184
- output.push('WITH CHECK');
2185
- output.push('(');
2186
- output.push(this.deparse(node.with_check, context));
2187
- output.push(')');
2188
- }
2189
- return output.join(' ');
2190
- }
2191
- AlterPolicyStmt(node, context = {}) {
2192
- const output = [];
2193
- output.push('ALTER POLICY');
2194
- output.push(this.quote(node.policy_name));
2195
- if (node.table) {
2196
- output.push('ON');
2197
- output.push(this.RangeVar(node.table, context));
2198
- }
2199
- output.push('TO');
2200
- output.push(this.list(node.roles));
2201
- if (node.qual) {
2202
- output.push('USING');
2203
- output.push('(');
2204
- output.push(this.deparse(node.qual, context));
2205
- output.push(')');
2206
- }
2207
- if (node.with_check) {
2208
- output.push('WITH CHECK');
2209
- output.push('(');
2210
- output.push(this.deparse(node.with_check, context));
2211
- output.push(')');
2212
- }
2213
- return output.join(' ');
2214
- }
2215
- ViewStmt(node, context = {}) {
2216
- const output = [];
2217
- output.push('CREATE');
2218
- if (node.replace)
2219
- output.push('OR REPLACE');
2220
- if (node.view.relpersistence === 't') {
2221
- output.push('TEMPORARY');
2222
- }
2223
- output.push('VIEW');
2224
- output.push(this.RangeVar(node.view, 'view'));
2225
- if (node.aliases) {
2226
- output.push('(');
2227
- output.push(this.list(node.aliases, ', ', '', context));
2228
- output.push(')');
2229
- }
2230
- output.push('AS');
2231
- output.push(this.deparse(node.query, context));
2232
- if (node.withCheckOption === 'LOCAL_CHECK_OPTION') {
2233
- output.push('WITH LOCAL CHECK OPTION');
2234
- }
2235
- else if (node.withCheckOption === 'CASCADED_CHECK_OPTION') {
2236
- output.push('WITH CASCADED CHECK OPTION');
2237
- }
2238
- return output.join(' ');
2239
- }
2240
- CreateSeqStmt(node, context = {}) {
2241
- const output = [];
2242
- output.push('CREATE SEQUENCE');
2243
- output.push(this.RangeVar(node.sequence, context));
2244
- const options = unwrapList(node.options);
2245
- if (options && options.length) {
2246
- options.forEach((opt) => {
2247
- output.push(this.deparse(opt, 'sequence'));
2248
- });
2249
- }
2250
- return output.join(' ');
2251
- }
2252
- AlterSeqStmt(node, context = {}) {
2253
- const output = [];
2254
- output.push('ALTER SEQUENCE');
2255
- output.push(this.RangeVar(node.sequence, context));
2256
- const options = unwrapList(node.options);
2257
- if (options && options.length) {
2258
- options.forEach((opt) => {
2259
- output.push(this.deparse(opt, 'sequence'));
2260
- });
2261
- }
2262
- return output.join(' ');
2263
- }
2264
- CreateTableAsStmt(node, context = {}) {
2265
- const output = ['CREATE'];
2266
- const relpersistence = dotty.get(node, 'into.rel.relpersistence');
2267
- if (node.relkind === 'OBJECT_MATVIEW') {
2268
- output.push('MATERIALIZED VIEW');
2269
- }
2270
- else if (relpersistence !== 't') {
2271
- output.push('TABLE');
2272
- if (node.if_not_exists) {
2273
- output.push('IF NOT EXISTS');
2274
- }
2275
- }
2276
- output.push(this.IntoClause(node.into, context));
2277
- output.push('AS');
2278
- output.push(this.deparse(node.query, context));
2279
- return output.join(' ');
2280
- }
2281
- CreateTrigStmt(node, context = {}) {
2282
- const output = [];
2283
- output.push('CREATE');
2284
- if (node.isconstraint) {
2285
- output.push('CONSTRAINT');
2286
- }
2287
- output.push('TRIGGER');
2288
- output.push(this.quote(node.trigname));
2289
- output.push(NEWLINE_CHAR);
2290
- // int16 timing; BEFORE, AFTER, or INSTEAD
2291
- if (node.timing === 64) {
2292
- output.push('INSTEAD OF');
2293
- }
2294
- else if (node.timing === 2) {
2295
- output.push('BEFORE');
2296
- }
2297
- else {
2298
- output.push('AFTER');
2299
- }
2300
- // int16 events; "OR" of INSERT/UPDATE/DELETE/TRUNCATE
2301
- // 4 = 0b000100 (insert)
2302
- // 8 = 0b001000 (delete)
2303
- // 16 = 0b010000 (update)
2304
- // 32 = 0b100000 (TRUNCATE)
2305
- const TRIGGER_EVENTS = {
2306
- INSERT: 4,
2307
- DELETE: 8,
2308
- UPDATE: 16,
2309
- TRUNCATE: 32
2310
- };
2311
- const events = [];
2312
- if ((TRIGGER_EVENTS.INSERT & node.events) === TRIGGER_EVENTS.INSERT) {
2313
- events.push('INSERT');
2314
- }
2315
- if ((TRIGGER_EVENTS.UPDATE & node.events) === TRIGGER_EVENTS.UPDATE) {
2316
- events.push('UPDATE');
2317
- }
2318
- if ((TRIGGER_EVENTS.DELETE & node.events) === TRIGGER_EVENTS.DELETE) {
2319
- events.push('DELETE');
2320
- }
2321
- if ((TRIGGER_EVENTS.TRUNCATE & node.events) === TRIGGER_EVENTS.TRUNCATE) {
2322
- events.push('TRUNCATE');
2323
- }
2324
- // events
2325
- output.push(events.join(' OR '));
2326
- // columns
2327
- if (node.columns) {
2328
- output.push('OF');
2329
- output.push(this.list(node.columns, ', ', '', context));
2330
- }
2331
- // ON
2332
- output.push('ON');
2333
- output.push(this.RangeVar(node.relation, context));
2334
- output.push(NEWLINE_CHAR);
2335
- if (node.transitionRels) {
2336
- output.push('REFERENCING');
2337
- node.transitionRels.forEach(({ TriggerTransition }) => {
2338
- if (TriggerTransition.isNew === true &&
2339
- TriggerTransition.isTable === true) {
2340
- output.push(`NEW TABLE AS ${TriggerTransition.name}`);
2341
- }
2342
- else if (TriggerTransition.isNew !== true &&
2343
- TriggerTransition.isTable === true) {
2344
- output.push(`OLD TABLE AS ${TriggerTransition.name}`);
2345
- }
2346
- });
2347
- }
2348
- // opts
2349
- if (node.deferrable || node.initdeferred) {
2350
- if (node.deferrable) {
2351
- output.push('DEFERRABLE');
2352
- }
2353
- if (node.deferrable) {
2354
- output.push('INITIALLY DEFERRED');
2355
- }
2356
- output.push(NEWLINE_CHAR);
2357
- }
2358
- if (node.row) {
2359
- output.push(`FOR EACH ROW${NEWLINE_CHAR}`);
2360
- }
2361
- else {
2362
- output.push(`FOR EACH STATEMENT${NEWLINE_CHAR}`);
2363
- }
2364
- if (node.whenClause) {
2365
- output.push('WHEN');
2366
- output.push('(');
2367
- output.push(this.deparse(node.whenClause, 'trigger'));
2368
- output.push(')');
2369
- output.push(NEWLINE_CHAR);
2370
- }
2371
- output.push('EXECUTE PROCEDURE');
2372
- output.push(this.listQuotes(node.funcname).split(',').join('.'));
2373
- output.push('(');
2374
- let args = [];
2375
- if (node.args) {
2376
- args = unwrapList(node.args);
2377
- }
2378
- // seems that it's only parsing strings?
2379
- args = args
2380
- .map((arg) => {
2381
- if (arg.String !== undefined && arg.String.str !== undefined) {
2382
- return `'${arg.String.str}'`;
2383
- }
2384
- return this.deparse(arg, context);
2385
- })
2386
- .filter((a) => a);
2387
- output.push(args.join(','));
2388
- output.push(')');
2389
- return output.join(' ');
2390
- }
2391
- CreateDomainStmt(node, context = {}) {
2392
- const output = [];
2393
- output.push('CREATE DOMAIN');
2394
- output.push(this.list(node.domainname, '.', '', context));
2395
- output.push('AS');
2396
- output.push(this.TypeName(node.typeName, context));
2397
- if (node.constraints) {
2398
- output.push(this.list(node.constraints, ', ', '', context));
2399
- }
2400
- return output.join(' ');
2401
- }
2402
- CreateStmt(node, context = {}) {
2403
- const output = [];
2404
- const relpersistence = dotty.get(node, 'relation.relpersistence');
2405
- if (relpersistence === 't') {
2406
- output.push('CREATE');
2407
- }
2408
- else {
2409
- output.push('CREATE TABLE');
2410
- if (node.if_not_exists) {
2411
- output.push('IF NOT EXISTS');
2412
- }
2413
- }
2414
- output.push(this.RangeVar(node.relation, context));
2415
- output.push(`(${NEWLINE_CHAR}`);
2416
- output.push(this.list(node.tableElts, `,${NEWLINE_CHAR}`, TAB_CHAR, context));
2417
- output.push(`${NEWLINE_CHAR})`);
2418
- if (node.hasOwnProperty('inhRelations')) {
2419
- output.push('INHERITS');
2420
- output.push('(');
2421
- output.push(this.list(node.inhRelations, ', ', '', context));
2422
- output.push(')');
2423
- }
2424
- if (node.options) {
2425
- // TODO was this deprecated?
2426
- node.options.forEach((opt) => {
2427
- if (dotty.get(opt, 'DefElem.defname') === 'oids') {
2428
- if (Number(dotty.get(opt, 'DefElem.arg.Integer.ival')) === 1) {
2429
- output.push('WITH OIDS');
2430
- }
2431
- else {
2432
- output.push('WITHOUT OIDS');
2433
- }
2434
- }
2435
- });
2436
- }
2437
- return output.join(' ');
2438
- }
2439
- ConstraintStmt(node) {
2440
- const output = [];
2441
- const constraint = getConstraintFromConstrType(node.contype);
2442
- if (node.conname) {
2443
- output.push('CONSTRAINT');
2444
- output.push(node.conname);
2445
- if (!node.pktable) {
2446
- output.push(constraint);
2447
- }
2448
- }
2449
- else if (node.contype === 'CONSTR_IDENTITY') {
2450
- // IDENTITY
2451
- output.push('GENERATED');
2452
- if (node.generated_when == 'a') {
2453
- output.push('ALWAYS AS');
2454
- }
2455
- else {
2456
- output.push('BY DEFAULT AS');
2457
- }
2458
- output.push('IDENTITY');
2459
- const options = unwrapList(node.options);
2460
- if (options && options.length) {
2461
- output.push('(');
2462
- output.push(this.list(options, ' ', '', 'generated'));
2463
- output.push(')');
2464
- }
2465
- }
2466
- else if (node.contype === 'CONSTR_GENERATED') {
2467
- output.push('GENERATED');
2468
- if (node.generated_when == 'a') {
2469
- output.push('ALWAYS AS');
2470
- }
2471
- }
2472
- else {
2473
- output.push(constraint);
2474
- }
2475
- return output.join(' ');
2476
- }
2477
- ReferenceConstraint(node, context = {}) {
2478
- const output = [];
2479
- if (node.pk_attrs && node.fk_attrs) {
2480
- if (node.conname) {
2481
- output.push('CONSTRAINT');
2482
- output.push(node.conname);
2483
- }
2484
- output.push('FOREIGN KEY');
2485
- output.push('(');
2486
- output.push(this.listQuotes(node.fk_attrs));
2487
- output.push(')');
2488
- output.push('REFERENCES');
2489
- output.push(this.RangeVar(node.pktable, context));
2490
- output.push('(');
2491
- output.push(this.listQuotes(node.pk_attrs));
2492
- output.push(')');
2493
- }
2494
- else if (node.pk_attrs) {
2495
- output.push(this.ConstraintStmt(node, context));
2496
- output.push(this.RangeVar(node.pktable, context));
2497
- output.push('(');
2498
- output.push(this.listQuotes(node.pk_attrs));
2499
- output.push(')');
2500
- }
2501
- else if (node.fk_attrs) {
2502
- if (node.conname) {
2503
- output.push('CONSTRAINT');
2504
- output.push(node.conname);
2505
- }
2506
- output.push('FOREIGN KEY');
2507
- output.push('(');
2508
- output.push(this.listQuotes(node.fk_attrs));
2509
- output.push(')');
2510
- output.push('REFERENCES');
2511
- output.push(this.RangeVar(node.pktable, context));
2512
- }
2513
- else {
2514
- output.push(this.ConstraintStmt(node, context));
2515
- output.push(this.RangeVar(node.pktable, context));
2516
- }
2517
- return output.join(' ');
2518
- }
2519
- ExclusionConstraint(node, context = {}) {
2520
- const output = [];
2521
- function getExclusionGroup(nde) {
2522
- const exclusions = unwrapList(nde.exclusions);
2523
- const a = exclusions.map((excl) => {
2524
- const firstExcl = unwrapList(excl)[0];
2525
- if (firstExcl.IndexElem.name) {
2526
- return firstExcl.IndexElem.name;
2527
- }
2528
- return firstExcl.IndexElem.expr
2529
- ? this.deparse(firstExcl.IndexElem.expr, context)
2530
- : null;
2531
- });
2532
- const b = exclusions.map((excl) => this.deparse(unwrapList(unwrapList(excl)[1])[0], context));
2533
- const stmts = a.map((_v, i) => `${a[i]} WITH ${b[i]}`);
2534
- return stmts.join(', ');
2535
- }
2536
- if (node.exclusions && node.access_method) {
2537
- output.push('USING');
2538
- output.push(node.access_method);
2539
- output.push('(');
2540
- output.push(getExclusionGroup.call(this, node));
2541
- output.push(')');
2542
- }
2543
- return output.join(' ');
2544
- }
2545
- Constraint(node, context = {}) {
2546
- const output = [];
2547
- if (node.contype === 'CONSTR_FOREIGN') {
2548
- output.push(this.ReferenceConstraint(node, context));
2549
- }
2550
- else {
2551
- output.push(this.ConstraintStmt(node, context));
2552
- }
2553
- if (node.keys) {
2554
- output.push('(');
2555
- output.push(this.listQuotes(node.keys));
2556
- output.push(')');
2557
- }
2558
- if (node.raw_expr) {
2559
- output.push('(');
2560
- output.push(this.deparse(node.raw_expr, context));
2561
- output.push(')');
2562
- if (node.contype == 'CONSTR_GENERATED') {
2563
- output.push('STORED');
2564
- }
2565
- }
2566
- if (node.fk_del_action) {
2567
- switch (node.fk_del_action) {
2568
- case 'r':
2569
- output.push('ON DELETE RESTRICT');
2570
- break;
2571
- case 'c':
2572
- output.push('ON DELETE CASCADE');
2573
- break;
2574
- case 'n':
2575
- output.push('ON DELETE SET NULL');
2576
- break;
2577
- case 'd':
2578
- output.push('ON DELETE SET DEFAULT');
2579
- break;
2580
- case 'a':
2581
- // output.push('ON DELETE NO ACTION');
2582
- break;
2583
- default:
2584
- }
2585
- }
2586
- if (node.fk_upd_action) {
2587
- switch (node.fk_upd_action) {
2588
- case 'r':
2589
- output.push('ON UPDATE RESTRICT');
2590
- break;
2591
- case 'c':
2592
- output.push('ON UPDATE CASCADE');
2593
- break;
2594
- case 'n':
2595
- output.push('ON UPDATE SET NULL');
2596
- break;
2597
- case 'd':
2598
- output.push('ON UPDATE SET DEFAULT');
2599
- break;
2600
- case 'a':
2601
- // output.push('ON UPDATE NO ACTION');
2602
- break;
2603
- default:
2604
- }
2605
- }
2606
- if (node.fk_matchtype === 'f') {
2607
- output.push('MATCH FULL');
2608
- }
2609
- if (node.is_no_inherit === true) {
2610
- output.push('NO INHERIT');
2611
- }
2612
- if (node.skip_validation === true) {
2613
- output.push('NOT VALID');
2614
- }
2615
- if (node.contype === 'CONSTR_EXCLUSION') {
2616
- output.push(this.ExclusionConstraint(node, context));
2617
- }
2618
- if (node.deferrable) {
2619
- output.push('deferrable');
2620
- }
2621
- return output.join(' ');
2622
- }
2623
- AccessPriv(node) {
2624
- const output = [];
2625
- if (node.priv_name) {
2626
- output.push(node.priv_name.toUpperCase());
2627
- }
2628
- else {
2629
- output.push('ALL');
2630
- }
2631
- if (node.cols) {
2632
- output.push('(');
2633
- output.push(this.listQuotes(node.cols));
2634
- output.push(')');
2635
- }
2636
- return output.join(' ');
2637
- }
2638
- VariableSetStmt(node) {
2639
- switch (node.kind) {
2640
- case 'VAR_SET_VALUE':
2641
- return format('SET %s%s = %s', node.is_local ? 'LOCAL ' : '', node.name, this.deparseNodes(node.args, 'simple').join(', '));
2642
- case 'VAR_SET_DEFAULT':
2643
- return format('SET %s TO DEFAULT', node.name);
2644
- case 'VAR_SET_CURRENT':
2645
- return format('SET %s FROM CURRENT', node.name);
2646
- case 'VAR_SET_MULTI': {
2647
- const name = {
2648
- TRANSACTION: 'TRANSACTION',
2649
- 'SESSION CHARACTERISTICS': 'SESSION CHARACTERISTICS AS TRANSACTION'
2650
- }[node.name];
2651
- return format('SET %s %s', name, this.deparseNodes(node.args, 'simple').join(', '));
2652
- }
2653
- case 'VAR_RESET':
2654
- return format('RESET %s', node.name);
2655
- case 'VAR_RESET_ALL':
2656
- return 'RESET ALL';
2657
- default:
2658
- return fail('VariableSetKind', node);
2659
- }
2660
- }
2661
- VariableShowStmt(node) {
2662
- return format('SHOW %s', node.name);
2663
- }
2664
- FuncWithArgs(node, context = {}) {
2665
- const output = [];
2666
- output.push(this.deparse(unwrapList(node.funcname)[0], context));
2667
- output.push('(');
2668
- output.push(this.list(node.funcargs, ', ', '', context));
2669
- output.push(')');
2670
- return output.join(' ');
2671
- }
2672
- FunctionParameter(node, context = {}) {
2673
- const output = [];
2674
- if (node.mode === 'FUNC_PARAM_VARIADIC') {
2675
- output.push('VARIADIC');
2676
- }
2677
- if (node.mode === 'FUNC_PARAM_OUT') {
2678
- output.push('OUT');
2679
- }
2680
- if (node.mode === 'FUNC_PARAM_INOUT') {
2681
- output.push('INOUT');
2682
- }
2683
- output.push(node.name);
2684
- output.push(this.TypeName(node.argType, context));
2685
- if (node.defexpr) {
2686
- output.push('DEFAULT');
2687
- output.push(this.deparse(node.defexpr, context));
2688
- }
2689
- return output.join(' ');
2690
- }
2691
- CreateFunctionStmt(node, context = {}) {
2692
- const output = [];
2693
- output.push('CREATE');
2694
- if (node.replace) {
2695
- output.push('OR REPLACE');
2696
- }
2697
- output.push('FUNCTION');
2698
- output.push(unwrapList(node.funcname)
2699
- .map((name) => this.deparse(name, context))
2700
- .join('.'));
2701
- output.push('(');
2702
- let parameters = [];
2703
- if (node.parameters) {
2704
- parameters = unwrapList(node.parameters);
2705
- }
2706
- const parametersList = parameters.filter(({ FunctionParameter }) => FunctionParameter.mode === 'FUNC_PARAM_VARIADIC' ||
2707
- FunctionParameter.mode === 'FUNC_PARAM_OUT' ||
2708
- FunctionParameter.mode === 'FUNC_PARAM_INOUT' ||
2709
- FunctionParameter.mode === 'FUNC_PARAM_IN');
2710
- output.push(this.list(parametersList));
2711
- output.push(')');
2712
- const returns = parameters.filter(({ FunctionParameter }) => FunctionParameter.mode === 'FUNC_PARAM_TABLE');
2713
- if (returns.length > 0) {
2714
- output.push('RETURNS');
2715
- output.push('TABLE');
2716
- output.push('(');
2717
- output.push(this.list(returns, ', ', '', context));
2718
- output.push(')');
2719
- }
2720
- else if (node.returnType) {
2721
- output.push('RETURNS');
2722
- output.push(this.TypeName(node.returnType, context));
2723
- }
2724
- node.options.forEach((option, i) => {
2725
- if (option && option.DefElem) {
2726
- let value = '';
2727
- switch (option.DefElem.defname) {
2728
- case 'as':
2729
- value = this.deparse(unwrapList(option.DefElem.arg)[0], context);
2730
- output.push(`AS $EOFCODE$${value}$EOFCODE$`);
2731
- break;
2732
- case 'language':
2733
- value = this.deparse(option.DefElem.arg, context);
2734
- output.push('LANGUAGE');
2735
- output.push(value);
2736
- break;
2737
- case 'security':
2738
- output.push('SECURITY');
2739
- value = Number(option.DefElem.arg.Integer.ival);
2740
- if (value > 0) {
2741
- output.push('DEFINER');
2742
- }
2743
- else {
2744
- output.push('INVOKER');
2745
- }
2746
- break;
2747
- case 'leakproof':
2748
- value = Number(option.DefElem.arg.Integer.ival);
2749
- if (value > 0) {
2750
- output.push('LEAKPROOF');
2751
- }
2752
- break;
2753
- case 'window':
2754
- value = Number(option.DefElem.arg.Integer.ival);
2755
- if (value > 0) {
2756
- output.push('WINDOW');
2757
- }
2758
- break;
2759
- case 'strict':
2760
- value = Number(option.DefElem.arg.Integer.ival);
2761
- if (value > 0) {
2762
- output.push('STRICT');
2763
- }
2764
- else {
2765
- output.push('CALLED ON NULL INPUT');
2766
- }
2767
- break;
2768
- case 'set':
2769
- output.push(this.deparse(option, context));
2770
- break;
2771
- case 'volatility':
2772
- value = this.deparse(option.DefElem.arg, context);
2773
- output.push(value.toUpperCase());
2774
- break;
2775
- default:
2776
- }
2777
- }
2778
- });
2779
- return output.join(' ');
2780
- }
2781
- CreateSchemaStmt(node) {
2782
- const output = [];
2783
- output.push('CREATE');
2784
- if (node.replace) {
2785
- output.push('OR REPLACE');
2786
- }
2787
- output.push('SCHEMA');
2788
- if (node.if_not_exists) {
2789
- output.push('IF NOT EXISTS');
2790
- }
2791
- output.push(node.schemaname);
2792
- return output.join(' ');
2793
- }
2794
- RoleSpec(node) {
2795
- switch (node.roletype) {
2796
- case 'ROLESPEC_CSTRING':
2797
- return this.quote(node.rolename);
2798
- case 'ROLESPEC_CURRENT_USER':
2799
- return 'CURRENT_USER';
2800
- case 'ROLESPEC_SESSION_USER':
2801
- return 'SESSION_USER';
2802
- case 'ROLESPEC_PUBLIC':
2803
- return 'PUBLIC';
2804
- default:
2805
- return fail('RoleSpec', node);
2806
- }
2807
- }
2808
- GrantStmt(node) {
2809
- const output = [];
2810
- const getTypeFromNode = (nodeObj) => {
2811
- switch (nodeObj.objtype) {
2812
- case 'OBJECT_TABLE':
2813
- if (nodeObj.targtype === 'ACL_TARGET_ALL_IN_SCHEMA') {
2814
- return 'ALL TABLES IN SCHEMA';
2815
- }
2816
- if (nodeObj.targtype === 'ACL_TARGET_DEFAULTS') {
2817
- return 'TABLES';
2818
- }
2819
- // todo could be view
2820
- return 'TABLE';
2821
- case 'OBJECT_SEQUENCE':
2822
- if (nodeObj.targtype === 'ACL_TARGET_ALL_IN_SCHEMA') {
2823
- return 'ALL SEQUENCES IN SCHEMA';
2824
- }
2825
- if (nodeObj.targtype === 'ACL_TARGET_DEFAULTS') {
2826
- return 'SEQUENCES';
2827
- }
2828
- return 'SEQUENCE';
2829
- case 'OBJECT_DATABASE':
2830
- return 'DATABASE';
2831
- case 'OBJECT_DOMAIN':
2832
- return 'DOMAIN';
2833
- case 'OBJECT_FDW':
2834
- return 'FOREIGN DATA WRAPPER';
2835
- case 'OBJECT_FOREIGN_SERVER':
2836
- return 'FOREIGN SERVER';
2837
- case 'OBJECT_FUNCTION':
2838
- if (nodeObj.targtype === 'ACL_TARGET_ALL_IN_SCHEMA') {
2839
- return 'ALL FUNCTIONS IN SCHEMA';
2840
- }
2841
- if (nodeObj.targtype === 'ACL_TARGET_DEFAULTS') {
2842
- return 'FUNCTIONS';
2843
- }
2844
- return 'FUNCTION';
2845
- case 'OBJECT_LANGUAGE':
2846
- return 'LANGUAGE';
2847
- case 'OBJECT_LARGEOBJECT':
2848
- return 'LARGE OBJECT';
2849
- case 'OBJECT_SCHEMA':
2850
- return 'SCHEMA';
2851
- case 'OBJECT_TABLESPACE':
2852
- return 'TABLESPACE';
2853
- case 'OBJECT_TYPE':
2854
- return 'TYPE';
2855
- default:
2856
- }
2857
- return fail('GrantStmt', node);
2858
- };
2859
- if (node.objtype !== 'OBJECT_COLUMN') {
2860
- if (!node.is_grant) {
2861
- output.push('REVOKE');
2862
- if (node.grant_option) {
2863
- output.push('GRANT OPTION');
2864
- output.push('FOR');
2865
- }
2866
- if (node.privileges) {
2867
- output.push(this.list(node.privileges));
2868
- }
2869
- else {
2870
- output.push('ALL');
2871
- }
2872
- output.push('ON');
2873
- output.push(getTypeFromNode(node));
2874
- output.push(this.list(node.objects));
2875
- output.push('FROM');
2876
- output.push(this.list(node.grantees));
2877
- }
2878
- else {
2879
- output.push('GRANT');
2880
- if (node.privileges) {
2881
- output.push(this.list(node.privileges));
2882
- }
2883
- else {
2884
- output.push('ALL');
2885
- }
2886
- output.push('ON');
2887
- output.push(getTypeFromNode(node));
2888
- output.push(this.list(node.objects));
2889
- output.push('TO');
2890
- output.push(this.list(node.grantees));
2891
- if (node.grant_option) {
2892
- output.push('WITH GRANT OPTION');
2893
- }
2894
- }
2895
- if (node.behavior === 'DROP_CASCADE') {
2896
- output.push('CASCADE');
2897
- }
2898
- }
2899
- return output.join(' ');
2900
- }
2901
- GrantRoleStmt(node, context = {}) {
2902
- const output = [];
2903
- if (!node.is_grant) {
2904
- output.push('REVOKE');
2905
- output.push(this.list(node.granted_roles, ', ', '', context));
2906
- output.push('FROM');
2907
- output.push(this.list(node.grantee_roles, ', ', '', context));
2908
- }
2909
- else {
2910
- output.push('GRANT');
2911
- output.push(this.list(node.granted_roles, ', ', '', context));
2912
- output.push('TO');
2913
- output.push(this.list(node.grantee_roles, ', ', '', context));
2914
- }
2915
- if (node.admin_opt) {
2916
- output.push('WITH ADMIN OPTION');
2917
- }
2918
- return output.join(' ');
2919
- }
2920
- CreateRoleStmt(node, context = {}) {
2921
- const output = [];
2922
- const roleOption = (nodeObj, i, val1, val2) => {
2923
- const val = Number(dotty.get(unwrapList(nodeObj.options), `${i}.DefElem.arg.Integer.ival`));
2924
- if (val > 0) {
2925
- output.push(val1);
2926
- }
2927
- else {
2928
- output.push(val2);
2929
- }
2930
- };
2931
- output.push('CREATE');
2932
- switch (node.stmt_type) {
2933
- case 'ROLESTMT_USER':
2934
- output.push('USER');
2935
- break;
2936
- case 'ROLESTMT_GROUP':
2937
- output.push('GROUP');
2938
- break;
2939
- default:
2940
- output.push('ROLE');
2941
- }
2942
- output.push(`"${node.role}"`);
2943
- if (node.options) {
2944
- const options = unwrapList(node.options);
2945
- const opts = dotty.search(options, '*.DefElem.defname');
2946
- if (opts.length === 1 && opts[0] === 'addroleto') {
2947
- // only one case
2948
- }
2949
- else {
2950
- output.push('WITH');
2951
- }
2952
- opts.forEach((option, i) => {
2953
- let value = '';
2954
- switch (option) {
2955
- case 'canlogin':
2956
- roleOption(node, i, 'LOGIN', 'NOLOGIN');
2957
- break;
2958
- case 'addroleto':
2959
- output.push('IN ROLE');
2960
- output.push(dotty
2961
- .search(flatten(dotty.search(options, `${i}.DefElem.arg`).map(unwrapList)), '*.RoleSpec.rolename')
2962
- .join(','));
2963
- break;
2964
- case 'password':
2965
- output.push('PASSWORD');
2966
- value = dotty.get(options, `${i}.DefElem.arg.String.str`);
2967
- output.push(`'${value}'`);
2968
- break;
2969
- case 'adminmembers':
2970
- output.push('ADMIN');
2971
- output.push(this.list(options[i].DefElem.arg, ', ', '', context));
2972
- break;
2973
- case 'rolemembers':
2974
- output.push('USER');
2975
- output.push(this.list(options[i].DefElem.arg, ', ', '', context));
2976
- break;
2977
- case 'createdb':
2978
- roleOption(node, i, 'CREATEDB', 'NOCREATEDB');
2979
- break;
2980
- case 'isreplication':
2981
- roleOption(node, i, 'REPLICATION', 'NOREPLICATION');
2982
- break;
2983
- case 'bypassrls':
2984
- roleOption(node, i, 'BYPASSRLS', 'NOBYPASSRLS');
2985
- break;
2986
- case 'inherit':
2987
- roleOption(node, i, 'INHERIT', 'NOINHERIT');
2988
- break;
2989
- case 'superuser':
2990
- roleOption(node, i, 'SUPERUSER', 'NOSUPERUSER');
2991
- break;
2992
- case 'createrole':
2993
- roleOption(node, i, 'CREATEROLE', 'NOCREATEROLE');
2994
- break;
2995
- case 'validUntil':
2996
- output.push('VALID UNTIL');
2997
- value = dotty.get(options[i], `DefElem.arg.String.str`);
2998
- output.push(`'${value}'`);
2999
- break;
3000
- default:
3001
- }
3002
- });
3003
- }
3004
- return output.join(' ');
3005
- }
3006
- TransactionStmt(node, context = {}) {
3007
- const output = [];
3008
- const begin = (nodeOpts) => {
3009
- const options = unwrapList(nodeOpts.options);
3010
- const opts = options ? dotty.search(options, '*.DefElem.defname') : [];
3011
- if (opts.includes('transaction_read_only')) {
3012
- const index = opts.indexOf('transaction_read_only');
3013
- const obj = options[index];
3014
- let set = false;
3015
- const flag = Number(this.deparse(dotty.get(obj, 'DefElem.arg'), context));
3016
- if (flag > 0) {
3017
- set = true;
3018
- }
3019
- if (set) {
3020
- return 'BEGIN TRANSACTION READ ONLY';
3021
- }
3022
- return 'BEGIN TRANSACTION READ WRITE';
3023
- }
3024
- if (opts.includes('transaction_isolation')) {
3025
- const index = opts.indexOf('transaction_isolation');
3026
- const obj = options[index];
3027
- const lopts = this.deparse(dotty.get(obj, 'DefElem.arg'), context).replace(/['"]+/g, '');
3028
- return `BEGIN TRANSACTION ISOLATION LEVEL ${lopts.toUpperCase()}`;
3029
- }
3030
- return 'BEGIN';
3031
- };
3032
- const start = (nodeOpts) => {
3033
- const options = unwrapList(nodeOpts.options);
3034
- const opts = options ? dotty.search(options, '*.DefElem.defname') : [];
3035
- if (opts.includes('transaction_read_only')) {
3036
- const index = opts.indexOf('transaction_read_only');
3037
- const obj = options[index];
3038
- let set = false;
3039
- const flag = Number(this.deparse(dotty.get(obj, 'DefElem.arg'), context));
3040
- if (flag > 0) {
3041
- set = true;
3042
- }
3043
- if (set) {
3044
- return 'START TRANSACTION READ ONLY';
3045
- }
3046
- return 'START TRANSACTION READ WRITE';
3047
- }
3048
- return 'START TRANSACTION';
3049
- };
3050
- const nodeOptions = unwrapList(node.options);
3051
- switch (node.kind) {
3052
- case 'TRANS_STMT_BEGIN':
3053
- return begin(node);
3054
- case 'TRANS_STMT_START':
3055
- return start(node);
3056
- case 'TRANS_STMT_COMMIT':
3057
- return 'COMMIT';
3058
- case 'TRANS_STMT_ROLLBACK':
3059
- return 'ROLLBACK';
3060
- case 'TRANS_STMT_SAVEPOINT':
3061
- output.push('SAVEPOINT');
3062
- output.push(this.deparse(nodeOptions[0].DefElem.arg, context));
3063
- break;
3064
- case 'TRANS_STMT_RELEASE':
3065
- output.push('RELEASE SAVEPOINT');
3066
- output.push(this.deparse(nodeOptions[0].DefElem.arg, context));
3067
- break;
3068
- case 'TRANS_STMT_ROLLBACK_TO':
3069
- output.push('ROLLBACK TO');
3070
- output.push(this.deparse(nodeOptions[0].DefElem.arg, context));
3071
- break;
3072
- case 'TRANS_STMT_PREPARE':
3073
- output.push('PREPARE TRANSACTION');
3074
- output.push(`'${node.gid}'`);
3075
- break;
3076
- case 'TRANS_STMT_COMMIT_PREPARED':
3077
- output.push('COMMIT PREPARED');
3078
- output.push(`'${node.gid}'`);
3079
- break;
3080
- case 'TRANS_STMT_ROLLBACK_PREPARED':
3081
- output.push('ROLLBACK PREPARED');
3082
- output.push(`'${node.gid}'`);
3083
- break;
3084
- default:
3085
- }
3086
- return output.join(' ');
3087
- }
3088
- SortBy(node, context = {}) {
3089
- const output = [];
3090
- output.push(this.deparse(node.node, context));
3091
- switch (node.sortby_dir) {
3092
- case 'SORTBY_ASC':
3093
- output.push('ASC');
3094
- break;
3095
- case 'SORTBY_DESC':
3096
- output.push('DESC');
3097
- break;
3098
- case 'SORTBY_USING':
3099
- output.push(`USING ${this.deparseNodes(node.useOp, context)}`);
3100
- break;
3101
- case 'SORTBY_DEFAULT':
3102
- break;
3103
- default:
3104
- return fail('SortBy', node);
3105
- }
3106
- if (node.sortby_nulls === 'SORTBY_NULLS_FIRST') {
3107
- output.push('NULLS FIRST');
3108
- }
3109
- if (node.sortby_nulls === 'SORTBY_NULLS_LAST') {
3110
- output.push('NULLS LAST');
3111
- }
3112
- return output.join(' ');
3113
- }
3114
- ObjectWithArgs(node, context = {}) {
3115
- const output = [];
3116
- if (context === 'noquotes') {
3117
- output.push(this.list(node.objname, ', ', '', context));
3118
- }
3119
- else {
3120
- output.push(this.listQuotes(node.objname, '.'));
3121
- }
3122
- const objargs = unwrapList(node.objargs);
3123
- if (objargs && objargs.length) {
3124
- output.push('(');
3125
- output.push(objargs
3126
- .map((arg) => {
3127
- if (isEmptyObject(arg)) {
3128
- return 'NONE';
3129
- }
3130
- return this.deparse(arg, context);
3131
- })
3132
- .join(','));
3133
- output.push(')');
3134
- }
3135
- else if (!node.args_unspecified) {
3136
- output.push('()');
3137
- }
3138
- return output.join(' ');
3139
- }
3140
- String(node) {
3141
- return node.str;
3142
- }
3143
- SubLink(node, context = {}) {
3144
- switch (true) {
3145
- case node.subLinkType === 'EXISTS_SUBLINK':
3146
- return format('EXISTS (%s)', this.deparse(node.subselect, context));
3147
- case node.subLinkType === 'ALL_SUBLINK':
3148
- return format('%s %s ALL (%s)', this.deparse(node.testexpr, context), this.deparse(node.operName[0], context), this.deparse(node.subselect, context));
3149
- case node.subLinkType === 'ANY_SUBLINK' && !(node.operName != null):
3150
- return format('%s IN (%s)', this.deparse(node.testexpr, context), this.deparse(node.subselect, context));
3151
- case node.subLinkType === 'ANY_SUBLINK':
3152
- return format('%s %s ANY (%s)', this.deparse(node.testexpr, context), this.deparse(node.operName[0], context), this.deparse(node.subselect, context));
3153
- case node.subLinkType === 'ROWCOMPARE_SUBLINK':
3154
- return format('%s %s (%s)', this.deparse(node.testexpr, context), this.deparse(node.operName[0], context), this.deparse(node.subselect, context));
3155
- case node.subLinkType === 'EXPR_SUBLINK':
3156
- return format('(%s)', this.deparse(node.subselect, context));
3157
- case node.subLinkType === 'MULTIEXPR_SUBLINK':
3158
- // TODO(zhm) what is this?
3159
- return fail('SubLink', node);
3160
- // MULTIEXPR_SUBLINK
3161
- // format('(%s)', @deparse(node.subselect))
3162
- case node.subLinkType === 'ARRAY_SUBLINK':
3163
- return format('ARRAY (%s)', this.deparse(node.subselect, context));
3164
- default:
3165
- return fail('SubLink', node);
3166
- }
3167
- }
3168
- TypeCast(node, context = {}) {
3169
- const type = this.TypeName(node.typeName, context);
3170
- let arg = this.deparse(node.arg, context);
3171
- if (node.arg !== undefined && node.arg.A_Expr !== undefined) {
3172
- arg = format('(%s)', arg);
3173
- }
3174
- if (type === 'boolean') {
3175
- const value = dotty.get(node, 'arg.A_Const.val.String.str');
3176
- if (value === 'f') {
3177
- return 'FALSE';
3178
- }
3179
- if (value === 't') {
3180
- return 'TRUE';
3181
- }
3182
- }
3183
- return format('%s::%s', arg, type);
3184
- }
3185
- TypeName(node, context = {}) {
3186
- const names = unwrapList(node.names);
3187
- if (names[names.length - 1].String.str === 'interval') {
3188
- return this.deparseInterval(node);
3189
- }
3190
- const output = [];
3191
- if (node.setof) {
3192
- output.push('SETOF');
3193
- }
3194
- let args = null;
3195
- if (node.typmods != null) {
3196
- args = unwrapList(node.typmods).map((item) => {
3197
- return this.deparse(item, context);
3198
- });
3199
- }
3200
- const type = [];
3201
- type.push(this.type(names, args && args.join(', ')));
3202
- if (node.arrayBounds != null) {
3203
- type.push('[]');
3204
- }
3205
- output.push(type.join(''));
3206
- return output.join(' ');
3207
- }
3208
- CaseWhen(node, context = {}) {
3209
- const output = ['WHEN'];
3210
- output.push(this.deparse(node.expr, context));
3211
- output.push('THEN');
3212
- output.push(this.deparse(node.result, context));
3213
- return output.join(' ');
3214
- }
3215
- WindowDef(node, context = {}) {
3216
- const output = [];
3217
- if (context !== 'window') {
3218
- if (node.name) {
3219
- output.push(node.name);
3220
- }
3221
- }
3222
- const empty = !(node.partitionClause != null) && !(node.orderClause != null);
3223
- const frameOptions = this.deparseFrameOptions(node.frameOptions, node.refname, node.startOffset, node.endOffset);
3224
- if (empty &&
3225
- context !== 'window' &&
3226
- !(node.name != null) &&
3227
- frameOptions.length === 0) {
3228
- return '()';
3229
- }
3230
- const windowParts = [];
3231
- let useParens = false;
3232
- if (node.partitionClause) {
3233
- const partition = ['PARTITION BY'];
3234
- const clause = unwrapList(node.partitionClause).map((item) => this.deparse(item, context));
3235
- partition.push(clause.join(', '));
3236
- windowParts.push(partition.join(' '));
3237
- useParens = true;
3238
- }
3239
- if (node.orderClause) {
3240
- windowParts.push('ORDER BY');
3241
- const orders = unwrapList(node.orderClause).map((item) => {
3242
- return this.deparse(item);
3243
- });
3244
- windowParts.push(orders.join(', '));
3245
- useParens = true;
3246
- }
3247
- if (frameOptions.length) {
3248
- useParens = true;
3249
- windowParts.push(frameOptions);
3250
- }
3251
- if (useParens && context !== 'window') {
3252
- return output.join(' ') + ' (' + windowParts.join(' ') + ')';
3253
- }
3254
- return output.join(' ') + windowParts.join(' ');
3255
- }
3256
- WithClause(node, context = {}) {
3257
- const output = ['WITH'];
3258
- if (node.recursive) {
3259
- output.push('RECURSIVE');
3260
- }
3261
- output.push(this.list(node.ctes, ', ', '', context));
3262
- return output.join(' ');
3263
- }
3264
- CopyStmt(node, context = {}) {
3265
- const output = ['COPY'];
3266
- output.push('(' + this.deparse(node.query, context) + ')');
3267
- output.push('TO');
3268
- output.push(`'${node.filename}'`);
3269
- const options = unwrapList(node.options);
3270
- if (options?.length > 0 && options[0].DefElem.defname === 'format') {
3271
- output.push(`(FORMAT '${this.deparse(options[0].DefElem.arg)}')`);
3272
- }
3273
- return output.join(' ');
3274
- }
3275
- CallStmt(node, context = {}) {
3276
- const output = ['CALL'];
3277
- output.push(this.deparse(unwrapList(node.funccall.funcname)[0]));
3278
- const funccallArgs = unwrapList(node.funccall.args);
3279
- if (funccallArgs && funccallArgs.length) {
3280
- // we have arguments
3281
- output.push('(' + this.list(funccallArgs, ', ', '', context) + ')');
3282
- }
3283
- else {
3284
- // just close parens
3285
- output.push('()');
3286
- }
3287
- return output.join(' ');
3288
- }
3289
- deparseFrameOptions(options, refName, startOffset, endOffset) {
3290
- // https://github.com/pganalyze/libpg_query/blob/442b1748d06364ecd3779bc558899176c02efaf0/src/postgres/include/nodes/parsenodes.h#L505-L522
3291
- const FRAMEOPTION_NONDEFAULT = 0x00001; /* any specified? */
3292
- const FRAMEOPTION_RANGE = 0x00002; /* RANGE behavior */
3293
- const FRAMEOPTION_ROWS = 0x00004; /* ROWS behavior */
3294
- const FRAMEOPTION_GROUPS = 0x00008; /* GROUPS behavior */
3295
- const FRAMEOPTION_BETWEEN = 0x00010; /* BETWEEN given? */
3296
- const FRAMEOPTION_START_UNBOUNDED_PRECEDING = 0x00020; /* start is U. P. */
3297
- const FRAMEOPTION_END_UNBOUNDED_PRECEDING = 0x00040; /* (disallowed) */
3298
- const FRAMEOPTION_START_UNBOUNDED_FOLLOWING = 0x00080; /* (disallowed) */
3299
- const FRAMEOPTION_END_UNBOUNDED_FOLLOWING = 0x00100; /* end is U. F. */
3300
- const FRAMEOPTION_START_CURRENT_ROW = 0x00200; /* start is C. R. */
3301
- const FRAMEOPTION_END_CURRENT_ROW = 0x00400; /* end is C. R. */
3302
- const FRAMEOPTION_START_OFFSET_PRECEDING = 0x00800; /* start is O. P. */
3303
- const FRAMEOPTION_END_OFFSET_PRECEDING = 0x01000; /* end is O. P. */
3304
- const FRAMEOPTION_START_OFFSET_FOLLOWING = 0x02000; /* start is O. F. */
3305
- const FRAMEOPTION_END_OFFSET_FOLLOWING = 0x04000; /* end is O. F. */
3306
- const FRAMEOPTION_EXCLUDE_CURRENT_ROW = 0x08000; /* omit C.R. */
3307
- const FRAMEOPTION_EXCLUDE_GROUP = 0x10000; /* omit C.R. & peers */
3308
- const FRAMEOPTION_EXCLUDE_TIES = 0x20000; /* omit C.R.'s peers */
3309
- // const FRAMEOPTION_START_OFFSET =
3310
- // FRAMEOPTION_START_OFFSET_PRECEDING | FRAMEOPTION_START_OFFSET_FOLLOWING;
3311
- // const FRAMEOPTION_END_OFFSET =
3312
- // FRAMEOPTION_END_OFFSET_PRECEDING | FRAMEOPTION_END_OFFSET_FOLLOWING;
3313
- // const FRAMEOPTION_EXCLUSION =
3314
- // FRAMEOPTION_EXCLUDE_CURRENT_ROW |
3315
- // FRAMEOPTION_EXCLUDE_GROUP |
3316
- // FRAMEOPTION_EXCLUDE_TIES;
3317
- // const FRAMEOPTION_DEFAULTS =
3318
- // FRAMEOPTION_RANGE |
3319
- // FRAMEOPTION_START_UNBOUNDED_PRECEDING |
3320
- // FRAMEOPTION_END_CURRENT_ROW;
3321
- if (!(options & FRAMEOPTION_NONDEFAULT)) {
3322
- return '';
3323
- }
3324
- const output = [];
3325
- if (refName != null) {
3326
- output.push(refName);
3327
- }
3328
- if (options & FRAMEOPTION_RANGE) {
3329
- output.push('RANGE');
3330
- }
3331
- if (options & FRAMEOPTION_ROWS) {
3332
- output.push('ROWS');
3333
- }
3334
- const between = options & FRAMEOPTION_BETWEEN;
3335
- if (between) {
3336
- output.push('BETWEEN');
3337
- }
3338
- if (options & FRAMEOPTION_START_UNBOUNDED_PRECEDING) {
3339
- output.push('UNBOUNDED PRECEDING');
3340
- }
3341
- if (options & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) {
3342
- output.push('UNBOUNDED FOLLOWING');
3343
- }
3344
- if (options & FRAMEOPTION_START_CURRENT_ROW) {
3345
- output.push('CURRENT ROW');
3346
- }
3347
- if (options & FRAMEOPTION_START_OFFSET_PRECEDING) {
3348
- output.push(this.deparse(startOffset) + ' PRECEDING');
3349
- }
3350
- if (options & FRAMEOPTION_START_OFFSET_FOLLOWING) {
3351
- output.push(this.deparse(startOffset) + ' FOLLOWING');
3352
- }
3353
- if (between) {
3354
- output.push('AND');
3355
- if (options & FRAMEOPTION_END_UNBOUNDED_PRECEDING) {
3356
- output.push('UNBOUNDED PRECEDING');
3357
- }
3358
- if (options & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) {
3359
- output.push('UNBOUNDED FOLLOWING');
3360
- }
3361
- if (options & FRAMEOPTION_END_CURRENT_ROW) {
3362
- output.push('CURRENT ROW');
3363
- }
3364
- if (options & FRAMEOPTION_END_OFFSET_PRECEDING) {
3365
- output.push(this.deparse(endOffset) + ' PRECEDING');
3366
- }
3367
- if (options & FRAMEOPTION_END_OFFSET_FOLLOWING) {
3368
- output.push(this.deparse(endOffset) + ' FOLLOWING');
3369
- }
3370
- }
3371
- return output.join(' ');
3372
- }
3373
- deparseInterval(node) {
3374
- const type = ['interval'];
3375
- if (node.arrayBounds != null) {
3376
- type.push('[]');
3377
- }
3378
- if (node.typmods) {
3379
- const nodeTypmods = unwrapList(node.typmods);
3380
- const typmods = nodeTypmods.map((item) => this.deparse(item));
3381
- let intervals = this.interval(typmods[0]);
3382
- // SELECT interval(0) '1 day 01:23:45.6789'
3383
- if (nodeTypmods[0] &&
3384
- nodeTypmods[0].A_Const &&
3385
- nodeTypmods[0].A_Const.val.Integer.ival === 32767 &&
3386
- nodeTypmods[1] &&
3387
- nodeTypmods[1].A_Const != null) {
3388
- intervals = [`(${nodeTypmods[1].A_Const.val.Integer.ival})`];
3389
- }
3390
- else {
3391
- intervals = unwrapList(intervals).map((part) => {
3392
- if (part === 'second' && typmods.length === 2) {
3393
- return 'second(' + typmods[typmods.length - 1] + ')';
3394
- }
3395
- return part;
3396
- });
3397
- }
3398
- type.push(intervals.join(' to '));
3399
- }
3400
- return type.join(' ');
3401
- }
3402
- interval(mask) {
3403
- // ported from https://github.com/lfittl/pg_query/blob/master/lib/pg_query/deparse/interval.rb
3404
- if (this.MASKS == null) {
3405
- this.MASKS = {
3406
- 0: 'RESERV',
3407
- 1: 'MONTH',
3408
- 2: 'YEAR',
3409
- 3: 'DAY',
3410
- 4: 'JULIAN',
3411
- 5: 'TZ',
3412
- 6: 'DTZ',
3413
- 7: 'DYNTZ',
3414
- 8: 'IGNORE_DTF',
3415
- 9: 'AMPM',
3416
- 10: 'HOUR',
3417
- 11: 'MINUTE',
3418
- 12: 'SECOND',
3419
- 13: 'MILLISECOND',
3420
- 14: 'MICROSECOND',
3421
- 15: 'DOY',
3422
- 16: 'DOW',
3423
- 17: 'UNITS',
3424
- 18: 'ADBC',
3425
- 19: 'AGO',
3426
- 20: 'ABS_BEFORE',
3427
- 21: 'ABS_AFTER',
3428
- 22: 'ISODATE',
3429
- 23: 'ISOTIME',
3430
- 24: 'WEEK',
3431
- 25: 'DECADE',
3432
- 26: 'CENTURY',
3433
- 27: 'MILLENNIUM',
3434
- 28: 'DTZMOD'
3435
- };
3436
- }
3437
- if (this.BITS == null) {
3438
- this.BITS = inverted(this.MASKS);
3439
- }
3440
- if (this.INTERVALS == null) {
3441
- this.INTERVALS = {};
3442
- this.INTERVALS[1 << this.BITS.YEAR] = ['year'];
3443
- this.INTERVALS[1 << this.BITS.MONTH] = ['month'];
3444
- this.INTERVALS[1 << this.BITS.DAY] = ['day'];
3445
- this.INTERVALS[1 << this.BITS.HOUR] = ['hour'];
3446
- this.INTERVALS[1 << this.BITS.MINUTE] = ['minute'];
3447
- this.INTERVALS[1 << this.BITS.SECOND] = ['second'];
3448
- this.INTERVALS[(1 << this.BITS.YEAR) | (1 << this.BITS.MONTH)] = [
3449
- 'year',
3450
- 'month'
3451
- ];
3452
- this.INTERVALS[(1 << this.BITS.DAY) | (1 << this.BITS.HOUR)] = [
3453
- 'day',
3454
- 'hour'
3455
- ];
3456
- this.INTERVALS[(1 << this.BITS.DAY) | (1 << this.BITS.HOUR) | (1 << this.BITS.MINUTE)] = ['day', 'minute'];
3457
- this.INTERVALS[(1 << this.BITS.DAY) |
3458
- (1 << this.BITS.HOUR) |
3459
- (1 << this.BITS.MINUTE) |
3460
- (1 << this.BITS.SECOND)] = ['day', 'second'];
3461
- this.INTERVALS[(1 << this.BITS.HOUR) | (1 << this.BITS.MINUTE)] = [
3462
- 'hour',
3463
- 'minute'
3464
- ];
3465
- this.INTERVALS[(1 << this.BITS.HOUR) |
3466
- (1 << this.BITS.MINUTE) |
3467
- (1 << this.BITS.SECOND)] = ['hour', 'second'];
3468
- this.INTERVALS[(1 << this.BITS.MINUTE) | (1 << this.BITS.SECOND)] = [
3469
- 'minute',
3470
- 'second'
3471
- ];
3472
- // utils/timestamp.h
3473
- // #define INTERVAL_FULL_RANGE (0x7FFF)
3474
- this.INTERVALS[(this.INTERVAL_FULL_RANGE = '32767')] = [];
3475
- }
3476
- return this.INTERVALS[mask.toString()];
3477
- }
3478
- }