pgsql-deparser 17.12.1 → 17.13.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.
@@ -1,53 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.QuoteUtils = void 0;
4
- const RESERVED_WORDS = new Set([
5
- 'all', 'analyse', 'analyze', 'and', 'any', 'array', 'as', 'asc', 'asymmetric',
6
- 'authorization', 'binary', 'both', 'case', 'cast', 'check', 'collate', 'collation',
7
- 'column', 'concurrently', 'constraint', 'create', 'cross', 'current_catalog',
8
- 'current_date', 'current_role', 'current_schema', 'current_time', 'current_timestamp',
9
- 'current_user', 'default', 'deferrable', 'desc', 'distinct', 'do', 'else', 'end',
10
- 'except', 'false', 'fetch', 'for', 'foreign', 'freeze', 'from', 'full', 'grant',
11
- 'group', 'having', 'ilike', 'in', 'initially', 'inner', 'intersect', 'into', 'is',
12
- 'isnull', 'join', 'lateral', 'leading', 'left', 'like', 'limit', 'localtime',
13
- 'localtimestamp', 'natural', 'not', 'notnull', 'null', 'offset', 'on', 'only',
14
- 'or', 'order', 'outer', 'overlaps', 'placing', 'primary', 'references', 'returning',
15
- 'right', 'select', 'session_user', 'similar', 'some', 'symmetric', 'table', 'tablesample',
16
- 'then', 'to', 'trailing', 'true', 'union', 'unique', 'user', 'using', 'variadic',
17
- 'verbose', 'when', 'where', 'window', 'with'
18
- ]);
4
+ const kwlist_1 = require("../kwlist");
19
5
  class QuoteUtils {
20
- static needsQuotes(value) {
21
- if (!value || typeof value !== 'string') {
22
- return false;
23
- }
24
- const lowerValue = value.toLowerCase();
25
- if (RESERVED_WORDS.has(lowerValue)) {
26
- return true;
27
- }
28
- if (!/^[a-z_][a-z0-9_$]*$/i.test(value)) {
29
- return true;
30
- }
31
- if (value !== value.toLowerCase()) {
32
- return true;
33
- }
34
- return false;
35
- }
36
- static quote(value) {
37
- if (value == null) {
38
- return null;
39
- }
40
- if (Array.isArray(value)) {
41
- return value.map(v => this.quote(v));
42
- }
43
- if (typeof value !== 'string') {
44
- return value;
45
- }
46
- if (this.needsQuotes(value)) {
47
- return `"${value}"`;
48
- }
49
- return value;
50
- }
51
6
  static escape(literal) {
52
7
  return `'${literal.replace(/'/g, "''")}'`;
53
8
  }
@@ -81,5 +36,81 @@ class QuoteUtils {
81
36
  // unless it's a raw \x... bytea-style literal.
82
37
  return !/^\\x[0-9a-fA-F]+$/i.test(value) && value.includes('\\');
83
38
  }
39
+ /**
40
+ * Quote an identifier only if needed
41
+ *
42
+ * This is a TypeScript port of PostgreSQL's quote_identifier() function from ruleutils.c
43
+ * https://github.com/postgres/postgres/blob/fab5cd3dd1323f9e66efeb676c4bb212ff340204/src/backend/utils/adt/ruleutils.c#L13055-L13137
44
+ *
45
+ * Can avoid quoting if ident starts with a lowercase letter or underscore
46
+ * and contains only lowercase letters, digits, and underscores, *and* is
47
+ * not any SQL keyword. Otherwise, supply quotes.
48
+ *
49
+ * When quotes are needed, embedded double quotes are properly escaped as "".
50
+ */
51
+ static quoteIdentifier(ident) {
52
+ if (!ident)
53
+ return ident;
54
+ let nquotes = 0;
55
+ let safe = true;
56
+ // Check first character: must be lowercase letter or underscore
57
+ const firstChar = ident[0];
58
+ if (!((firstChar >= 'a' && firstChar <= 'z') || firstChar === '_')) {
59
+ safe = false;
60
+ }
61
+ // Check all characters
62
+ for (let i = 0; i < ident.length; i++) {
63
+ const ch = ident[i];
64
+ if ((ch >= 'a' && ch <= 'z') ||
65
+ (ch >= '0' && ch <= '9') ||
66
+ (ch === '_')) {
67
+ // okay
68
+ }
69
+ else {
70
+ safe = false;
71
+ if (ch === '"') {
72
+ nquotes++;
73
+ }
74
+ }
75
+ }
76
+ if (safe) {
77
+ // Check for keyword. We quote keywords except for unreserved ones.
78
+ // (In some cases we could avoid quoting a col_name or type_func_name
79
+ // keyword, but it seems much harder than it's worth to tell that.)
80
+ const kwKind = (0, kwlist_1.keywordKindOf)(ident);
81
+ if (kwKind !== 'NO_KEYWORD' && kwKind !== 'UNRESERVED_KEYWORD') {
82
+ safe = false;
83
+ }
84
+ }
85
+ if (safe) {
86
+ return ident; // no change needed
87
+ }
88
+ // Build quoted identifier with escaped embedded quotes
89
+ let result = '"';
90
+ for (let i = 0; i < ident.length; i++) {
91
+ const ch = ident[i];
92
+ if (ch === '"') {
93
+ result += '"'; // escape " as ""
94
+ }
95
+ result += ch;
96
+ }
97
+ result += '"';
98
+ return result;
99
+ }
100
+ /**
101
+ * Quote a possibly-qualified identifier
102
+ *
103
+ * This is a TypeScript port of PostgreSQL's quote_qualified_identifier() function from ruleutils.c
104
+ * https://github.com/postgres/postgres/blob/fab5cd3dd1323f9e66efeb676c4bb212ff340204/src/backend/utils/adt/ruleutils.c#L13139-L13156
105
+ *
106
+ * Return a name of the form qualifier.ident, or just ident if qualifier
107
+ * is null/undefined, quoting each component if necessary.
108
+ */
109
+ static quoteQualifiedIdentifier(qualifier, ident) {
110
+ if (qualifier) {
111
+ return `${QuoteUtils.quoteIdentifier(qualifier)}.${QuoteUtils.quoteIdentifier(ident)}`;
112
+ }
113
+ return QuoteUtils.quoteIdentifier(ident);
114
+ }
84
115
  }
85
116
  exports.QuoteUtils = QuoteUtils;