@jrrd/postgresjs 0.0.4
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/dist/index.js +1735 -0
- package/package.json +14 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1735 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var pg = require('pg');
|
|
4
|
+
|
|
5
|
+
class ColumnLike {
|
|
6
|
+
#alias
|
|
7
|
+
#cast
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
this.#alias = undefined;
|
|
11
|
+
this.#cast = undefined;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
as(name) {
|
|
15
|
+
this.#alias = name;
|
|
16
|
+
|
|
17
|
+
return this
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
cast(type) {
|
|
21
|
+
this.#cast = type;
|
|
22
|
+
|
|
23
|
+
return this
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
toString() {
|
|
27
|
+
return (this.#cast ? `::${this.#cast}` : '') + (this.#alias ? ` AS "${this.#alias}"` : '')
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class SqlColumn extends ColumnLike {
|
|
32
|
+
#name
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {string} name
|
|
36
|
+
*/
|
|
37
|
+
constructor(name) {
|
|
38
|
+
super();
|
|
39
|
+
this.#name = name;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
toString() {
|
|
44
|
+
return this.#name.split('.').map(token => `"${token}"`).join('.') + super.toString()
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
class SqlCase extends ColumnLike {
|
|
49
|
+
#caseWhen = []
|
|
50
|
+
#caseElse
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {ConditionLike} condition
|
|
54
|
+
* @param {*} value
|
|
55
|
+
*/
|
|
56
|
+
when(condition, value) {
|
|
57
|
+
this.#caseWhen.push([condition, typeof value === 'string' ? new SqlColumn(value) : value]);
|
|
58
|
+
|
|
59
|
+
return this
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
else(value) {
|
|
63
|
+
this.#caseElse = typeof value === 'string' ? new SqlColumn(value) : value;
|
|
64
|
+
|
|
65
|
+
return this
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
toString() {
|
|
69
|
+
return `${this.#caseWhen.map(([condition, value]) => `WHEN ${condition} THEN ${value}`).join('\n')}` +
|
|
70
|
+
`\n${this.#caseElse}` +
|
|
71
|
+
`\nEND${super.toString()}`
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
class SqlCoalesce extends ColumnLike {
|
|
76
|
+
#left
|
|
77
|
+
#right
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {ColumnLike} left
|
|
81
|
+
* @param {ColumnLike} right
|
|
82
|
+
*/
|
|
83
|
+
constructor(left, right) {
|
|
84
|
+
super();
|
|
85
|
+
this.#left = typeof left === 'string' ? new SqlColumn(left) : left;
|
|
86
|
+
this.#right = typeof right === 'string' ? new SqlColumn(right) : right;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
toString() {
|
|
90
|
+
return `COALESCE(${this.#left}, ${this.#right})${super.toString()}`
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
class SqlConcat extends ColumnLike {
|
|
95
|
+
#columns
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {...ColumnLike} columns
|
|
99
|
+
*/
|
|
100
|
+
constructor(...columns) {
|
|
101
|
+
super();
|
|
102
|
+
this.#columns = columns.map(column => typeof column === 'string' ? new SqlColumn(column) : column);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
toString() {
|
|
106
|
+
return `CONCAT(${this.#columns.join(', ')})${super.toString()}`
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
class SqlDateInterval extends ColumnLike {
|
|
111
|
+
#unit
|
|
112
|
+
#value
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @param {number} value
|
|
116
|
+
* @param {string} unit
|
|
117
|
+
*/
|
|
118
|
+
constructor(value, unit) {
|
|
119
|
+
this.#value = value;
|
|
120
|
+
this.#unit = unit;
|
|
121
|
+
}
|
|
122
|
+
toString() {
|
|
123
|
+
return `${this.#value > 0 ? '+' : '-'} interval '${Math.abs(this.#value)} ${this.#unit}${Math.abs(this.#value) === 1 ? '' : 's'}'`
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
class SqlDatePart extends ColumnLike {
|
|
128
|
+
#part
|
|
129
|
+
#column
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @param {string} part
|
|
133
|
+
* @param {ColumnLike} column
|
|
134
|
+
*/
|
|
135
|
+
constructor(part, column) {
|
|
136
|
+
super();
|
|
137
|
+
this.#part = part;
|
|
138
|
+
this.#column = typeof column === 'string' ? new SqlColumn(column) : column;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
toString() {
|
|
142
|
+
return `date_part('${this.#part}', ${this.#column})${super.toString()}`
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
class SqlDateTrunc extends ColumnLike {
|
|
147
|
+
#part
|
|
148
|
+
#column
|
|
149
|
+
|
|
150
|
+
constructor(part, column) {
|
|
151
|
+
super();
|
|
152
|
+
this.#part = part;
|
|
153
|
+
this.#column = typeof column === 'string' ? new SqlColumn(column) : column;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
toString() {
|
|
157
|
+
return `date_trunc('${this.#part}', ${this.#column})${super.toString()}`
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
class SqlString extends ColumnLike {
|
|
162
|
+
#value
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* @param {string} value
|
|
166
|
+
*/
|
|
167
|
+
constructor(value) {
|
|
168
|
+
super();
|
|
169
|
+
this.#value = value;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
toString() {
|
|
173
|
+
return `'${this.#value}'${super.toString()}`
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
class SqlLPad extends ColumnLike {
|
|
178
|
+
#column
|
|
179
|
+
#length
|
|
180
|
+
#fill
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @param {ColumnLike} column
|
|
184
|
+
* @param {number} length
|
|
185
|
+
* @param {string} fill
|
|
186
|
+
*/
|
|
187
|
+
constructor(column ,length, fill) {
|
|
188
|
+
super();
|
|
189
|
+
this.#column = typeof column === 'string' ? new SqlColumn(column) : column;
|
|
190
|
+
this.#length = length;
|
|
191
|
+
this.#fill = typeof fill === 'string' ? new SqlString(fill) : fill;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
toString() {
|
|
195
|
+
return `lpad(${this.#column}, ${this.#length}, ${this.#fill})${super.toString()}`
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
class SqlMax extends ColumnLike {
|
|
200
|
+
#column
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* @param {ColumnLike} column
|
|
204
|
+
*/
|
|
205
|
+
constructor(column) {
|
|
206
|
+
super();
|
|
207
|
+
this.#column = typeof column === 'string' ? new SqlColumn(column) : column;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
toString() {
|
|
211
|
+
return `max(${this.#column})${super.toString()}`
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
class SqlParameter extends ColumnLike {
|
|
216
|
+
#number
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* @param {number} number
|
|
220
|
+
*/
|
|
221
|
+
constructor(number) {
|
|
222
|
+
super();
|
|
223
|
+
this.#number = number;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
toString() {
|
|
227
|
+
return `$${this.#number}${super.toString()}`
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
class SqlRPad extends ColumnLike {
|
|
232
|
+
#column
|
|
233
|
+
#length
|
|
234
|
+
#fill
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @param {ColumnLike} column
|
|
238
|
+
* @param {number} length
|
|
239
|
+
* @param {string} fill
|
|
240
|
+
*/
|
|
241
|
+
constructor(column ,length, fill) {
|
|
242
|
+
super();
|
|
243
|
+
this.#column = typeof column === 'string' ? new SqlColumn(column) : column;
|
|
244
|
+
this.#length = length;
|
|
245
|
+
this.#fill = typeof fill === 'string' ? new SqlString(fill) : fill;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
toString() {
|
|
249
|
+
return `rpad(${this.#column}, ${this.#length}, ${this.#fill})${super.toString()}`
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
class SqlStringAgg extends ColumnLike {
|
|
254
|
+
#column
|
|
255
|
+
#separator
|
|
256
|
+
#distinct
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @param {ColumnLike} column
|
|
260
|
+
* @param {string} separator
|
|
261
|
+
* @param {boolean} distinct
|
|
262
|
+
*/
|
|
263
|
+
constructor(column, separator, distinct=true) {
|
|
264
|
+
super();
|
|
265
|
+
this.#column = typeof column === 'string' ? new SqlColumn(column) : column;
|
|
266
|
+
this.#separator = typeof separator === 'string' ? new SqlString(separator) : separator;
|
|
267
|
+
this.#distinct = distinct;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
toString() {
|
|
271
|
+
return `string_agg(${this.#distinct ? 'DISTINCT ' : ''}${this.#column}, ${this.#separator})${super.toString()}`
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
class SqlStringToArray extends ColumnLike {
|
|
276
|
+
#column
|
|
277
|
+
#separator
|
|
278
|
+
#replace
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* @param {ColumnLike} column
|
|
282
|
+
* @param {string} separator
|
|
283
|
+
* @param {string=} replace
|
|
284
|
+
*/
|
|
285
|
+
constructor(column, separator, replace) {
|
|
286
|
+
this.#column = typeof column === 'string' ? new SqlColumn(column) : column;
|
|
287
|
+
this.#separator = typeof separator === 'string' ? new SqlString(separator) : separator;
|
|
288
|
+
this.#replace = replace;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
toString() {
|
|
292
|
+
return `string_to_array(${this.#column}, ${this.#separator}${this.#replace ? `, ${this.replace}` : ''})${super.toString()}`
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
class SqlSubString extends ColumnLike {
|
|
297
|
+
#column
|
|
298
|
+
#pattern
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* @param {ColumnLike} column
|
|
302
|
+
* @param {string} pattern
|
|
303
|
+
*/
|
|
304
|
+
constructor(column, pattern) {
|
|
305
|
+
super();
|
|
306
|
+
this.#column = typeof column === 'string' ? new SqlColumn(column) : column;
|
|
307
|
+
this.#pattern = typeof pattern === 'string' ? new SqlString(pattern) : pattern;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
toString() {
|
|
311
|
+
return `substring(${this.#column}, ${this.#pattern})${super.toString()}`
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
class ConditionLike {
|
|
316
|
+
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
class SqlAnd extends ConditionLike {
|
|
320
|
+
#conditions
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* @param {...ConditionLike} conditions
|
|
324
|
+
*/
|
|
325
|
+
constructor(...conditions) {
|
|
326
|
+
super();
|
|
327
|
+
this.#conditions = conditions;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
toString() {
|
|
331
|
+
return this.#conditions.map(condition => `(${condition})`).join(' AND ')
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
class SqlEqual extends ConditionLike {
|
|
336
|
+
#left
|
|
337
|
+
#right
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* @param {ColumnLike} left
|
|
341
|
+
* @param {ColumnLike} right
|
|
342
|
+
*/
|
|
343
|
+
constructor(left, right) {
|
|
344
|
+
super();
|
|
345
|
+
this.#left = typeof left === 'string' ? new SqlColumn(left) : left;
|
|
346
|
+
this.#right = typeof right === 'string' ? new SqlColumn(right) : right;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
toString() {
|
|
350
|
+
return `${this.#left} = ${this.#right}`
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
class SqlGreaterThan extends ConditionLike {
|
|
355
|
+
#left
|
|
356
|
+
#right
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* @param {ColumnLike} left
|
|
360
|
+
* @param {ColumnLike} right
|
|
361
|
+
*/
|
|
362
|
+
constructor(left, right) {
|
|
363
|
+
super();
|
|
364
|
+
this.#left = typeof left === 'string' ? new SqlColumn(left) : left;
|
|
365
|
+
this.#right = typeof right === 'string' ? new SqlColumn(right) : right;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
toString() {
|
|
369
|
+
return `${this.#left} > ${this.#right}`
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
class SqlGreaterThanOrEqual extends ConditionLike {
|
|
374
|
+
#left
|
|
375
|
+
#right
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* @param {ColumnLike} left
|
|
379
|
+
* @param {ColumnLike} right
|
|
380
|
+
*/
|
|
381
|
+
constructor(left, right) {
|
|
382
|
+
super();
|
|
383
|
+
this.#left = typeof left === 'string' ? new SqlColumn(left) : left;
|
|
384
|
+
this.#right = typeof right === 'string' ? new SqlColumn(right) : right;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
toString() {
|
|
388
|
+
return `${this.#left} >= ${this.#right}`
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
class SqlILike extends ConditionLike {
|
|
393
|
+
#left
|
|
394
|
+
#right
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* @param {ColumnLike} left
|
|
398
|
+
* @param {ColumnLike} right
|
|
399
|
+
*/
|
|
400
|
+
constructor(left, right) {
|
|
401
|
+
super();
|
|
402
|
+
this.#left = typeof left === 'string' ? new SqlColumn(left) : left;
|
|
403
|
+
this.#right = typeof right === 'string' ? new SqlColumn(right) : right;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
toString() {
|
|
407
|
+
return `${this.#left} ILIKE ${this.#right}`
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
class SqlIsNotNull extends ConditionLike {
|
|
412
|
+
#column
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* @param {ColumnLike} column
|
|
416
|
+
*/
|
|
417
|
+
constructor(column) {
|
|
418
|
+
super();
|
|
419
|
+
this.#column = typeof column === 'string' ? new SqlColumn(column) : column;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
toString() {
|
|
423
|
+
return `${this.#column} IS NOT NULL`
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
class SqlIsNull extends ConditionLike {
|
|
428
|
+
#column
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* @param {ColumnLike} column
|
|
432
|
+
*/
|
|
433
|
+
constructor(column) {
|
|
434
|
+
super();
|
|
435
|
+
this.#column = typeof column === 'string' ? new SqlColumn(column) : column;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
toString() {
|
|
439
|
+
return `${this.#column} IS NULL`
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
class SqlLessThan extends ConditionLike {
|
|
444
|
+
#left
|
|
445
|
+
#right
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* @param {ColumnLike} left
|
|
449
|
+
* @param {ColumnLike} right
|
|
450
|
+
*/
|
|
451
|
+
constructor(left, right) {
|
|
452
|
+
this.#left = typeof left === 'string' ? new SqlColumn(left) : left;
|
|
453
|
+
this.#right = typeof right === 'string' ? new SqlColumn(right) : right;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
toString() {
|
|
457
|
+
return `${this.#left} < ${this.#right}`
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
class SqlLessThanOrEqual extends ConditionLike {
|
|
462
|
+
#left
|
|
463
|
+
#right
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* @param {ColumnLike} left
|
|
467
|
+
* @param {ColumnLike} right
|
|
468
|
+
*/
|
|
469
|
+
constructor(left, right) {
|
|
470
|
+
this.#left = typeof left === 'string' ? new SqlColumn(left) : left;
|
|
471
|
+
this.#right = typeof right === 'string' ? new SqlColumn(right) : right;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
toString() {
|
|
475
|
+
return `${this.#left} <= ${this.#right}`
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
class SqlLike extends ConditionLike {
|
|
480
|
+
#left
|
|
481
|
+
#right
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* @param {ColumnLike} left
|
|
485
|
+
* @param {ColumnLike} right
|
|
486
|
+
*/
|
|
487
|
+
constructor(left, right) {
|
|
488
|
+
this.#left = typeof left === 'string' ? new SqlColumn(left) : left;
|
|
489
|
+
this.#right = typeof right === 'string' ? new SqlColumn(right) : right;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
toString() {
|
|
493
|
+
return `${this.#left} LIKE ${this.#right}`
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
class SqlMatch extends ConditionLike {
|
|
498
|
+
#left
|
|
499
|
+
#right
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* @param {ColumnLike} left
|
|
503
|
+
* @param {ColumnLike} right
|
|
504
|
+
*/
|
|
505
|
+
constructor(left, right) {
|
|
506
|
+
this.#left = typeof left === 'string' ? new SqlColumn(left) : left;
|
|
507
|
+
this.#right = typeof right === 'string' ? new SqlColumn(right) : right;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
toString() {
|
|
511
|
+
return `${this.#left} ~ ${this.#right}`
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
class SqlNotEqual extends ConditionLike {
|
|
516
|
+
#left
|
|
517
|
+
#right
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* @param {ColumnLike} left
|
|
521
|
+
* @param {ColumnLike} right
|
|
522
|
+
*/
|
|
523
|
+
constructor(left, right) {
|
|
524
|
+
super();
|
|
525
|
+
this.#left = typeof left === 'string' ? new SqlColumn(left) : left;
|
|
526
|
+
this.#right = typeof right === 'string' ? new SqlColumn(right) : right;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
toString() {
|
|
530
|
+
return `${this.#left} != ${this.#right}`
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
class SqlNotILike extends ConditionLike {
|
|
535
|
+
#left
|
|
536
|
+
#right
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* @param {ColumnLike} left
|
|
540
|
+
* @param {ColumnLike} right
|
|
541
|
+
*/
|
|
542
|
+
constructor(left, right) {
|
|
543
|
+
this.#left = typeof left === 'string' ? new SqlColumn(left) : left;
|
|
544
|
+
this.#right = typeof right === 'string' ? new SqlColumn(right) : right;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
toString() {
|
|
548
|
+
return `${this.#left} NOT ILIKE ${this.#right}`
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
class SqlNotLike extends ConditionLike {
|
|
553
|
+
#left
|
|
554
|
+
#right
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* @param {ColumnLike} left
|
|
558
|
+
* @param {ColumnLike} right
|
|
559
|
+
*/
|
|
560
|
+
constructor(left, right) {
|
|
561
|
+
this.#left = typeof left === 'string' ? new SqlColumn(left) : left;
|
|
562
|
+
this.#right = typeof right === 'string' ? new SqlColumn(right) : right;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
toString() {
|
|
566
|
+
return `${this.#left} NOT LIKE ${this.#right}`
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
class SqlNotMatch extends ConditionLike {
|
|
571
|
+
#left
|
|
572
|
+
#right
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* @param {ColumnLike} left
|
|
576
|
+
* @param {ColumnLike} right
|
|
577
|
+
*/
|
|
578
|
+
constructor(left, right) {
|
|
579
|
+
this.#left = typeof left === 'string' ? new SqlColumn(left) : left;
|
|
580
|
+
this.#right = typeof right === 'string' ? new SqlColumn(right) : right;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
toString() {
|
|
584
|
+
return `${this.#left} !~ ${this.#right}`
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
class SqlOr extends ConditionLike {
|
|
589
|
+
#conditions
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* @param {...ConditionLike} conditions
|
|
593
|
+
*/
|
|
594
|
+
constructor(...conditions) {
|
|
595
|
+
this.#conditions = conditions;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
toString() {
|
|
599
|
+
return this.#conditions.map(condition => `(${condition})`).join(' OR ')
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
class TableLike {
|
|
604
|
+
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
class SqlTable extends TableLike {
|
|
608
|
+
#name
|
|
609
|
+
|
|
610
|
+
constructor(name) {
|
|
611
|
+
super();
|
|
612
|
+
this.#name = name;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
toString() {
|
|
616
|
+
return `"${this.#name}"`
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
class SqlQuery {
|
|
621
|
+
/**
|
|
622
|
+
* @param {PostgreSQL} pgsql
|
|
623
|
+
*/
|
|
624
|
+
constructor(pgsql) {
|
|
625
|
+
/**
|
|
626
|
+
* @type {PostgreSQL}
|
|
627
|
+
*/
|
|
628
|
+
this.pgsql = pgsql;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
async invoke(...values) {
|
|
632
|
+
const query = this.toString();
|
|
633
|
+
return await this.pgsql.pool.query(query, values)
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
class SqlInsert extends SqlQuery {
|
|
638
|
+
#columns
|
|
639
|
+
#into
|
|
640
|
+
#values
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* @param {PostgreSQL} pgsql
|
|
644
|
+
* @param {...ColumnLike} columns
|
|
645
|
+
*/
|
|
646
|
+
constructor(pgsql, ...columns) {
|
|
647
|
+
super(pgsql);
|
|
648
|
+
|
|
649
|
+
this.#columns = columns.map(column => typeof column === 'string' ? new SqlColumn(column) : column);
|
|
650
|
+
this.#values = [];
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* @param {string} table
|
|
655
|
+
*/
|
|
656
|
+
into(table) {
|
|
657
|
+
this.#into = typeof table === 'string' ? new SqlTable(table) : table;
|
|
658
|
+
|
|
659
|
+
return this
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
values(...values) {
|
|
663
|
+
this.#values = values;
|
|
664
|
+
|
|
665
|
+
return this
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
toString() {
|
|
669
|
+
return `INSERT INTO ${this.#into} (${this.#columns.join(', ')}) VALUES (${this.#values.join(', ')})`
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
class SqlFrom {
|
|
674
|
+
#table
|
|
675
|
+
#alias
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* @param {TableLike} table
|
|
679
|
+
* @param {string} alias
|
|
680
|
+
*/
|
|
681
|
+
constructor(table, alias) {
|
|
682
|
+
this.#table = typeof table === 'string' ? new SqlTable(table) : table;
|
|
683
|
+
this.#alias = alias;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
toString() {
|
|
687
|
+
return this.#alias ? `FROM (${this.#table}) AS ${this.#alias}` : `FROM ${this.#table}`
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
class SqlGroupBy {
|
|
692
|
+
#columns
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* @param {...ColumnLike} columns
|
|
696
|
+
*/
|
|
697
|
+
constructor(...columns) {
|
|
698
|
+
this.#columns = columns.map(column => typeof column === 'string' ? new SqlColumn(column) : column);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
toString() {
|
|
702
|
+
return `GROUP BY ${this.#columns.join(', ')}`
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
class SqlJoin {
|
|
707
|
+
#table
|
|
708
|
+
#condition
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* @param {TableLike} table
|
|
712
|
+
* @param {ConditionLike} condition
|
|
713
|
+
*/
|
|
714
|
+
constructor(table, condition) {
|
|
715
|
+
this.#table = typeof table === 'string' ? new SqlTable(table) : table;
|
|
716
|
+
this.#condition = condition;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
toString() {
|
|
720
|
+
return `JOIN ${this.#table} ON ${this.#condition}`
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
class SqlJoinInnerLateral {
|
|
725
|
+
#table
|
|
726
|
+
#alias
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* @param {TableLike} table
|
|
730
|
+
* @param {string} alias
|
|
731
|
+
*/
|
|
732
|
+
constructor(table, alias) {
|
|
733
|
+
this.#table = typeof table === 'string' ? new SqlTable(table) : table;
|
|
734
|
+
this.#alias = alias;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
toString() {
|
|
738
|
+
return `INNER JOIN LATERAL (\n${this.#table}\n) ${this.#alias} ON TRUE`
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
class SqlJoinLeft {
|
|
743
|
+
#table
|
|
744
|
+
#condition
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* @param {TableLike} table
|
|
748
|
+
* @param {ConditionLike} condition
|
|
749
|
+
*/
|
|
750
|
+
constructor(table, condition) {
|
|
751
|
+
this.#table = typeof table === 'string' ? new SqlTable(table) : table;
|
|
752
|
+
this.#condition = condition;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
toString() {
|
|
756
|
+
return `LEFT JOIN ${this.#table} ON ${this.#condition}`
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
class SqlJoinLeftLateral {
|
|
761
|
+
#table
|
|
762
|
+
#alias
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* @param {TableLike} table
|
|
766
|
+
* @param {string} alias
|
|
767
|
+
*/
|
|
768
|
+
constructor(table, alias) {
|
|
769
|
+
this.#table = typeof table === 'string' ? new SqlTable(table) : table;
|
|
770
|
+
this.#alias = alias;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
toString() {
|
|
774
|
+
return `LEFT JOIN LATERAL (\n${this.#table}\n) ${this.#alias} ON TRUE`
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
class SqlLimit {
|
|
779
|
+
#count
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* @param {number} count
|
|
783
|
+
*/
|
|
784
|
+
constructor(count) {
|
|
785
|
+
this.count = count;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
toString() {
|
|
789
|
+
return `LIMIT ${this.#count}`
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
class SqlOrderBy {
|
|
794
|
+
#columns
|
|
795
|
+
|
|
796
|
+
/**
|
|
797
|
+
* @param {...ColumnLike} columns
|
|
798
|
+
*/
|
|
799
|
+
constructor(...columns) {
|
|
800
|
+
this.#columns = columns.map(column => typeof column === 'string' ? new SqlColumn(column) : column);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
toString() {
|
|
804
|
+
return `ORDER BY ${this.#columns.join(', ')}`
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
class SqlWhere {
|
|
809
|
+
#condition
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* @param {ConditionLike} condition
|
|
813
|
+
*/
|
|
814
|
+
constructor(condition) {
|
|
815
|
+
this.#condition = condition;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
toString() {
|
|
819
|
+
return `WHERE ${this.#condition}`
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
class SqlSelect extends SqlQuery {
|
|
824
|
+
/**
|
|
825
|
+
* @type {ColumnLike[]}
|
|
826
|
+
*/
|
|
827
|
+
#columns
|
|
828
|
+
|
|
829
|
+
/**
|
|
830
|
+
* @type {SqlFrom}
|
|
831
|
+
*/
|
|
832
|
+
#from
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* @type {SqlGroupBy}
|
|
836
|
+
*/
|
|
837
|
+
#groupby
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* @type {SqlJoin[]}
|
|
841
|
+
*/
|
|
842
|
+
#join
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* @type {SqlLimit}
|
|
846
|
+
*/
|
|
847
|
+
#limit
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* @type {SqlOrderBy}
|
|
851
|
+
*/
|
|
852
|
+
#orderby
|
|
853
|
+
|
|
854
|
+
/**
|
|
855
|
+
* @type {SqlWhere}
|
|
856
|
+
*/
|
|
857
|
+
#where
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* @param {PostgreSQL} pgsql
|
|
861
|
+
* @param {...ColumnLike} columns
|
|
862
|
+
*/
|
|
863
|
+
constructor(pgsql, ...columns) {
|
|
864
|
+
super(pgsql);
|
|
865
|
+
|
|
866
|
+
this.#columns = columns.map(column => typeof column === 'string' ? new SqlColumn(column) : column);
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* @param {TableLike} table
|
|
871
|
+
* @param {string} alias
|
|
872
|
+
*/
|
|
873
|
+
from(table, alias) {
|
|
874
|
+
this.#from = new SqlFrom(table, alias);
|
|
875
|
+
|
|
876
|
+
return this
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
* @param {...ColumnLike} columns
|
|
881
|
+
*/
|
|
882
|
+
groupby(...columns) {
|
|
883
|
+
this.#groupby = new SqlGroupBy(...columns);
|
|
884
|
+
|
|
885
|
+
return this
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
/**
|
|
889
|
+
* @param {TableLike} table
|
|
890
|
+
* @param {SqlToken} condition
|
|
891
|
+
*/
|
|
892
|
+
join(table, condition) {
|
|
893
|
+
if (!this.#join) {
|
|
894
|
+
this.#join = [];
|
|
895
|
+
}
|
|
896
|
+
this.#join.push(new SqlJoin(table, condition));
|
|
897
|
+
|
|
898
|
+
return this
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* @param {TableLike} table
|
|
904
|
+
* @param {string} alias
|
|
905
|
+
*/
|
|
906
|
+
joinInnerLateral(table, alias) {
|
|
907
|
+
if (!this.#join) {
|
|
908
|
+
this.#join = [];
|
|
909
|
+
}
|
|
910
|
+
this.#join.push(new SqlJoinInnerLateral(table, alias));
|
|
911
|
+
|
|
912
|
+
return this
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* @param {TableLike} table
|
|
917
|
+
* @param {SqlToken} condition
|
|
918
|
+
*/
|
|
919
|
+
joinLeft(table, condition) {
|
|
920
|
+
if (!this.#join) {
|
|
921
|
+
this.#join = [];
|
|
922
|
+
}
|
|
923
|
+
this.#join.push(new SqlJoinLeft(table, condition));
|
|
924
|
+
|
|
925
|
+
return this
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/**
|
|
929
|
+
* @param {TableLike} table
|
|
930
|
+
* @param {string} alias
|
|
931
|
+
*/
|
|
932
|
+
joinLeftLateral(table, alias) {
|
|
933
|
+
if (!this.#join) {
|
|
934
|
+
this.#join = [];
|
|
935
|
+
}
|
|
936
|
+
this.#join.push(new SqlJoinLeftLateral(table, alias));
|
|
937
|
+
|
|
938
|
+
return this
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
/**
|
|
942
|
+
* @param {number} count
|
|
943
|
+
*/
|
|
944
|
+
limit(count) {
|
|
945
|
+
this.#limit = new SqlLimit(count);
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
/**
|
|
949
|
+
* @param {...ColumnLike} columns
|
|
950
|
+
*/
|
|
951
|
+
orderby(...columns) {
|
|
952
|
+
this.orderby = new SqlOrderBy(...columns);
|
|
953
|
+
|
|
954
|
+
return this
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
/**
|
|
958
|
+
* @param {SqlToken} condition
|
|
959
|
+
*/
|
|
960
|
+
where(condition) {
|
|
961
|
+
this.#where = new SqlWhere(condition);
|
|
962
|
+
|
|
963
|
+
return this
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
toString() {
|
|
967
|
+
return `SELECT ${this.#columns.length === 0 ? '*' : this.#columns.join(',\n')}` +
|
|
968
|
+
`\n${this.#from}` +
|
|
969
|
+
(this.#join ? `\n${this.#join.join('\n')}` : '') +
|
|
970
|
+
(this.#where ? `\n${this.#where}` : '') +
|
|
971
|
+
(this.#orderby ? `\n${this.#orderby}` : '') +
|
|
972
|
+
(this.#groupby ? `\n${this.#groupby}` : '') +
|
|
973
|
+
(this.#limit ? `\n${this.#limit}` : '')
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
class SqlSelectDistinct extends SqlQuery {
|
|
978
|
+
/**
|
|
979
|
+
* @type {SqlToken[]}
|
|
980
|
+
*/
|
|
981
|
+
#distinct
|
|
982
|
+
|
|
983
|
+
/**
|
|
984
|
+
* @type {SqlToken}
|
|
985
|
+
*/
|
|
986
|
+
#from
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* @type {SqlGroupBy}
|
|
990
|
+
*/
|
|
991
|
+
#groupby
|
|
992
|
+
|
|
993
|
+
/**
|
|
994
|
+
* @type {SqlToken[]}
|
|
995
|
+
*/
|
|
996
|
+
#join
|
|
997
|
+
|
|
998
|
+
/**
|
|
999
|
+
* @type {SqlToken}
|
|
1000
|
+
*/
|
|
1001
|
+
#limit
|
|
1002
|
+
|
|
1003
|
+
/**
|
|
1004
|
+
* @type {SqlToken}
|
|
1005
|
+
*/
|
|
1006
|
+
#where
|
|
1007
|
+
|
|
1008
|
+
/**
|
|
1009
|
+
* @type {SqlToken}
|
|
1010
|
+
*/
|
|
1011
|
+
#orderby
|
|
1012
|
+
|
|
1013
|
+
/**
|
|
1014
|
+
* @param {PostgreSQL} pgsql
|
|
1015
|
+
* @param {...ColumnLike} columns
|
|
1016
|
+
*/
|
|
1017
|
+
constructor(pgsql, ...columns) {
|
|
1018
|
+
super(pgsql);
|
|
1019
|
+
|
|
1020
|
+
this.#distinct = columns.map(column => typeof column === 'string' ? new SqlColumn(column) : column);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/**
|
|
1024
|
+
* @param {TableLike} table
|
|
1025
|
+
* @param {string} alias
|
|
1026
|
+
*/
|
|
1027
|
+
from(table, alias) {
|
|
1028
|
+
this.#from = new SqlFrom(table, alias);
|
|
1029
|
+
|
|
1030
|
+
return this
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
/**
|
|
1034
|
+
* @param {...ColumnLike} columns
|
|
1035
|
+
*/
|
|
1036
|
+
groupby(...columns) {
|
|
1037
|
+
this.#groupby = new SqlGroupBy(...columns);
|
|
1038
|
+
|
|
1039
|
+
return this
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
/**
|
|
1043
|
+
* @param {string|SqlToken} table
|
|
1044
|
+
* @param {SqlToken} condition
|
|
1045
|
+
*/
|
|
1046
|
+
join(table, condition) {
|
|
1047
|
+
if (!this.#join) {
|
|
1048
|
+
this.#join = [];
|
|
1049
|
+
}
|
|
1050
|
+
this.#join.push(new SqlJoin(table, condition));
|
|
1051
|
+
|
|
1052
|
+
return this
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
/**
|
|
1056
|
+
* @param {TableLike} table
|
|
1057
|
+
* @param {string} alias
|
|
1058
|
+
*/
|
|
1059
|
+
joinInnerLateral(table, alias) {
|
|
1060
|
+
if (!this.#join) {
|
|
1061
|
+
this.#join = [];
|
|
1062
|
+
}
|
|
1063
|
+
this.#join.push(new SqlJoinInnerLateral(table, alias));
|
|
1064
|
+
|
|
1065
|
+
return this
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
/**
|
|
1069
|
+
* @param {TableLike} table
|
|
1070
|
+
* @param {SqlToken} condition
|
|
1071
|
+
*/
|
|
1072
|
+
joinLeft(table, condition) {
|
|
1073
|
+
if (!this.#join) {
|
|
1074
|
+
this.#join = [];
|
|
1075
|
+
}
|
|
1076
|
+
this.#join.push(new SqlJoinLeft(table, condition));
|
|
1077
|
+
|
|
1078
|
+
return this
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* @param {TableLike} table
|
|
1083
|
+
* @param {string} alias
|
|
1084
|
+
*/
|
|
1085
|
+
joinLeftLateral(table, alias) {
|
|
1086
|
+
if (!this.#join) {
|
|
1087
|
+
this.#join = [];
|
|
1088
|
+
}
|
|
1089
|
+
this.#join.push(new SqlJoinLeftLateral(table, alias));
|
|
1090
|
+
|
|
1091
|
+
return this
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
/**
|
|
1095
|
+
* @param {number} count
|
|
1096
|
+
*/
|
|
1097
|
+
limit(count) {
|
|
1098
|
+
this.#limit = new SqlLimit(count);
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* @param {...ColumnLike} columns
|
|
1103
|
+
*/
|
|
1104
|
+
orderby(...columns) {
|
|
1105
|
+
this.orderby = new SqlOrderBy(...columns);
|
|
1106
|
+
|
|
1107
|
+
return this
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
* @param {ConditionLike} condition
|
|
1112
|
+
*/
|
|
1113
|
+
where(condition) {
|
|
1114
|
+
this.#where = SqlWhere(condition);
|
|
1115
|
+
|
|
1116
|
+
return this
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
toString() {
|
|
1120
|
+
return `SELECT DISTINCT ${this.#distinct.length === 0 ? '*' : this.#distinct.join(',\n')}` +
|
|
1121
|
+
`\n${this.#from}` +
|
|
1122
|
+
(this.#join ? `\n${this.#join.join('\n')}` : '') +
|
|
1123
|
+
(this.#where ? `\n${this.#where}` : '') +
|
|
1124
|
+
(this.#orderby ? `\n${this.#orderby}` : '') +
|
|
1125
|
+
(this.#groupby ? `\n${this.#groupby}` : '') +
|
|
1126
|
+
(this.#limit ? `\n${this.#limit}` : '')
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
class SqlSelectDistinctOn extends SqlQuery {
|
|
1131
|
+
/**
|
|
1132
|
+
* @type {SqlToken[]}
|
|
1133
|
+
*/
|
|
1134
|
+
#distinct
|
|
1135
|
+
|
|
1136
|
+
/**
|
|
1137
|
+
* @type {SqlToken[]}
|
|
1138
|
+
*/
|
|
1139
|
+
#columns
|
|
1140
|
+
|
|
1141
|
+
/**
|
|
1142
|
+
* @type {SqlToken}
|
|
1143
|
+
*/
|
|
1144
|
+
#from
|
|
1145
|
+
|
|
1146
|
+
/**
|
|
1147
|
+
* @type {SqlGroupBy}
|
|
1148
|
+
*/
|
|
1149
|
+
#groupby
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* @type {SqlToken[]}
|
|
1153
|
+
*/
|
|
1154
|
+
#join
|
|
1155
|
+
|
|
1156
|
+
/**
|
|
1157
|
+
* @type {SqlToken}
|
|
1158
|
+
*/
|
|
1159
|
+
#limit
|
|
1160
|
+
|
|
1161
|
+
/**
|
|
1162
|
+
* @type {SqlToken}
|
|
1163
|
+
*/
|
|
1164
|
+
#orderby
|
|
1165
|
+
|
|
1166
|
+
/**
|
|
1167
|
+
* @type {SqlToken}
|
|
1168
|
+
*/
|
|
1169
|
+
#where
|
|
1170
|
+
|
|
1171
|
+
/**
|
|
1172
|
+
* @param {PostgreSQL} pgsql
|
|
1173
|
+
* @param {...ColumnLike} columns
|
|
1174
|
+
*/
|
|
1175
|
+
constructor(pgsql, ...columns) {
|
|
1176
|
+
super(pgsql);
|
|
1177
|
+
|
|
1178
|
+
this.#distinct = columns.map(column => typeof column === 'string' ? new SqlColumn(column) : column);
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
/**
|
|
1182
|
+
* @param {TableLike} table
|
|
1183
|
+
* @param {string} alias
|
|
1184
|
+
*/
|
|
1185
|
+
from(table, alias) {
|
|
1186
|
+
this.#from = new SqlFrom(table, alias);
|
|
1187
|
+
|
|
1188
|
+
return this
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
/**
|
|
1192
|
+
* @param {...ColumnLike} columns
|
|
1193
|
+
*/
|
|
1194
|
+
groupby(...columns) {
|
|
1195
|
+
this.#groupby = new SqlGroupBy(...columns);
|
|
1196
|
+
|
|
1197
|
+
return this
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
/**
|
|
1201
|
+
* @param {TableLike} table
|
|
1202
|
+
* @param {ConditionLike} condition
|
|
1203
|
+
*/
|
|
1204
|
+
join(table, condition) {
|
|
1205
|
+
if (!this.#join) {
|
|
1206
|
+
this.#join = [];
|
|
1207
|
+
}
|
|
1208
|
+
this.#join.push(new SqlJoin(table, condition));
|
|
1209
|
+
|
|
1210
|
+
return this
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
/**
|
|
1214
|
+
* @param {TableLike} table
|
|
1215
|
+
* @param {string} alias
|
|
1216
|
+
*/
|
|
1217
|
+
joinInnerLateral(table, alias) {
|
|
1218
|
+
if (!this.#join) {
|
|
1219
|
+
this.#join = [];
|
|
1220
|
+
}
|
|
1221
|
+
this.#join.push(new SqlJoinInnerLateral(table, alias));
|
|
1222
|
+
|
|
1223
|
+
return this
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
/**
|
|
1227
|
+
* @param {TableLike} table
|
|
1228
|
+
* @param {SqlToken} condition
|
|
1229
|
+
*/
|
|
1230
|
+
joinLeft(table, condition) {
|
|
1231
|
+
if (!this.#join) {
|
|
1232
|
+
this.#join = [];
|
|
1233
|
+
}
|
|
1234
|
+
this.#join.push(new SqlJoinLeft(table, condition));
|
|
1235
|
+
|
|
1236
|
+
return this
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
/**
|
|
1240
|
+
* @param {TableLike} table
|
|
1241
|
+
* @param {string} alias
|
|
1242
|
+
*/
|
|
1243
|
+
joinLeftLateral(table, alias) {
|
|
1244
|
+
if (!this.#join) {
|
|
1245
|
+
this.#join = [];
|
|
1246
|
+
}
|
|
1247
|
+
this.#join.push(new SqlJoinLeftLateral(table, alias));
|
|
1248
|
+
|
|
1249
|
+
return this
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
/**
|
|
1253
|
+
* @param {number} count
|
|
1254
|
+
*/
|
|
1255
|
+
limit(count) {
|
|
1256
|
+
this.#limit = new SqlLimit(count);
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
/**
|
|
1260
|
+
* @param {...ColumnLike} columns
|
|
1261
|
+
*/
|
|
1262
|
+
orderby(...columns) {
|
|
1263
|
+
this.orderby = new SqlOrderBy(...columns);
|
|
1264
|
+
|
|
1265
|
+
return this
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
/**
|
|
1269
|
+
* @param {...ColumnLike} columns
|
|
1270
|
+
*/
|
|
1271
|
+
select(...columns) {
|
|
1272
|
+
this.#columns = columns.map(column => typeof column === 'string' ? new SqlColumn(column) : column);
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
/**
|
|
1276
|
+
* @param {SqlToken} condition
|
|
1277
|
+
*/
|
|
1278
|
+
where(condition) {
|
|
1279
|
+
this.#where = new SqlWhere(condition);
|
|
1280
|
+
|
|
1281
|
+
return this
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
toString() {
|
|
1285
|
+
return `SELECT DISTINCT ON (${this.#distinct.join(',')})\n ${this.#columns.length === 0 ? '*' : this.#columns.join(',\n')}` +
|
|
1286
|
+
`\n${this.#from}` +
|
|
1287
|
+
(this.#join ? `\n${this.#join.join('\n')}` : '') +
|
|
1288
|
+
(this.#where ? `\n${this.#where}` : '') +
|
|
1289
|
+
(this.#orderby ? `\n${this.#orderby}` : '') +
|
|
1290
|
+
(this.#groupby ? `\n${this.#groupby}` : '') +
|
|
1291
|
+
(this.#limit ? `\n${this.#limit}` : '')
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
class SqlUnion {
|
|
1296
|
+
#statements
|
|
1297
|
+
|
|
1298
|
+
/**
|
|
1299
|
+
* @param {...SqlQuery} statements
|
|
1300
|
+
*/
|
|
1301
|
+
constructor(...statements) {
|
|
1302
|
+
this.#statements = statements;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
toString() {
|
|
1306
|
+
return this.#statements.map(statement => `(\n${statement}\n)`).join('\nUNION\n')
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
class ValueLike {
|
|
1311
|
+
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
class SqlAll extends ValueLike {
|
|
1315
|
+
#statement
|
|
1316
|
+
|
|
1317
|
+
/**
|
|
1318
|
+
* @param {StatementLike} statement
|
|
1319
|
+
*/
|
|
1320
|
+
constructor(statement) {
|
|
1321
|
+
super();
|
|
1322
|
+
this.#statement = statement;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
toString() {
|
|
1326
|
+
return `ALL(${this.#statement})`
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
class SqlAny extends ValueLike {
|
|
1331
|
+
#statement
|
|
1332
|
+
|
|
1333
|
+
/**
|
|
1334
|
+
* @param {StatementLike} statement
|
|
1335
|
+
*/
|
|
1336
|
+
constructor(statement) {
|
|
1337
|
+
super();
|
|
1338
|
+
this.#statement = statement;
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
toString() {
|
|
1342
|
+
return `ANY(${this.#statement})`
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
class SqlConstant extends ValueLike {
|
|
1347
|
+
#name
|
|
1348
|
+
|
|
1349
|
+
/**
|
|
1350
|
+
* @param {string} name
|
|
1351
|
+
*/
|
|
1352
|
+
constructor(name) {
|
|
1353
|
+
super();
|
|
1354
|
+
this.#name = name;
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
toString() {
|
|
1358
|
+
return this.#name
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
class PostgreSQL {
|
|
1363
|
+
/**
|
|
1364
|
+
* @param {pg.PoolConfig} options
|
|
1365
|
+
*/
|
|
1366
|
+
constructor(options) {
|
|
1367
|
+
/**
|
|
1368
|
+
* @type {pg.Pool}
|
|
1369
|
+
*/
|
|
1370
|
+
this.pool = new pg.Pool(options);
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+
// #region Queries
|
|
1375
|
+
|
|
1376
|
+
|
|
1377
|
+
/**
|
|
1378
|
+
* @param {...ColumnLike=} columns
|
|
1379
|
+
*/
|
|
1380
|
+
insert(...columns) {
|
|
1381
|
+
return new SqlInsert(this, ...columns)
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
|
|
1385
|
+
/**
|
|
1386
|
+
* @param {...ColumnLike=} columns
|
|
1387
|
+
*/
|
|
1388
|
+
select(...columns) {
|
|
1389
|
+
return new SqlSelect(this, ...columns)
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
/**
|
|
1394
|
+
* @param {...ColumnLike=} columns
|
|
1395
|
+
*/
|
|
1396
|
+
selectDistinct(...columns) {
|
|
1397
|
+
return new SqlSelectDistinct(this, ...columns)
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
|
|
1401
|
+
/**
|
|
1402
|
+
* @param {...ColumnLike} columns
|
|
1403
|
+
*/
|
|
1404
|
+
selectDistinctOn(...columns) {
|
|
1405
|
+
return new SqlSelectDistinctOn(this, ...columns)
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
|
|
1409
|
+
/**
|
|
1410
|
+
* @param {...SqlQuery} statements
|
|
1411
|
+
*/
|
|
1412
|
+
union(...statements) {
|
|
1413
|
+
return new SqlUnion(...statements)
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
|
|
1417
|
+
// #endregion
|
|
1418
|
+
|
|
1419
|
+
|
|
1420
|
+
// #region Constants
|
|
1421
|
+
|
|
1422
|
+
|
|
1423
|
+
CURRENT_DATE = new SqlConstant('CURRENT_DATE')
|
|
1424
|
+
|
|
1425
|
+
FALSE = new SqlConstant('FALSE')
|
|
1426
|
+
|
|
1427
|
+
NULL = new SqlConstant('NULL')
|
|
1428
|
+
|
|
1429
|
+
TRUE = new SqlConstant('TRUE')
|
|
1430
|
+
|
|
1431
|
+
// #endregion
|
|
1432
|
+
|
|
1433
|
+
|
|
1434
|
+
// #region Column-like
|
|
1435
|
+
|
|
1436
|
+
|
|
1437
|
+
case() {
|
|
1438
|
+
return new SqlCase()
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
|
|
1442
|
+
/**
|
|
1443
|
+
* @param {ColumnLike} left
|
|
1444
|
+
* @param {ColumnLike} right
|
|
1445
|
+
*/
|
|
1446
|
+
coalese(left, right) {
|
|
1447
|
+
return new SqlCoalesce(left, right)
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
|
|
1451
|
+
/**
|
|
1452
|
+
* @param {string} name
|
|
1453
|
+
*/
|
|
1454
|
+
column(name) {
|
|
1455
|
+
return new SqlColumn(name)
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
|
|
1459
|
+
/**
|
|
1460
|
+
* @param {...ColumnLike} columns
|
|
1461
|
+
*/
|
|
1462
|
+
concat(...columns) {
|
|
1463
|
+
return new SqlConcat(...columns)
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
|
|
1467
|
+
/**
|
|
1468
|
+
* @param {number} value
|
|
1469
|
+
* @param {string} unit
|
|
1470
|
+
*/
|
|
1471
|
+
dateinterval(value, unit) {
|
|
1472
|
+
return new SqlDateInterval(value, unit)
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
|
|
1476
|
+
/**
|
|
1477
|
+
* @param {string} part
|
|
1478
|
+
* @param {ColumnLike} column
|
|
1479
|
+
*/
|
|
1480
|
+
datepart(part, column) {
|
|
1481
|
+
return new SqlDatePart(part, column)
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
|
|
1485
|
+
/**
|
|
1486
|
+
* @param {string} part
|
|
1487
|
+
* @param {ColumnLike} column
|
|
1488
|
+
*/
|
|
1489
|
+
datetrunc(part, column) {
|
|
1490
|
+
return new SqlDateTrunc(part, column)
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
|
|
1494
|
+
/**
|
|
1495
|
+
* @param {ColumnLike} column
|
|
1496
|
+
* @param {number} length
|
|
1497
|
+
* @param {string} fill
|
|
1498
|
+
*/
|
|
1499
|
+
lpad(column, length, fill) {
|
|
1500
|
+
return new SqlLPad(column, length, fill)
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
|
|
1504
|
+
/**
|
|
1505
|
+
* @param {ColumnLike} column
|
|
1506
|
+
*/
|
|
1507
|
+
max(column) {
|
|
1508
|
+
return new SqlMax(column)
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
|
|
1512
|
+
/**
|
|
1513
|
+
* @param {number} number
|
|
1514
|
+
*/
|
|
1515
|
+
param(number) {
|
|
1516
|
+
return new SqlParameter(number)
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
|
|
1520
|
+
/**
|
|
1521
|
+
* @param {ColumnLike} column
|
|
1522
|
+
* @param {number} length
|
|
1523
|
+
* @param {string} fill
|
|
1524
|
+
*/
|
|
1525
|
+
rpad(column, length, fill) {
|
|
1526
|
+
return new SqlRPad(column, length, fill)
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
|
|
1530
|
+
/**
|
|
1531
|
+
* @param {string} value
|
|
1532
|
+
*/
|
|
1533
|
+
string(value) {
|
|
1534
|
+
return new SqlString(value)
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
|
|
1538
|
+
/**
|
|
1539
|
+
* @param {ColumnLike} column
|
|
1540
|
+
* @param {string} separator
|
|
1541
|
+
* @param {boolean} distinct
|
|
1542
|
+
*/
|
|
1543
|
+
stringagg(column, separator, distinct=true) {
|
|
1544
|
+
return new SqlStringAgg(column, separator, distinct)
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
|
|
1548
|
+
/**
|
|
1549
|
+
* @param {ColumnLike} column
|
|
1550
|
+
* @param {string} separator
|
|
1551
|
+
* @param {string=} replace
|
|
1552
|
+
*/
|
|
1553
|
+
stringtoarray(column, separator, replace) {
|
|
1554
|
+
return new SqlStringToArray(column, separator, replace)
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
|
|
1558
|
+
/**
|
|
1559
|
+
* @param {ColumnLike} column
|
|
1560
|
+
* @param {string} pattern
|
|
1561
|
+
*/
|
|
1562
|
+
substring(column, pattern) {
|
|
1563
|
+
return new SqlSubString(column, pattern)
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
|
|
1567
|
+
// #endregion
|
|
1568
|
+
|
|
1569
|
+
|
|
1570
|
+
// #region Condition-like
|
|
1571
|
+
|
|
1572
|
+
|
|
1573
|
+
/**
|
|
1574
|
+
* @param {...ConditionLike} conditions
|
|
1575
|
+
*/
|
|
1576
|
+
and(...conditions) {
|
|
1577
|
+
return new SqlAnd(...conditions)
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
|
|
1581
|
+
/**
|
|
1582
|
+
* @param {ColumnLike} left
|
|
1583
|
+
* @param {ColumnLike} right
|
|
1584
|
+
*/
|
|
1585
|
+
equal(left, right) {
|
|
1586
|
+
return new SqlEqual(left, right)
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
|
|
1590
|
+
/**
|
|
1591
|
+
* @param {ColumnLike} left
|
|
1592
|
+
* @param {ColumnLike} right
|
|
1593
|
+
*/
|
|
1594
|
+
greaterThan(left, right) {
|
|
1595
|
+
return new SqlGreaterThan(left, right)
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
|
|
1599
|
+
/**
|
|
1600
|
+
* @param {ColumnLike} left
|
|
1601
|
+
* @param {ColumnLike} right
|
|
1602
|
+
*/
|
|
1603
|
+
greaterThanOrEqual(left, right) {
|
|
1604
|
+
return new SqlGreaterThanOrEqual(left, right)
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
|
|
1608
|
+
/**
|
|
1609
|
+
* @param {ColumnLike} left
|
|
1610
|
+
* @param {ColumnLike} right
|
|
1611
|
+
*/
|
|
1612
|
+
ilike(left, right) {
|
|
1613
|
+
return new SqlILike(left, right)
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
|
|
1617
|
+
/**
|
|
1618
|
+
* @param {ColumnLike} column
|
|
1619
|
+
*/
|
|
1620
|
+
isNotNull(column) {
|
|
1621
|
+
return new SqlIsNotNull(column)
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
|
|
1625
|
+
/**
|
|
1626
|
+
* @param {ColumnLike} column
|
|
1627
|
+
*/
|
|
1628
|
+
isNull(column) {
|
|
1629
|
+
return new SqlIsNull(column)
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
|
|
1633
|
+
/**
|
|
1634
|
+
* @param {ColumnLike} left
|
|
1635
|
+
* @param {ColumnLike} right
|
|
1636
|
+
*/
|
|
1637
|
+
lessThan(left, right) {
|
|
1638
|
+
return new SqlLessThan(left, right)
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
|
|
1642
|
+
/**
|
|
1643
|
+
* @param {ColumnLike} left
|
|
1644
|
+
* @param {ColumnLike} right
|
|
1645
|
+
*/
|
|
1646
|
+
lessThanOrEqual(left, right) {
|
|
1647
|
+
return new SqlLessThanOrEqual(left, right)
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
|
|
1651
|
+
/**
|
|
1652
|
+
* @param {ColumnLike} left
|
|
1653
|
+
* @param {ColumnLike} right
|
|
1654
|
+
*/
|
|
1655
|
+
like(left, right) {
|
|
1656
|
+
return new SqlLike(left, right)
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
|
|
1660
|
+
/**
|
|
1661
|
+
* @param {ColumnLike} left
|
|
1662
|
+
* @param {ColumnLike} right
|
|
1663
|
+
*/
|
|
1664
|
+
match(left, right) {
|
|
1665
|
+
return new SqlMatch(left, right)
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
|
|
1669
|
+
/**
|
|
1670
|
+
* @param {ColumnLike} left
|
|
1671
|
+
* @param {ColumnLike} right
|
|
1672
|
+
*/
|
|
1673
|
+
notEqual(left, right) {
|
|
1674
|
+
return new SqlNotEqual(left, right)
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
/**
|
|
1678
|
+
* @param {ColumnLike} left
|
|
1679
|
+
* @param {ColumnLike} right
|
|
1680
|
+
*/
|
|
1681
|
+
notILike(left, right) {
|
|
1682
|
+
return new SqlNotILike(left, right)
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
/**
|
|
1686
|
+
* @param {ColumnLike} left
|
|
1687
|
+
* @param {ColumnLike} right
|
|
1688
|
+
*/
|
|
1689
|
+
notLike(left, right) {
|
|
1690
|
+
return new SqlNotLike(left, right)
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
|
|
1694
|
+
/**
|
|
1695
|
+
* @param {ColumnLike} left
|
|
1696
|
+
* @param {ColumnLike} right
|
|
1697
|
+
*/
|
|
1698
|
+
notMatch(left, right) {
|
|
1699
|
+
return new SqlNotMatch(left, right)
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
|
|
1703
|
+
/**
|
|
1704
|
+
* @param {...ConditionLike} conditions
|
|
1705
|
+
*/
|
|
1706
|
+
or(...conditions) {
|
|
1707
|
+
return new SqlOr(...conditions)
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
// #endregion
|
|
1711
|
+
|
|
1712
|
+
|
|
1713
|
+
// #region Value-like
|
|
1714
|
+
|
|
1715
|
+
|
|
1716
|
+
/**
|
|
1717
|
+
* @param {StatementLike} statement
|
|
1718
|
+
*/
|
|
1719
|
+
all(statement) {
|
|
1720
|
+
return new SqlAll(statement)
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
|
|
1724
|
+
/**
|
|
1725
|
+
* @param {StatementLike} statement
|
|
1726
|
+
*/
|
|
1727
|
+
any(statement) {
|
|
1728
|
+
return new SqlAny(statement)
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
|
|
1732
|
+
// #endregion
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
exports.PostgreSQL = PostgreSQL;
|