knex 0.95.14 → 1.0.2
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 +90 -1
- package/README.md +1 -1
- package/UPGRADING.md +7 -0
- package/lib/client.js +14 -1
- package/lib/constants.js +2 -0
- package/lib/dialects/better-sqlite3/index.js +72 -0
- package/lib/dialects/cockroachdb/crdb-querycompiler.js +92 -33
- package/lib/dialects/cockroachdb/crdb-tablecompiler.js +19 -0
- package/lib/dialects/cockroachdb/index.js +13 -0
- package/lib/dialects/mssql/index.js +0 -11
- package/lib/dialects/mssql/query/mssql-querycompiler.js +122 -64
- package/lib/dialects/mssql/schema/mssql-columncompiler.js +41 -6
- package/lib/dialects/mssql/schema/mssql-compiler.js +3 -4
- package/lib/dialects/mssql/schema/mssql-tablecompiler.js +24 -9
- package/lib/dialects/mssql/schema/mssql-viewcompiler.js +15 -1
- package/lib/dialects/mysql/query/mysql-querycompiler.js +93 -5
- package/lib/dialects/mysql/schema/mysql-columncompiler.js +32 -5
- package/lib/dialects/mysql/schema/mysql-tablecompiler.js +33 -6
- package/lib/dialects/oracle/query/oracle-querycompiler.js +7 -6
- package/lib/dialects/oracle/schema/internal/trigger.js +1 -1
- package/lib/dialects/oracle/schema/oracle-columncompiler.js +10 -4
- package/lib/dialects/oracle/schema/oracle-tablecompiler.js +17 -6
- package/lib/dialects/oracledb/index.js +0 -4
- package/lib/dialects/oracledb/query/oracledb-querycompiler.js +89 -0
- package/lib/dialects/oracledb/schema/oracledb-columncompiler.js +23 -0
- package/lib/dialects/postgres/index.js +21 -6
- package/lib/dialects/postgres/query/pg-querybuilder.js +38 -0
- package/lib/dialects/postgres/query/pg-querycompiler.js +172 -9
- package/lib/dialects/postgres/schema/pg-columncompiler.js +24 -4
- package/lib/dialects/postgres/schema/pg-tablecompiler.js +63 -46
- package/lib/dialects/redshift/index.js +12 -0
- package/lib/dialects/redshift/query/redshift-querycompiler.js +62 -26
- package/lib/dialects/redshift/schema/redshift-columncompiler.js +2 -1
- package/lib/dialects/redshift/schema/redshift-tablecompiler.js +4 -1
- package/lib/dialects/sqlite3/index.js +23 -4
- package/lib/dialects/sqlite3/query/sqlite-querybuilder.js +33 -0
- package/lib/dialects/sqlite3/query/sqlite-querycompiler.js +87 -22
- package/lib/dialects/sqlite3/schema/ddl.js +274 -282
- package/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js +18 -8
- package/lib/dialects/sqlite3/schema/sqlite-columncompiler.js +20 -0
- package/lib/dialects/sqlite3/schema/sqlite-compiler.js +16 -12
- package/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js +15 -5
- package/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js +31 -2
- package/lib/execution/runner.js +37 -2
- package/lib/knex-builder/FunctionHelper.js +36 -0
- package/lib/migrations/common/MigrationsLoader.js +36 -0
- package/lib/migrations/migrate/MigrationGenerator.js +1 -1
- package/lib/migrations/migrate/Migrator.js +22 -24
- package/lib/migrations/migrate/migration-list-resolver.js +2 -5
- package/lib/migrations/migrate/{configuration-merger.js → migrator-configuration-merger.js} +2 -4
- package/lib/migrations/migrate/sources/fs-migrations.js +4 -29
- package/lib/migrations/migrate/stub/js.stub +8 -1
- package/lib/migrations/migrate/stub/knexfile-js.stub +3 -0
- package/lib/migrations/migrate/stub/knexfile-ts.stub +5 -2
- package/lib/migrations/migrate/table-creator.js +6 -5
- package/lib/migrations/seed/Seeder.js +25 -92
- package/lib/migrations/seed/seeder-configuration-merger.js +60 -0
- package/lib/migrations/seed/sources/fs-seeds.js +65 -0
- package/lib/migrations/seed/stub/js.stub +4 -1
- package/lib/migrations/util/import-file.js +0 -1
- package/lib/query/joinclause.js +24 -5
- package/lib/query/method-constants.js +37 -0
- package/lib/query/querybuilder.js +292 -53
- package/lib/query/querycompiler.js +309 -85
- package/lib/schema/columnbuilder.js +14 -1
- package/lib/schema/columncompiler.js +132 -5
- package/lib/schema/compiler.js +1 -0
- package/lib/schema/tablebuilder.js +41 -8
- package/lib/schema/tablecompiler.js +61 -4
- package/lib/schema/viewcompiler.js +13 -10
- package/package.json +37 -27
- package/scripts/docker-compose.yml +7 -7
- package/scripts/oracledb-install-driver-libs.sh +82 -0
- package/scripts/runkit-example.js +1 -1
- package/scripts/stress-test/docker-compose.yml +3 -3
- package/scripts/stress-test/knex-stress-test.js +1 -1
- package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +1 -1
- package/types/index.d.ts +133 -21
|
@@ -19,7 +19,7 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
19
19
|
: 'create table ';
|
|
20
20
|
const { client } = this;
|
|
21
21
|
let conn = {};
|
|
22
|
-
const columnsSql = ' (' + columns.sql.join(', ') + ')';
|
|
22
|
+
const columnsSql = ' (' + columns.sql.join(', ') + this._addChecks() + ')';
|
|
23
23
|
let sql =
|
|
24
24
|
createStatement +
|
|
25
25
|
this.tableName() +
|
|
@@ -42,14 +42,18 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
42
42
|
|
|
43
43
|
if (this.single.comment) {
|
|
44
44
|
const comment = this.single.comment || '';
|
|
45
|
-
|
|
45
|
+
const MAX_COMMENT_LENGTH = 1024;
|
|
46
|
+
if (comment.length > MAX_COMMENT_LENGTH)
|
|
46
47
|
this.client.logger.warn(
|
|
47
|
-
|
|
48
|
+
`The max length for a table comment is ${MAX_COMMENT_LENGTH} characters`
|
|
48
49
|
);
|
|
49
50
|
sql += ` comment = '${comment}'`;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
this.pushQuery(sql);
|
|
54
|
+
if (like) {
|
|
55
|
+
this.addColumns(columns, this.addColumnsPrefix);
|
|
56
|
+
}
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
// Compiles the comment on the table.
|
|
@@ -69,7 +73,7 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
69
73
|
|
|
70
74
|
this.pushQuery({
|
|
71
75
|
sql:
|
|
72
|
-
`show fields from ${table} where field = ` +
|
|
76
|
+
`show full fields from ${table} where field = ` +
|
|
73
77
|
this.client.parameter(from, this.tableBuilder, this.bindingsHolder),
|
|
74
78
|
output(resp) {
|
|
75
79
|
const column = resp[0];
|
|
@@ -97,7 +101,10 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
97
101
|
if (column.Default !== void 0 && column.Default !== null) {
|
|
98
102
|
sql += ` DEFAULT '${column.Default}'`;
|
|
99
103
|
}
|
|
100
|
-
|
|
104
|
+
if (column.Collation !== void 0 && column.Collation !== null) {
|
|
105
|
+
sql += ` COLLATE '${column.Collation}'`;
|
|
106
|
+
}
|
|
107
|
+
// Add back the auto increment if the column it, fix issue #2767
|
|
101
108
|
if (column.Extra == 'auto_increment') {
|
|
102
109
|
sql += ` AUTO_INCREMENT`;
|
|
103
110
|
}
|
|
@@ -249,11 +256,31 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
249
256
|
constraintName = constraintName
|
|
250
257
|
? this.formatter.wrap(constraintName)
|
|
251
258
|
: this.formatter.wrap(`${this.tableNameRaw}_pkey`);
|
|
259
|
+
|
|
260
|
+
const primaryCols = columns;
|
|
261
|
+
let incrementsCols = [];
|
|
262
|
+
if (this.grouped.columns) {
|
|
263
|
+
incrementsCols = this._getIncrementsColumnNames();
|
|
264
|
+
if (incrementsCols) {
|
|
265
|
+
incrementsCols.forEach((c) => {
|
|
266
|
+
if (!primaryCols.includes(c)) {
|
|
267
|
+
primaryCols.unshift(c);
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
252
272
|
this.pushQuery(
|
|
253
273
|
`alter table ${this.tableName()} add primary key ${constraintName}(${this.formatter.columnize(
|
|
254
|
-
|
|
274
|
+
primaryCols
|
|
255
275
|
)})`
|
|
256
276
|
);
|
|
277
|
+
if (incrementsCols.length) {
|
|
278
|
+
this.pushQuery(
|
|
279
|
+
`alter table ${this.tableName()} modify column ${this.formatter.columnize(
|
|
280
|
+
incrementsCols
|
|
281
|
+
)} int unsigned not null auto_increment`
|
|
282
|
+
);
|
|
283
|
+
}
|
|
257
284
|
}
|
|
258
285
|
|
|
259
286
|
unique(columns, indexName) {
|
|
@@ -315,10 +315,9 @@ class QueryCompiler_Oracle extends QueryCompiler {
|
|
|
315
315
|
query = query || '';
|
|
316
316
|
|
|
317
317
|
if (hasLimit && !offset) {
|
|
318
|
-
return `select * from (${query}) where rownum <= ${this.
|
|
319
|
-
limit,
|
|
320
|
-
|
|
321
|
-
this.bindingsHolder
|
|
318
|
+
return `select * from (${query}) where rownum <= ${this._getValueOrParameterFromAttribute(
|
|
319
|
+
'limit',
|
|
320
|
+
limit
|
|
322
321
|
)}`;
|
|
323
322
|
}
|
|
324
323
|
|
|
@@ -330,10 +329,12 @@ class QueryCompiler_Oracle extends QueryCompiler {
|
|
|
330
329
|
query +
|
|
331
330
|
') row_ ' +
|
|
332
331
|
'where rownum <= ' +
|
|
333
|
-
|
|
332
|
+
(this.single.skipBinding['offset']
|
|
333
|
+
? endRow
|
|
334
|
+
: this.client.parameter(endRow, this.builder, this.bindingsHolder)) +
|
|
334
335
|
') ' +
|
|
335
336
|
'where rownum_ > ' +
|
|
336
|
-
this.
|
|
337
|
+
this._getValueOrParameterFromAttribute('offset', offset)
|
|
337
338
|
);
|
|
338
339
|
}
|
|
339
340
|
}
|
|
@@ -64,7 +64,7 @@ const trigger = {
|
|
|
64
64
|
`PK_NAME VARCHAR(200); ` +
|
|
65
65
|
`BEGIN` +
|
|
66
66
|
` EXECUTE IMMEDIATE ('CREATE SEQUENCE ${schemaQuoted}${sequenceNameQuoted}');` +
|
|
67
|
-
` SELECT cols.column_name INTO PK_NAME` +
|
|
67
|
+
` SELECT cols.column_name INTO PK_NAME` + // TODO : support autoincrement on table with multiple primary keys
|
|
68
68
|
` FROM all_constraints cons, all_cons_columns cols` +
|
|
69
69
|
` WHERE cons.constraint_type = 'P'` +
|
|
70
70
|
` AND cons.constraint_name = cols.constraint_name` +
|
|
@@ -15,14 +15,20 @@ class ColumnCompiler_Oracle extends ColumnCompiler {
|
|
|
15
15
|
this.modifiers = ['defaultTo', 'checkIn', 'nullable', 'comment'];
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
increments({ primaryKey
|
|
18
|
+
increments(options = { primaryKey: true }) {
|
|
19
19
|
createAutoIncrementTriggerAndSequence(this);
|
|
20
|
-
return
|
|
20
|
+
return (
|
|
21
|
+
'integer not null' +
|
|
22
|
+
(this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
|
|
23
|
+
);
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
bigincrements({ primaryKey
|
|
26
|
+
bigincrements(options = { primaryKey: true }) {
|
|
24
27
|
createAutoIncrementTriggerAndSequence(this);
|
|
25
|
-
return
|
|
28
|
+
return (
|
|
29
|
+
'number(20, 0) not null' +
|
|
30
|
+
(this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
|
|
31
|
+
);
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
floating(precision) {
|
|
@@ -57,7 +57,7 @@ class TableCompiler_Oracle extends TableCompiler {
|
|
|
57
57
|
const columnsSql =
|
|
58
58
|
like && this.tableNameLike()
|
|
59
59
|
? ' as (select * from ' + this.tableNameLike() + ' where 0=1)'
|
|
60
|
-
: ' (' + columns.sql.join(', ') + ')';
|
|
60
|
+
: ' (' + columns.sql.join(', ') + this._addChecks() + ')';
|
|
61
61
|
const sql = `create table ${this.tableName()}${columnsSql}`;
|
|
62
62
|
|
|
63
63
|
this.pushQuery({
|
|
@@ -66,6 +66,9 @@ class TableCompiler_Oracle extends TableCompiler {
|
|
|
66
66
|
bindings: columns.bindings,
|
|
67
67
|
});
|
|
68
68
|
if (this.single.comment) this.comment(this.single.comment);
|
|
69
|
+
if (like) {
|
|
70
|
+
this.addColumns(columns, this.addColumnsPrefix);
|
|
71
|
+
}
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
// Compiles the comment on the table.
|
|
@@ -82,10 +85,6 @@ class TableCompiler_Oracle extends TableCompiler {
|
|
|
82
85
|
);
|
|
83
86
|
}
|
|
84
87
|
|
|
85
|
-
changeType() {
|
|
86
|
-
// alter table + table + ' modify ' + wrapped + '// type';
|
|
87
|
-
}
|
|
88
|
-
|
|
89
88
|
_indexCommand(type, tableName, columns) {
|
|
90
89
|
return this.formatter.wrap(
|
|
91
90
|
utils.generateCombinedName(this.client.logger, type, tableName, columns)
|
|
@@ -101,9 +100,21 @@ class TableCompiler_Oracle extends TableCompiler {
|
|
|
101
100
|
constraintName = constraintName
|
|
102
101
|
? this.formatter.wrap(constraintName)
|
|
103
102
|
: this.formatter.wrap(`${this.tableNameRaw}_pkey`);
|
|
103
|
+
const primaryCols = columns;
|
|
104
|
+
let incrementsCols = [];
|
|
105
|
+
if (this.grouped.columns) {
|
|
106
|
+
incrementsCols = this._getIncrementsColumnNames();
|
|
107
|
+
if (incrementsCols) {
|
|
108
|
+
incrementsCols.forEach((c) => {
|
|
109
|
+
if (!primaryCols.includes(c)) {
|
|
110
|
+
primaryCols.unshift(c);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
104
115
|
this.pushQuery(
|
|
105
116
|
`alter table ${this.tableName()} add constraint ${constraintName} primary key (${this.formatter.columnize(
|
|
106
|
-
|
|
117
|
+
primaryCols
|
|
107
118
|
)})${deferrable}`
|
|
108
119
|
);
|
|
109
120
|
}
|
|
@@ -4,7 +4,6 @@ const each = require('lodash/each');
|
|
|
4
4
|
const flatten = require('lodash/flatten');
|
|
5
5
|
const isEmpty = require('lodash/isEmpty');
|
|
6
6
|
const map = require('lodash/map');
|
|
7
|
-
const values = require('lodash/values');
|
|
8
7
|
|
|
9
8
|
const Formatter = require('../../formatter');
|
|
10
9
|
const QueryCompiler = require('./query/oracledb-querycompiler');
|
|
@@ -288,9 +287,6 @@ class Client_Oracledb extends Client_Oracle {
|
|
|
288
287
|
case 'update':
|
|
289
288
|
case 'counter':
|
|
290
289
|
if (obj.returning && !isEmpty(obj.returning)) {
|
|
291
|
-
if (obj.returning.length === 1 && obj.returning[0] !== '*') {
|
|
292
|
-
return flatten(map(response, values));
|
|
293
|
-
}
|
|
294
290
|
return response;
|
|
295
291
|
} else if (obj.rowsAffected !== undefined) {
|
|
296
292
|
return obj.rowsAffected;
|
|
@@ -6,6 +6,9 @@ const Oracle_Compiler = require('../../oracle/query/oracle-querycompiler');
|
|
|
6
6
|
const ReturningHelper = require('../utils').ReturningHelper;
|
|
7
7
|
const BlobHelper = require('../utils').BlobHelper;
|
|
8
8
|
const { isString } = require('../../../util/is');
|
|
9
|
+
const {
|
|
10
|
+
columnize: columnize_,
|
|
11
|
+
} = require('../../../formatter/wrappingFormatter');
|
|
9
12
|
|
|
10
13
|
class Oracledb_Compiler extends Oracle_Compiler {
|
|
11
14
|
// Compiles an "insert" query, allowing for multiple
|
|
@@ -312,6 +315,10 @@ class Oracledb_Compiler extends Oracle_Compiler {
|
|
|
312
315
|
return result;
|
|
313
316
|
}
|
|
314
317
|
|
|
318
|
+
_groupOrder(item, type) {
|
|
319
|
+
return super._groupOrderNulls(item, type);
|
|
320
|
+
}
|
|
321
|
+
|
|
315
322
|
update() {
|
|
316
323
|
const self = this;
|
|
317
324
|
const sql = {};
|
|
@@ -387,6 +394,88 @@ class Oracledb_Compiler extends Oracle_Compiler {
|
|
|
387
394
|
|
|
388
395
|
return sql;
|
|
389
396
|
}
|
|
397
|
+
|
|
398
|
+
_jsonPathWrap(extraction) {
|
|
399
|
+
return `'${extraction.path || extraction[1]}'`;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Json functions
|
|
403
|
+
jsonExtract(params) {
|
|
404
|
+
return this._jsonExtract(
|
|
405
|
+
params.singleValue ? 'json_value' : 'json_query',
|
|
406
|
+
params
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
jsonSet(params) {
|
|
411
|
+
return `json_transform(${columnize_(
|
|
412
|
+
params.column,
|
|
413
|
+
this.builder,
|
|
414
|
+
this.client,
|
|
415
|
+
this.bindingsHolder
|
|
416
|
+
)}, set ${this.client.parameter(
|
|
417
|
+
params.path,
|
|
418
|
+
this.builder,
|
|
419
|
+
this.bindingsHolder
|
|
420
|
+
)} = ${this.client.parameter(
|
|
421
|
+
params.value,
|
|
422
|
+
this.builder,
|
|
423
|
+
this.bindingsHolder
|
|
424
|
+
)})`;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
jsonInsert(params) {
|
|
428
|
+
return `json_transform(${columnize_(
|
|
429
|
+
params.column,
|
|
430
|
+
this.builder,
|
|
431
|
+
this.client,
|
|
432
|
+
this.bindingsHolder
|
|
433
|
+
)}, insert ${this.client.parameter(
|
|
434
|
+
params.path,
|
|
435
|
+
this.builder,
|
|
436
|
+
this.bindingsHolder
|
|
437
|
+
)} = ${this.client.parameter(
|
|
438
|
+
params.value,
|
|
439
|
+
this.builder,
|
|
440
|
+
this.bindingsHolder
|
|
441
|
+
)})`;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
jsonRemove(params) {
|
|
445
|
+
const jsonCol = `json_transform(${columnize_(
|
|
446
|
+
params.column,
|
|
447
|
+
this.builder,
|
|
448
|
+
this.client,
|
|
449
|
+
this.bindingsHolder
|
|
450
|
+
)}, remove ${this.client.parameter(
|
|
451
|
+
params.path,
|
|
452
|
+
this.builder,
|
|
453
|
+
this.bindingsHolder
|
|
454
|
+
)})`;
|
|
455
|
+
return params.alias
|
|
456
|
+
? this.client.alias(jsonCol, this.formatter.wrap(params.alias))
|
|
457
|
+
: jsonCol;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
whereJsonPath(statement) {
|
|
461
|
+
return this._whereJsonPath('json_value', statement);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
whereJsonSupersetOf(statement) {
|
|
465
|
+
throw new Error(
|
|
466
|
+
'Json superset where clause not actually supported by Oracle'
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
whereJsonSubsetOf(statement) {
|
|
471
|
+
throw new Error(
|
|
472
|
+
'Json subset where clause not actually supported by Oracle'
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
onJsonPathEquals(clause) {
|
|
477
|
+
return this._onJsonPathEquals('json_value', clause);
|
|
478
|
+
}
|
|
390
479
|
}
|
|
391
480
|
|
|
392
481
|
module.exports = Oracledb_Compiler;
|
|
@@ -4,6 +4,8 @@ const { isObject } = require('../../../util/is');
|
|
|
4
4
|
class ColumnCompiler_Oracledb extends ColumnCompiler_Oracle {
|
|
5
5
|
constructor() {
|
|
6
6
|
super(...arguments);
|
|
7
|
+
this.modifiers = ['defaultTo', 'nullable', 'comment'];
|
|
8
|
+
this._addCheckModifiers();
|
|
7
9
|
}
|
|
8
10
|
|
|
9
11
|
datetime(withoutTz) {
|
|
@@ -25,8 +27,29 @@ class ColumnCompiler_Oracledb extends ColumnCompiler_Oracle {
|
|
|
25
27
|
}
|
|
26
28
|
return useTz ? 'timestamp with local time zone' : 'timestamp';
|
|
27
29
|
}
|
|
30
|
+
|
|
31
|
+
checkRegex(regex, constraintName) {
|
|
32
|
+
return this._check(
|
|
33
|
+
`REGEXP_LIKE(${this.formatter.wrap(
|
|
34
|
+
this.getColumnName()
|
|
35
|
+
)},${this.client._escapeBinding(regex)})`,
|
|
36
|
+
constraintName
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
json() {
|
|
41
|
+
return `varchar2(4000) check (${this.formatter.columnize(
|
|
42
|
+
this.getColumnName()
|
|
43
|
+
)} is json)`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
jsonb() {
|
|
47
|
+
return this.json();
|
|
48
|
+
}
|
|
28
49
|
}
|
|
29
50
|
|
|
30
51
|
ColumnCompiler_Oracledb.prototype.time = 'timestamp with local time zone';
|
|
52
|
+
ColumnCompiler_Oracledb.prototype.uuid = ({ useBinaryUuid = false } = {}) =>
|
|
53
|
+
useBinaryUuid ? 'raw(16)' : 'char(36)';
|
|
31
54
|
|
|
32
55
|
module.exports = ColumnCompiler_Oracledb;
|
|
@@ -7,6 +7,7 @@ const Client = require('../../client');
|
|
|
7
7
|
|
|
8
8
|
const Transaction = require('./execution/pg-transaction');
|
|
9
9
|
const QueryCompiler = require('./query/pg-querycompiler');
|
|
10
|
+
const QueryBuilder = require('./query/pg-querybuilder');
|
|
10
11
|
const ColumnCompiler = require('./schema/pg-columncompiler');
|
|
11
12
|
const TableCompiler = require('./schema/pg-tablecompiler');
|
|
12
13
|
const ViewCompiler = require('./schema/pg-viewcompiler');
|
|
@@ -30,6 +31,10 @@ class Client_PG extends Client {
|
|
|
30
31
|
return new Transaction(this, ...arguments);
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
queryBuilder() {
|
|
35
|
+
return new QueryBuilder(this);
|
|
36
|
+
}
|
|
37
|
+
|
|
33
38
|
queryCompiler(builder, formatter) {
|
|
34
39
|
return new QueryCompiler(this, builder, formatter);
|
|
35
40
|
}
|
|
@@ -241,12 +246,7 @@ class Client_PG extends Client {
|
|
|
241
246
|
const returns = [];
|
|
242
247
|
for (let i = 0, l = resp.rows.length; i < l; i++) {
|
|
243
248
|
const row = resp.rows[i];
|
|
244
|
-
|
|
245
|
-
returns[i] = row;
|
|
246
|
-
} else {
|
|
247
|
-
// Pluck the only column in the row.
|
|
248
|
-
returns[i] = row[Object.keys(row)[0]];
|
|
249
|
-
}
|
|
249
|
+
returns[i] = row;
|
|
250
250
|
}
|
|
251
251
|
return returns;
|
|
252
252
|
}
|
|
@@ -274,6 +274,21 @@ class Client_PG extends Client {
|
|
|
274
274
|
options: {},
|
|
275
275
|
});
|
|
276
276
|
}
|
|
277
|
+
|
|
278
|
+
toPathForJson(jsonPath) {
|
|
279
|
+
const PG_PATH_REGEX = /^{.*}$/;
|
|
280
|
+
if (jsonPath.match(PG_PATH_REGEX)) {
|
|
281
|
+
return jsonPath;
|
|
282
|
+
}
|
|
283
|
+
return (
|
|
284
|
+
'{' +
|
|
285
|
+
jsonPath
|
|
286
|
+
.replace(/^(\$\.)/, '') // remove the first dollar
|
|
287
|
+
.replace('.', ',')
|
|
288
|
+
.replace(/\[([0-9]+)]/, ',$1') + // transform [number] to ,number
|
|
289
|
+
'}'
|
|
290
|
+
);
|
|
291
|
+
}
|
|
277
292
|
}
|
|
278
293
|
|
|
279
294
|
Object.assign(Client_PG.prototype, {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const QueryBuilder = require('../../../query/querybuilder.js');
|
|
2
|
+
|
|
3
|
+
module.exports = class QueryBuilder_PostgreSQL extends QueryBuilder {
|
|
4
|
+
using(tables) {
|
|
5
|
+
this._single.using = tables;
|
|
6
|
+
return this;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
withMaterialized(alias, statementOrColumnList, nothingOrStatement) {
|
|
10
|
+
this._validateWithArgs(
|
|
11
|
+
alias,
|
|
12
|
+
statementOrColumnList,
|
|
13
|
+
nothingOrStatement,
|
|
14
|
+
'with'
|
|
15
|
+
);
|
|
16
|
+
return this.withWrapped(
|
|
17
|
+
alias,
|
|
18
|
+
statementOrColumnList,
|
|
19
|
+
nothingOrStatement,
|
|
20
|
+
true
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
withNotMaterialized(alias, statementOrColumnList, nothingOrStatement) {
|
|
25
|
+
this._validateWithArgs(
|
|
26
|
+
alias,
|
|
27
|
+
statementOrColumnList,
|
|
28
|
+
nothingOrStatement,
|
|
29
|
+
'with'
|
|
30
|
+
);
|
|
31
|
+
return this.withWrapped(
|
|
32
|
+
alias,
|
|
33
|
+
statementOrColumnList,
|
|
34
|
+
nothingOrStatement,
|
|
35
|
+
false
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
@@ -4,7 +4,12 @@ const identity = require('lodash/identity');
|
|
|
4
4
|
const reduce = require('lodash/reduce');
|
|
5
5
|
|
|
6
6
|
const QueryCompiler = require('../../../query/querycompiler');
|
|
7
|
-
const {
|
|
7
|
+
const {
|
|
8
|
+
wrapString,
|
|
9
|
+
columnize: columnize_,
|
|
10
|
+
operator: operator_,
|
|
11
|
+
wrap: wrap_,
|
|
12
|
+
} = require('../../../formatter/wrappingFormatter');
|
|
8
13
|
|
|
9
14
|
class QueryCompiler_PG extends QueryCompiler {
|
|
10
15
|
constructor(client, builder, formatter) {
|
|
@@ -35,7 +40,7 @@ class QueryCompiler_PG extends QueryCompiler {
|
|
|
35
40
|
if (returning) sql += this._returning(returning);
|
|
36
41
|
|
|
37
42
|
return {
|
|
38
|
-
sql
|
|
43
|
+
sql,
|
|
39
44
|
returning,
|
|
40
45
|
};
|
|
41
46
|
}
|
|
@@ -57,9 +62,70 @@ class QueryCompiler_PG extends QueryCompiler {
|
|
|
57
62
|
};
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
|
|
65
|
+
using() {
|
|
66
|
+
const usingTables = this.single.using;
|
|
67
|
+
if (!usingTables) return;
|
|
68
|
+
let sql = 'using ';
|
|
69
|
+
if (Array.isArray(usingTables)) {
|
|
70
|
+
sql += usingTables
|
|
71
|
+
.map((table) => {
|
|
72
|
+
return this.formatter.wrap(table);
|
|
73
|
+
})
|
|
74
|
+
.join(',');
|
|
75
|
+
} else {
|
|
76
|
+
sql += this.formatter.wrap(usingTables);
|
|
77
|
+
}
|
|
78
|
+
return sql;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Compiles an `delete` query, allowing for a return value.
|
|
61
82
|
del() {
|
|
62
|
-
|
|
83
|
+
// Make sure tableName is processed by the formatter first.
|
|
84
|
+
const { tableName } = this;
|
|
85
|
+
const withSQL = this.with();
|
|
86
|
+
let wheres = this.where() || '';
|
|
87
|
+
let using = this.using() || '';
|
|
88
|
+
const joins = this.grouped.join;
|
|
89
|
+
|
|
90
|
+
const tableJoins = [];
|
|
91
|
+
if (Array.isArray(joins)) {
|
|
92
|
+
for (const join of joins) {
|
|
93
|
+
tableJoins.push(
|
|
94
|
+
wrap_(
|
|
95
|
+
this._joinTable(join),
|
|
96
|
+
undefined,
|
|
97
|
+
this.builder,
|
|
98
|
+
this.client,
|
|
99
|
+
this.bindingsHolder
|
|
100
|
+
)
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const joinWheres = [];
|
|
104
|
+
for (const clause of join.clauses) {
|
|
105
|
+
joinWheres.push(
|
|
106
|
+
this.whereBasic({
|
|
107
|
+
column: clause.column,
|
|
108
|
+
operator: '=',
|
|
109
|
+
value: clause.value,
|
|
110
|
+
asColumn: true,
|
|
111
|
+
})
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
if (joinWheres.length > 0) {
|
|
115
|
+
wheres += (wheres ? ' and ' : '') + joinWheres.join(' ');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (tableJoins.length > 0) {
|
|
119
|
+
using += (using ? ',' : 'using ') + tableJoins.join(',');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// With 'using' syntax, no tablename between DELETE and FROM.
|
|
124
|
+
const sql =
|
|
125
|
+
withSQL +
|
|
126
|
+
`delete from ${this.single.only ? 'only ' : ''}${tableName}` +
|
|
127
|
+
(using ? ` ${using}` : '') +
|
|
128
|
+
(wheres ? ` ${wheres}` : '');
|
|
63
129
|
const { returning } = this.single;
|
|
64
130
|
return {
|
|
65
131
|
sql: sql + this._returning(returning),
|
|
@@ -79,13 +145,11 @@ class QueryCompiler_PG extends QueryCompiler {
|
|
|
79
145
|
if (columns === true) {
|
|
80
146
|
return ' on conflict do nothing';
|
|
81
147
|
}
|
|
82
|
-
return ` on conflict
|
|
148
|
+
return ` on conflict ${this._onConflictClause(columns)} do nothing`;
|
|
83
149
|
}
|
|
84
150
|
|
|
85
151
|
_merge(updates, columns, insert) {
|
|
86
|
-
let sql = ` on conflict
|
|
87
|
-
columns
|
|
88
|
-
)}) do update set `;
|
|
152
|
+
let sql = ` on conflict ${this._onConflictClause(columns)} do update set `;
|
|
89
153
|
if (updates && Array.isArray(updates)) {
|
|
90
154
|
sql += updates
|
|
91
155
|
.map((column) =>
|
|
@@ -153,6 +217,10 @@ class QueryCompiler_PG extends QueryCompiler {
|
|
|
153
217
|
return lockMode + (tables.length ? ' of ' + this._tableNames(tables) : '');
|
|
154
218
|
}
|
|
155
219
|
|
|
220
|
+
_groupOrder(item, type) {
|
|
221
|
+
return super._groupOrderNulls(item, type);
|
|
222
|
+
}
|
|
223
|
+
|
|
156
224
|
forUpdate() {
|
|
157
225
|
return this._lockingClause('for update');
|
|
158
226
|
}
|
|
@@ -191,10 +259,14 @@ class QueryCompiler_PG extends QueryCompiler {
|
|
|
191
259
|
schema = this.client.customWrapIdentifier(schema, identity);
|
|
192
260
|
}
|
|
193
261
|
|
|
194
|
-
|
|
262
|
+
const sql =
|
|
195
263
|
'select * from information_schema.columns where table_name = ? and table_catalog = current_database()';
|
|
196
264
|
const bindings = [table];
|
|
197
265
|
|
|
266
|
+
return this._buildColumnInfoQuery(schema, sql, bindings, column);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
_buildColumnInfoQuery(schema, sql, bindings, column) {
|
|
198
270
|
if (schema) {
|
|
199
271
|
sql += ' and table_schema = ?';
|
|
200
272
|
bindings.push(schema);
|
|
@@ -227,6 +299,97 @@ class QueryCompiler_PG extends QueryCompiler {
|
|
|
227
299
|
distinctOn(value) {
|
|
228
300
|
return 'distinct on (' + this.formatter.columnize(value) + ') ';
|
|
229
301
|
}
|
|
302
|
+
|
|
303
|
+
// Json functions
|
|
304
|
+
jsonExtract(params) {
|
|
305
|
+
return this._jsonExtract('jsonb_path_query', params);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
jsonSet(params) {
|
|
309
|
+
return this._jsonSet(
|
|
310
|
+
'jsonb_set',
|
|
311
|
+
Object.assign({}, params, {
|
|
312
|
+
path: this.client.toPathForJson(params.path),
|
|
313
|
+
})
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
jsonInsert(params) {
|
|
318
|
+
return this._jsonSet(
|
|
319
|
+
'jsonb_insert',
|
|
320
|
+
Object.assign({}, params, {
|
|
321
|
+
path: this.client.toPathForJson(params.path),
|
|
322
|
+
})
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
jsonRemove(params) {
|
|
327
|
+
const jsonCol = `${columnize_(
|
|
328
|
+
params.column,
|
|
329
|
+
this.builder,
|
|
330
|
+
this.client,
|
|
331
|
+
this.bindingsHolder
|
|
332
|
+
)} #- ${this.client.parameter(
|
|
333
|
+
this.client.toPathForJson(params.path),
|
|
334
|
+
this.builder,
|
|
335
|
+
this.bindingsHolder
|
|
336
|
+
)}`;
|
|
337
|
+
return params.alias
|
|
338
|
+
? this.client.alias(jsonCol, this.formatter.wrap(params.alias))
|
|
339
|
+
: jsonCol;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
whereJsonPath(statement) {
|
|
343
|
+
let castValue = '';
|
|
344
|
+
if (parseInt(statement.value)) {
|
|
345
|
+
castValue = '::int';
|
|
346
|
+
} else if (parseFloat(statement.value)) {
|
|
347
|
+
castValue = '::float';
|
|
348
|
+
} else {
|
|
349
|
+
castValue = " #>> '{}'";
|
|
350
|
+
}
|
|
351
|
+
return `jsonb_path_query_first(${this._columnClause(
|
|
352
|
+
statement
|
|
353
|
+
)}, ${this.client.parameter(
|
|
354
|
+
statement.jsonPath,
|
|
355
|
+
this.builder,
|
|
356
|
+
this.bindingsHolder
|
|
357
|
+
)})${castValue} ${operator_(
|
|
358
|
+
statement.operator,
|
|
359
|
+
this.builder,
|
|
360
|
+
this.client,
|
|
361
|
+
this.bindingsHolder
|
|
362
|
+
)} ${this._jsonValueClause(statement)}`;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
whereJsonSupersetOf(statement) {
|
|
366
|
+
return this._not(
|
|
367
|
+
statement,
|
|
368
|
+
`${wrap_(
|
|
369
|
+
statement.column,
|
|
370
|
+
undefined,
|
|
371
|
+
this.builder,
|
|
372
|
+
this.client,
|
|
373
|
+
this.bindingsHolder
|
|
374
|
+
)} @> ${this._jsonValueClause(statement)}`
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
whereJsonSubsetOf(statement) {
|
|
379
|
+
return this._not(
|
|
380
|
+
statement,
|
|
381
|
+
`${columnize_(
|
|
382
|
+
statement.column,
|
|
383
|
+
this.builder,
|
|
384
|
+
this.client,
|
|
385
|
+
this.bindingsHolder
|
|
386
|
+
)} <@ ${this._jsonValueClause(statement)}`
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
onJsonPathEquals(clause) {
|
|
391
|
+
return this._onJsonPathEquals('jsonb_path_query_first', clause);
|
|
392
|
+
}
|
|
230
393
|
}
|
|
231
394
|
|
|
232
395
|
module.exports = QueryCompiler_PG;
|