pgsql-deparser 13.3.10 → 13.3.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,30 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [13.3.13](https://github.com/pyramation/pgsql-parser/compare/pgsql-deparser@13.3.12...pgsql-deparser@13.3.13) (2022-08-31)
7
+
8
+ **Note:** Version bump only for package pgsql-deparser
9
+
10
+
11
+
12
+
13
+
14
+ ## [13.3.12](https://github.com/pyramation/pgsql-parser/compare/pgsql-deparser@13.3.11...pgsql-deparser@13.3.12) (2022-07-29)
15
+
16
+ **Note:** Version bump only for package pgsql-deparser
17
+
18
+
19
+
20
+
21
+
22
+ ## [13.3.11](https://github.com/pyramation/pgsql-parser/compare/pgsql-deparser@13.3.10...pgsql-deparser@13.3.11) (2022-05-20)
23
+
24
+ **Note:** Version bump only for package pgsql-deparser
25
+
26
+
27
+
28
+
29
+
6
30
  ## [13.3.10](https://github.com/pyramation/pgsql-parser/compare/pgsql-deparser@13.3.9...pgsql-deparser@13.3.10) (2022-05-19)
7
31
 
8
32
  **Note:** Version bump only for package pgsql-deparser
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # pgsql-parser [![Build Status](https://travis-ci.org/pyramation/pgsql-parser.svg?branch=master)](https://travis-ci.org/pyramation/pgsql-parser)
1
+ # pgsql-parser [![tests](https://github.com/pyramation/pgsql-parser/actions/workflows/run-tests.yaml/badge.svg)](https://github.com/pyramation/pgsql-parser/actions/workflows/run-tests.yaml)
2
2
 
3
3
  The real PostgreSQL parser for nodejs. The primary objective of this module is to provide symmetric parsing and deparsing of SQL statements. With this module you can modify parts of a SQL query statement and serialize the query tree back into a formatted SQL statement. It uses the *real* [PostgreSQL parser](https://github.com/pganalyze/libpg_query).
4
4
 
package/main/deparser.js CHANGED
@@ -45,7 +45,18 @@ var fail = function fail(type, node) {
45
45
  }; // select word from pg_get_keywords() where catcode = 'R';
46
46
 
47
47
 
48
- var RESERVED_WORDS = ['all', 'analyse', 'analyze', 'and', 'any', 'array', 'as', 'asc', 'asymmetric', 'both', 'case', 'cast', 'check', 'collate', 'column', 'constraint', 'create', 'current_catalog', 'current_date', 'current_role', 'current_time', 'current_timestamp', 'current_user', 'default', 'deferrable', 'desc', 'distinct', 'do', 'else', 'end', 'except', 'false', 'fetch', 'for', 'foreign', 'from', 'grant', 'group', 'having', 'in', 'initially', 'intersect', 'into', 'lateral', 'leading', 'limit', 'localtime', 'localtimestamp', 'not', 'null', 'offset', 'on', 'only', 'or', 'order', 'placing', 'primary', 'references', 'returning', 'select', 'session_user', 'some', 'symmetric', 'table', 'then', 'to', 'trailing', 'true', 'union', 'unique', 'user', 'using', 'variadic', 'when', 'where', 'window', 'with'];
48
+ var RESERVED_WORDS = ['all', 'analyse', 'analyze', 'and', 'any', 'array', 'as', 'asc', 'asymmetric', 'both', 'case', 'cast', 'check', 'collate', 'column', 'constraint', 'create', 'current_catalog', 'current_date', 'current_role', 'current_time', 'current_timestamp', 'current_user', 'default', 'deferrable', 'desc', 'distinct', 'do', 'else', 'end', 'except', 'false', 'fetch', 'for', 'foreign', 'from', 'grant', 'group', 'having', 'in', 'initially', 'intersect', 'into', 'lateral', 'leading', 'limit', 'localtime', 'localtimestamp', 'not', 'null', 'offset', 'on', 'only', 'or', 'order', 'placing', 'primary', 'references', 'returning', 'select', 'session_user', 'some', 'symmetric', 'table', 'then', 'to', 'trailing', 'true', 'union', 'unique', 'user', 'using', 'variadic', 'when', 'where', 'window', 'with']; // https://github.com/pganalyze/libpg_query/blob/b2790f8140721ff7f047167ecd7d44267b0a3880/src/postgres/include/storage/lockdefs.h
49
+
50
+ var LOCK_MODES = {
51
+ 1: 'ACCESS SHARE',
52
+ 2: 'ROW SHARE',
53
+ 3: 'ROW EXCLUSIVE',
54
+ 4: 'SHARE UPDATE EXCLUSIVE',
55
+ 5: 'SHARE',
56
+ 6: 'SHARE ROW',
57
+ 7: 'EXCLUSIVE',
58
+ 8: 'ACCESS EXCLUSIVE'
59
+ };
49
60
 
50
61
  var isReserved = function isReserved(value) {
51
62
  return RESERVED_WORDS.includes(value.toLowerCase());
@@ -113,6 +124,15 @@ var Deparser = /*#__PURE__*/function () {
113
124
  return _lodash["default"].isArray(node) ? _this2.list(node, ', ', '', context) : _this2.deparse(node, context);
114
125
  });
115
126
  }
127
+ }, {
128
+ key: "deparseReturningList",
129
+ value: function deparseReturningList(list, context) {
130
+ var _this3 = this;
131
+
132
+ return list.map(function (returning) {
133
+ return _this3.deparse(returning.ResTarget.val, context) + (returning.ResTarget.name ? ' AS ' + _this3.quote(returning.ResTarget.name) : '');
134
+ }).join(',');
135
+ }
116
136
  }, {
117
137
  key: "list",
118
138
  value: function list(nodes) {
@@ -131,17 +151,17 @@ var Deparser = /*#__PURE__*/function () {
131
151
  }, {
132
152
  key: "listQuotes",
133
153
  value: function listQuotes(nodes) {
134
- var _this3 = this;
154
+ var _this4 = this;
135
155
 
136
156
  var separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ', ';
137
157
  return this.list(nodes, separator).split(separator).map(function (a) {
138
- return _this3.quote(a.trim());
158
+ return _this4.quote(a.trim());
139
159
  }).join(separator);
140
160
  }
141
161
  }, {
142
162
  key: "quote",
143
163
  value: function quote(value) {
144
- var _this4 = this;
164
+ var _this5 = this;
145
165
 
146
166
  if (value == null) {
147
167
  return null;
@@ -149,7 +169,7 @@ var Deparser = /*#__PURE__*/function () {
149
169
 
150
170
  if (_lodash["default"].isArray(value)) {
151
171
  return value.map(function (o) {
152
- return _this4.quote(o);
172
+ return _this5.quote(o);
153
173
  });
154
174
  }
155
175
 
@@ -218,10 +238,10 @@ var Deparser = /*#__PURE__*/function () {
218
238
  }, {
219
239
  key: "type",
220
240
  value: function type(names, args) {
221
- var _this5 = this;
241
+ var _this6 = this;
222
242
 
223
243
  var _names$map = names.map(function (name) {
224
- return _this5.deparse(name);
244
+ return _this6.deparse(name);
225
245
  }),
226
246
  _names$map2 = (0, _slicedToArray2["default"])(_names$map, 2),
227
247
  catalog = _names$map2[0],
@@ -325,15 +345,15 @@ var Deparser = /*#__PURE__*/function () {
325
345
  output.push('TO');
326
346
  output.push(this.RangeVar(node.relation, context));
327
347
 
328
- if (node.instead) {
329
- output.push('DO');
330
- output.push('INSTEAD');
331
- }
332
-
333
348
  if (node.whereClause) {
334
349
  output.push('WHERE');
335
350
  output.push(this.deparse(node.whereClause, context));
336
- output.push('DO');
351
+ }
352
+
353
+ output.push('DO');
354
+
355
+ if (node.instead) {
356
+ output.push('INSTEAD');
337
357
  }
338
358
 
339
359
  if (!node.actions || !node.actions.length) {
@@ -909,22 +929,22 @@ var Deparser = /*#__PURE__*/function () {
909
929
  }, {
910
930
  key: 'ColumnRef',
911
931
  value: function ColumnRef(node) {
912
- var _this6 = this;
932
+ var _this7 = this;
913
933
 
914
934
  var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
915
935
  var KEYWORDS = ['old', 'new'];
916
936
  var fields = node.fields.map(function (field) {
917
937
  if (field.String) {
918
- var value = _this6.deparse(field, context);
938
+ var value = _this7.deparse(field, context);
919
939
 
920
940
  if (context === 'trigger' && KEYWORDS.includes(value.toLowerCase())) {
921
941
  return value.toUpperCase();
922
942
  }
923
943
 
924
- return _this6.quote(value);
944
+ return _this7.quote(value);
925
945
  }
926
946
 
927
- return _this6.deparse(field, context);
947
+ return _this7.deparse(field, context);
928
948
  });
929
949
  return fields.join('.');
930
950
  }
@@ -1027,7 +1047,8 @@ var Deparser = /*#__PURE__*/function () {
1027
1047
  output.push(node.ctename);
1028
1048
 
1029
1049
  if (node.aliascolnames) {
1030
- output.push((0, _util.format)('(%s)', this.quote(this.deparseNodes(node.aliascolnames, context))));
1050
+ var colnames = this.quote(this.deparseNodes(node.aliascolnames, context));
1051
+ output.push("(".concat(colnames.join(', '), ")"));
1031
1052
  }
1032
1053
 
1033
1054
  output.push((0, _util.format)('AS (%s)', this.deparse(node.ctequery)));
@@ -1140,7 +1161,7 @@ var Deparser = /*#__PURE__*/function () {
1140
1161
  }, {
1141
1162
  key: 'DefElem',
1142
1163
  value: function DefElem(node) {
1143
- var _this7 = this;
1164
+ var _this8 = this;
1144
1165
 
1145
1166
  var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1146
1167
 
@@ -1215,7 +1236,7 @@ var Deparser = /*#__PURE__*/function () {
1215
1236
  {
1216
1237
  var output = [];
1217
1238
  node.arg.forEach(function (opt) {
1218
- output.push(_this7.quote(_this7.deparse(opt, context)));
1239
+ output.push(_this8.quote(_this8.deparse(opt, context)));
1219
1240
  });
1220
1241
  return "OWNED BY ".concat(output.join('.'));
1221
1242
  }
@@ -1237,6 +1258,10 @@ var Deparser = /*#__PURE__*/function () {
1237
1258
  }
1238
1259
 
1239
1260
  }
1261
+ } else if (context === 'explain') {
1262
+ if (node.arg) {
1263
+ return "".concat(name, " ").concat(this.deparse(node.arg));
1264
+ }
1240
1265
  } else if (node.arg) {
1241
1266
  return "".concat(name, " = ").concat(this.deparse(node.arg, context));
1242
1267
  }
@@ -1261,7 +1286,7 @@ var Deparser = /*#__PURE__*/function () {
1261
1286
  }, {
1262
1287
  key: 'FuncCall',
1263
1288
  value: function FuncCall(node) {
1264
- var _this8 = this;
1289
+ var _this9 = this;
1265
1290
 
1266
1291
  var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1267
1292
  var output = [];
@@ -1269,7 +1294,7 @@ var Deparser = /*#__PURE__*/function () {
1269
1294
 
1270
1295
  if (node.args) {
1271
1296
  params = node.args.map(function (item) {
1272
- return _this8.deparse(item, context);
1297
+ return _this9.deparse(item, context);
1273
1298
  });
1274
1299
  } // COUNT(*)
1275
1300
 
@@ -1435,10 +1460,13 @@ var Deparser = /*#__PURE__*/function () {
1435
1460
  }, {
1436
1461
  key: 'InsertStmt',
1437
1462
  value: function InsertStmt(node) {
1438
- var _this9 = this;
1439
-
1440
1463
  var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1441
1464
  var output = [];
1465
+
1466
+ if (node.withClause) {
1467
+ output.push(this.WithClause(node.withClause, context));
1468
+ }
1469
+
1442
1470
  output.push('INSERT INTO');
1443
1471
  output.push(this.RangeVar(node.relation, context));
1444
1472
 
@@ -1484,9 +1512,7 @@ var Deparser = /*#__PURE__*/function () {
1484
1512
 
1485
1513
  if (node.returningList) {
1486
1514
  output.push('RETURNING');
1487
- output.push(node.returningList.map(function (returning) {
1488
- return _this9.deparse(returning.ResTarget.val, context) + (returning.ResTarget.name ? ' AS ' + _this9.quote(returning.ResTarget.name) : '');
1489
- }).join(','));
1515
+ output.push(this.deparseReturningList(node.returningList, context));
1490
1516
  }
1491
1517
 
1492
1518
  return output.join(' ');
@@ -1509,15 +1535,30 @@ var Deparser = /*#__PURE__*/function () {
1509
1535
  value: function DeleteStmt(node) {
1510
1536
  var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1511
1537
  var output = [''];
1538
+
1539
+ if (node.withClause) {
1540
+ output.push(this.WithClause(node.withClause, context));
1541
+ }
1542
+
1512
1543
  output.push('DELETE');
1513
1544
  output.push('FROM');
1514
1545
  output.push(this.RangeVar(node.relation, context));
1515
1546
 
1547
+ if (node.usingClause) {
1548
+ output.push('USING');
1549
+ output.push(this.list(node.usingClause, ', ', '', context));
1550
+ }
1551
+
1516
1552
  if (node.whereClause) {
1517
1553
  output.push('WHERE');
1518
1554
  output.push(this.deparse(node.whereClause, context));
1519
1555
  }
1520
1556
 
1557
+ if (node.returningList) {
1558
+ output.push('RETURNING');
1559
+ output.push(this.deparseReturningList(node.returningList, context));
1560
+ }
1561
+
1521
1562
  return output.join(' ');
1522
1563
  }
1523
1564
  }, {
@@ -1527,6 +1568,11 @@ var Deparser = /*#__PURE__*/function () {
1527
1568
 
1528
1569
  var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1529
1570
  var output = [];
1571
+
1572
+ if (node.withClause) {
1573
+ output.push(this.WithClause(node.withClause, context));
1574
+ }
1575
+
1530
1576
  output.push('UPDATE');
1531
1577
 
1532
1578
  if (node.relation) {
@@ -1564,9 +1610,7 @@ var Deparser = /*#__PURE__*/function () {
1564
1610
 
1565
1611
  if (node.returningList) {
1566
1612
  output.push('RETURNING');
1567
- output.push(node.returningList.map(function (returning) {
1568
- return _this10.deparse(returning.ResTarget.val, context) + (returning.ResTarget.name ? ' AS ' + _this10.quote(returning.ResTarget.name) : '');
1569
- }).join(','));
1613
+ output.push(this.deparseReturningList(node.returningList, context));
1570
1614
  }
1571
1615
 
1572
1616
  return output.join(' ');
@@ -1699,6 +1743,24 @@ var Deparser = /*#__PURE__*/function () {
1699
1743
  return output.join(' ');
1700
1744
  }
1701
1745
  }, {
1746
+ key: 'LockStmt',
1747
+ value: function LockStmt(node) {
1748
+ var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1749
+ var output = ['LOCK'];
1750
+ output.push(this.list(node.relations, ', ', '', {
1751
+ lock: true
1752
+ }));
1753
+ output.push('IN');
1754
+ output.push(LOCK_MODES[node.mode]);
1755
+ output.push('MODE');
1756
+
1757
+ if (node.nowait) {
1758
+ output.push('NOWAIT');
1759
+ }
1760
+
1761
+ return output.join(' ');
1762
+ }
1763
+ }, {
1702
1764
  key: 'MinMaxExpr',
1703
1765
  value: function MinMaxExpr(node) {
1704
1766
  var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -1847,17 +1909,17 @@ var Deparser = /*#__PURE__*/function () {
1847
1909
 
1848
1910
  if (node.inhOpt === 0) {
1849
1911
  output.push('ONLY');
1850
- } // TODO why does this seem to be what we really need vs the above?
1851
- // if (!node.inh) {
1852
- // output.push('ONLY');
1853
- // }
1912
+ }
1854
1913
 
1914
+ if (!node.inh && (context.lock || context === 'truncate')) {
1915
+ output.push('ONLY');
1916
+ }
1855
1917
 
1856
1918
  if (node.relpersistence === 'u') {
1857
1919
  output.push('UNLOGGED');
1858
1920
  }
1859
1921
 
1860
- if (node.relpersistence === 't') {
1922
+ if (node.relpersistence === 't' && context !== 'view') {
1861
1923
  output.push('TEMPORARY TABLE');
1862
1924
  }
1863
1925
 
@@ -1905,6 +1967,13 @@ var Deparser = /*#__PURE__*/function () {
1905
1967
  var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1906
1968
  var output = [];
1907
1969
  output.push('EXPLAIN');
1970
+
1971
+ if (node.options) {
1972
+ output.push('(');
1973
+ output.push(this.list(node.options, ', ', '', 'explain'));
1974
+ output.push(')');
1975
+ }
1976
+
1908
1977
  output.push(this.deparse(node.query, context));
1909
1978
  return output.join(' ');
1910
1979
  }
@@ -2057,6 +2126,23 @@ var Deparser = /*#__PURE__*/function () {
2057
2126
  return output.join(' ');
2058
2127
  }
2059
2128
  }, {
2129
+ key: 'TruncateStmt',
2130
+ value: function TruncateStmt(node) {
2131
+ var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2132
+ var output = ['TRUNCATE TABLE'];
2133
+ output.push(this.list(node.relations, ', ', '', 'truncate'));
2134
+
2135
+ if (node.restart_seqs) {
2136
+ output.push('RESTART IDENTITY');
2137
+ }
2138
+
2139
+ if (node.behavior === 'DROP_CASCADE') {
2140
+ output.push('CASCADE');
2141
+ }
2142
+
2143
+ return output.join(' ');
2144
+ }
2145
+ }, {
2060
2146
  key: 'AlterDefaultPrivilegesStmt',
2061
2147
  value: function AlterDefaultPrivilegesStmt(node) {
2062
2148
  var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -2579,10 +2665,29 @@ var Deparser = /*#__PURE__*/function () {
2579
2665
  var output = [];
2580
2666
  output.push('CREATE');
2581
2667
  if (node.replace) output.push('OR REPLACE');
2668
+
2669
+ if (node.view.relpersistence === 't') {
2670
+ output.push('TEMPORARY');
2671
+ }
2672
+
2582
2673
  output.push('VIEW');
2583
- output.push(this.RangeVar(node.view, context));
2674
+ output.push(this.RangeVar(node.view, 'view'));
2675
+
2676
+ if (node.aliases) {
2677
+ output.push('(');
2678
+ output.push(this.list(node.aliases, ', ', '', context));
2679
+ output.push(')');
2680
+ }
2681
+
2584
2682
  output.push('AS');
2585
2683
  output.push(this.deparse(node.query, context));
2684
+
2685
+ if (node.withCheckOption === 'LOCAL_CHECK_OPTION') {
2686
+ output.push('WITH LOCAL CHECK OPTION');
2687
+ } else if (node.withCheckOption === 'CASCADED_CHECK_OPTION') {
2688
+ output.push('WITH CASCADED CHECK OPTION');
2689
+ }
2690
+
2586
2691
  return output.join(' ');
2587
2692
  }
2588
2693
  }, {
@@ -2625,8 +2730,19 @@ var Deparser = /*#__PURE__*/function () {
2625
2730
  key: 'CreateTableAsStmt',
2626
2731
  value: function CreateTableAsStmt(node) {
2627
2732
  var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2628
- var output = [];
2629
- output.push('CREATE MATERIALIZED VIEW');
2733
+ var output = ['CREATE'];
2734
+ var relpersistence = dotty.get(node, 'into.rel.relpersistence');
2735
+
2736
+ if (node.relkind === 'OBJECT_MATVIEW') {
2737
+ output.push('MATERIALIZED VIEW');
2738
+ } else if (relpersistence !== 't') {
2739
+ output.push('TABLE');
2740
+
2741
+ if (node.if_not_exists) {
2742
+ output.push('IF NOT EXISTS');
2743
+ }
2744
+ }
2745
+
2630
2746
  output.push(this.IntoClause(node.into, context));
2631
2747
  output.push('AS');
2632
2748
  output.push(this.deparse(node.query, context));
@@ -2800,7 +2916,7 @@ var Deparser = /*#__PURE__*/function () {
2800
2916
  output.push(this.list(node.tableElts, ",".concat(NEWLINE_CHAR), TAB_CHAR, context));
2801
2917
  output.push("".concat(NEWLINE_CHAR, ")"));
2802
2918
 
2803
- if (relpersistence === 'p' && node.hasOwnProperty('inhRelations')) {
2919
+ if (node.hasOwnProperty('inhRelations')) {
2804
2920
  output.push('INHERITS');
2805
2921
  output.push('(');
2806
2922
  output.push(this.list(node.inhRelations, ', ', '', context));
@@ -22,7 +22,18 @@ const fail = (type, node) => {
22
22
  }; // select word from pg_get_keywords() where catcode = 'R';
23
23
 
24
24
 
25
- const RESERVED_WORDS = ['all', 'analyse', 'analyze', 'and', 'any', 'array', 'as', 'asc', 'asymmetric', 'both', 'case', 'cast', 'check', 'collate', 'column', 'constraint', 'create', 'current_catalog', 'current_date', 'current_role', 'current_time', 'current_timestamp', 'current_user', 'default', 'deferrable', 'desc', 'distinct', 'do', 'else', 'end', 'except', 'false', 'fetch', 'for', 'foreign', 'from', 'grant', 'group', 'having', 'in', 'initially', 'intersect', 'into', 'lateral', 'leading', 'limit', 'localtime', 'localtimestamp', 'not', 'null', 'offset', 'on', 'only', 'or', 'order', 'placing', 'primary', 'references', 'returning', 'select', 'session_user', 'some', 'symmetric', 'table', 'then', 'to', 'trailing', 'true', 'union', 'unique', 'user', 'using', 'variadic', 'when', 'where', 'window', 'with'];
25
+ const RESERVED_WORDS = ['all', 'analyse', 'analyze', 'and', 'any', 'array', 'as', 'asc', 'asymmetric', 'both', 'case', 'cast', 'check', 'collate', 'column', 'constraint', 'create', 'current_catalog', 'current_date', 'current_role', 'current_time', 'current_timestamp', 'current_user', 'default', 'deferrable', 'desc', 'distinct', 'do', 'else', 'end', 'except', 'false', 'fetch', 'for', 'foreign', 'from', 'grant', 'group', 'having', 'in', 'initially', 'intersect', 'into', 'lateral', 'leading', 'limit', 'localtime', 'localtimestamp', 'not', 'null', 'offset', 'on', 'only', 'or', 'order', 'placing', 'primary', 'references', 'returning', 'select', 'session_user', 'some', 'symmetric', 'table', 'then', 'to', 'trailing', 'true', 'union', 'unique', 'user', 'using', 'variadic', 'when', 'where', 'window', 'with']; // https://github.com/pganalyze/libpg_query/blob/b2790f8140721ff7f047167ecd7d44267b0a3880/src/postgres/include/storage/lockdefs.h
26
+
27
+ const LOCK_MODES = {
28
+ 1: 'ACCESS SHARE',
29
+ 2: 'ROW SHARE',
30
+ 3: 'ROW EXCLUSIVE',
31
+ 4: 'SHARE UPDATE EXCLUSIVE',
32
+ 5: 'SHARE',
33
+ 6: 'SHARE ROW',
34
+ 7: 'EXCLUSIVE',
35
+ 8: 'ACCESS EXCLUSIVE'
36
+ };
26
37
 
27
38
  const isReserved = value => RESERVED_WORDS.includes(value.toLowerCase()); // usually the AST lowercases all the things, so if we
28
39
  // have both, the author most likely used double quotes
@@ -79,6 +90,10 @@ export default class Deparser {
79
90
  });
80
91
  }
81
92
 
93
+ deparseReturningList(list, context) {
94
+ return list.map(returning => this.deparse(returning.ResTarget.val, context) + (returning.ResTarget.name ? ' AS ' + this.quote(returning.ResTarget.name) : '')).join(',');
95
+ }
96
+
82
97
  list(nodes, separator = ', ', prefix = '', context) {
83
98
  if (!nodes) {
84
99
  return '';
@@ -256,15 +271,15 @@ export default class Deparser {
256
271
  output.push('TO');
257
272
  output.push(this.RangeVar(node.relation, context));
258
273
 
259
- if (node.instead) {
260
- output.push('DO');
261
- output.push('INSTEAD');
262
- }
263
-
264
274
  if (node.whereClause) {
265
275
  output.push('WHERE');
266
276
  output.push(this.deparse(node.whereClause, context));
267
- output.push('DO');
277
+ }
278
+
279
+ output.push('DO');
280
+
281
+ if (node.instead) {
282
+ output.push('INSTEAD');
268
283
  }
269
284
 
270
285
  if (!node.actions || !node.actions.length) {
@@ -913,7 +928,8 @@ export default class Deparser {
913
928
  output.push(node.ctename);
914
929
 
915
930
  if (node.aliascolnames) {
916
- output.push(format('(%s)', this.quote(this.deparseNodes(node.aliascolnames, context))));
931
+ const colnames = this.quote(this.deparseNodes(node.aliascolnames, context));
932
+ output.push(`(${colnames.join(', ')})`);
917
933
  }
918
934
 
919
935
  output.push(format('AS (%s)', this.deparse(node.ctequery)));
@@ -1115,6 +1131,10 @@ export default class Deparser {
1115
1131
  }
1116
1132
 
1117
1133
  }
1134
+ } else if (context === 'explain') {
1135
+ if (node.arg) {
1136
+ return `${name} ${this.deparse(node.arg)}`;
1137
+ }
1118
1138
  } else if (node.arg) {
1119
1139
  return `${name} = ${this.deparse(node.arg, context)}`;
1120
1140
  }
@@ -1298,6 +1318,11 @@ export default class Deparser {
1298
1318
 
1299
1319
  ['InsertStmt'](node, context = {}) {
1300
1320
  const output = [];
1321
+
1322
+ if (node.withClause) {
1323
+ output.push(this.WithClause(node.withClause, context));
1324
+ }
1325
+
1301
1326
  output.push('INSERT INTO');
1302
1327
  output.push(this.RangeVar(node.relation, context));
1303
1328
 
@@ -1343,7 +1368,7 @@ export default class Deparser {
1343
1368
 
1344
1369
  if (node.returningList) {
1345
1370
  output.push('RETURNING');
1346
- output.push(node.returningList.map(returning => this.deparse(returning.ResTarget.val, context) + (returning.ResTarget.name ? ' AS ' + this.quote(returning.ResTarget.name) : '')).join(','));
1371
+ output.push(this.deparseReturningList(node.returningList, context));
1347
1372
  }
1348
1373
 
1349
1374
  return output.join(' ');
@@ -1361,20 +1386,40 @@ export default class Deparser {
1361
1386
 
1362
1387
  ['DeleteStmt'](node, context = {}) {
1363
1388
  const output = [''];
1389
+
1390
+ if (node.withClause) {
1391
+ output.push(this.WithClause(node.withClause, context));
1392
+ }
1393
+
1364
1394
  output.push('DELETE');
1365
1395
  output.push('FROM');
1366
1396
  output.push(this.RangeVar(node.relation, context));
1367
1397
 
1398
+ if (node.usingClause) {
1399
+ output.push('USING');
1400
+ output.push(this.list(node.usingClause, ', ', '', context));
1401
+ }
1402
+
1368
1403
  if (node.whereClause) {
1369
1404
  output.push('WHERE');
1370
1405
  output.push(this.deparse(node.whereClause, context));
1371
1406
  }
1372
1407
 
1408
+ if (node.returningList) {
1409
+ output.push('RETURNING');
1410
+ output.push(this.deparseReturningList(node.returningList, context));
1411
+ }
1412
+
1373
1413
  return output.join(' ');
1374
1414
  }
1375
1415
 
1376
1416
  ['UpdateStmt'](node, context = {}) {
1377
1417
  const output = [];
1418
+
1419
+ if (node.withClause) {
1420
+ output.push(this.WithClause(node.withClause, context));
1421
+ }
1422
+
1378
1423
  output.push('UPDATE');
1379
1424
 
1380
1425
  if (node.relation) {
@@ -1408,7 +1453,7 @@ export default class Deparser {
1408
1453
 
1409
1454
  if (node.returningList) {
1410
1455
  output.push('RETURNING');
1411
- output.push(node.returningList.map(returning => this.deparse(returning.ResTarget.val, context) + (returning.ResTarget.name ? ' AS ' + this.quote(returning.ResTarget.name) : '')).join(','));
1456
+ output.push(this.deparseReturningList(node.returningList, context));
1412
1457
  }
1413
1458
 
1414
1459
  return output.join(' ');
@@ -1532,6 +1577,22 @@ export default class Deparser {
1532
1577
  return output.join(' ');
1533
1578
  }
1534
1579
 
1580
+ ['LockStmt'](node, context = {}) {
1581
+ const output = ['LOCK'];
1582
+ output.push(this.list(node.relations, ', ', '', {
1583
+ lock: true
1584
+ }));
1585
+ output.push('IN');
1586
+ output.push(LOCK_MODES[node.mode]);
1587
+ output.push('MODE');
1588
+
1589
+ if (node.nowait) {
1590
+ output.push('NOWAIT');
1591
+ }
1592
+
1593
+ return output.join(' ');
1594
+ }
1595
+
1535
1596
  ['MinMaxExpr'](node, context = {}) {
1536
1597
  const output = [];
1537
1598
 
@@ -1664,17 +1725,17 @@ export default class Deparser {
1664
1725
 
1665
1726
  if (node.inhOpt === 0) {
1666
1727
  output.push('ONLY');
1667
- } // TODO why does this seem to be what we really need vs the above?
1668
- // if (!node.inh) {
1669
- // output.push('ONLY');
1670
- // }
1728
+ }
1671
1729
 
1730
+ if (!node.inh && (context.lock || context === 'truncate')) {
1731
+ output.push('ONLY');
1732
+ }
1672
1733
 
1673
1734
  if (node.relpersistence === 'u') {
1674
1735
  output.push('UNLOGGED');
1675
1736
  }
1676
1737
 
1677
- if (node.relpersistence === 't') {
1738
+ if (node.relpersistence === 't' && context !== 'view') {
1678
1739
  output.push('TEMPORARY TABLE');
1679
1740
  }
1680
1741
 
@@ -1714,6 +1775,13 @@ export default class Deparser {
1714
1775
  ['ExplainStmt'](node, context = {}) {
1715
1776
  const output = [];
1716
1777
  output.push('EXPLAIN');
1778
+
1779
+ if (node.options) {
1780
+ output.push('(');
1781
+ output.push(this.list(node.options, ', ', '', 'explain'));
1782
+ output.push(')');
1783
+ }
1784
+
1717
1785
  output.push(this.deparse(node.query, context));
1718
1786
  return output.join(' ');
1719
1787
  }
@@ -1852,6 +1920,21 @@ export default class Deparser {
1852
1920
  return output.join(' ');
1853
1921
  }
1854
1922
 
1923
+ ['TruncateStmt'](node, context = {}) {
1924
+ const output = ['TRUNCATE TABLE'];
1925
+ output.push(this.list(node.relations, ', ', '', 'truncate'));
1926
+
1927
+ if (node.restart_seqs) {
1928
+ output.push('RESTART IDENTITY');
1929
+ }
1930
+
1931
+ if (node.behavior === 'DROP_CASCADE') {
1932
+ output.push('CASCADE');
1933
+ }
1934
+
1935
+ return output.join(' ');
1936
+ }
1937
+
1855
1938
  ['AlterDefaultPrivilegesStmt'](node, context = {}) {
1856
1939
  const output = [];
1857
1940
  output.push('ALTER DEFAULT PRIVILEGES');
@@ -2348,10 +2431,29 @@ export default class Deparser {
2348
2431
  const output = [];
2349
2432
  output.push('CREATE');
2350
2433
  if (node.replace) output.push('OR REPLACE');
2434
+
2435
+ if (node.view.relpersistence === 't') {
2436
+ output.push('TEMPORARY');
2437
+ }
2438
+
2351
2439
  output.push('VIEW');
2352
- output.push(this.RangeVar(node.view, context));
2440
+ output.push(this.RangeVar(node.view, 'view'));
2441
+
2442
+ if (node.aliases) {
2443
+ output.push('(');
2444
+ output.push(this.list(node.aliases, ', ', '', context));
2445
+ output.push(')');
2446
+ }
2447
+
2353
2448
  output.push('AS');
2354
2449
  output.push(this.deparse(node.query, context));
2450
+
2451
+ if (node.withCheckOption === 'LOCAL_CHECK_OPTION') {
2452
+ output.push('WITH LOCAL CHECK OPTION');
2453
+ } else if (node.withCheckOption === 'CASCADED_CHECK_OPTION') {
2454
+ output.push('WITH CASCADED CHECK OPTION');
2455
+ }
2456
+
2355
2457
  return output.join(' ');
2356
2458
  }
2357
2459
 
@@ -2384,8 +2486,19 @@ export default class Deparser {
2384
2486
  }
2385
2487
 
2386
2488
  ['CreateTableAsStmt'](node, context = {}) {
2387
- const output = [];
2388
- output.push('CREATE MATERIALIZED VIEW');
2489
+ const output = ['CREATE'];
2490
+ const relpersistence = dotty.get(node, 'into.rel.relpersistence');
2491
+
2492
+ if (node.relkind === 'OBJECT_MATVIEW') {
2493
+ output.push('MATERIALIZED VIEW');
2494
+ } else if (relpersistence !== 't') {
2495
+ output.push('TABLE');
2496
+
2497
+ if (node.if_not_exists) {
2498
+ output.push('IF NOT EXISTS');
2499
+ }
2500
+ }
2501
+
2389
2502
  output.push(this.IntoClause(node.into, context));
2390
2503
  output.push('AS');
2391
2504
  output.push(this.deparse(node.query, context));
@@ -2549,7 +2662,7 @@ export default class Deparser {
2549
2662
  output.push(this.list(node.tableElts, `,${NEWLINE_CHAR}`, TAB_CHAR, context));
2550
2663
  output.push(`${NEWLINE_CHAR})`);
2551
2664
 
2552
- if (relpersistence === 'p' && node.hasOwnProperty('inhRelations')) {
2665
+ if (node.hasOwnProperty('inhRelations')) {
2553
2666
  output.push('INHERITS');
2554
2667
  output.push('(');
2555
2668
  output.push(this.list(node.inhRelations, ', ', '', context));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgsql-deparser",
3
- "version": "13.3.10",
3
+ "version": "13.3.13",
4
4
  "description": "PostgreSQL AST Deparser",
5
5
  "author": "Dan Lynch <pyramation@gmail.com>",
6
6
  "homepage": "https://github.com/pyramation/pgsql-parser",
@@ -65,7 +65,7 @@
65
65
  "eslint-plugin-prettier": "^3.1.2",
66
66
  "glob": "7.1.6",
67
67
  "jest": "^25.1.0",
68
- "pgsql-parser": "^13.3.10",
68
+ "pgsql-parser": "^13.3.13",
69
69
  "prettier": "^2.1.2",
70
70
  "regenerator-runtime": "^0.13.2"
71
71
  },
@@ -73,7 +73,7 @@
73
73
  "@babel/runtime": "^7.11.2",
74
74
  "dotty": "^0.1.0",
75
75
  "lodash": "^4.17.20",
76
- "pgsql-enums": "^13.1.2"
76
+ "pgsql-enums": "^13.1.3"
77
77
  },
78
- "gitHead": "330bf9929afa01f21e7e19136045bbbf48af7e98"
78
+ "gitHead": "6161588d5b59842d0b5281e8819ddf363a3e3aea"
79
79
  }