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.
Files changed (78) hide show
  1. package/CHANGELOG.md +90 -1
  2. package/README.md +1 -1
  3. package/UPGRADING.md +7 -0
  4. package/lib/client.js +14 -1
  5. package/lib/constants.js +2 -0
  6. package/lib/dialects/better-sqlite3/index.js +72 -0
  7. package/lib/dialects/cockroachdb/crdb-querycompiler.js +92 -33
  8. package/lib/dialects/cockroachdb/crdb-tablecompiler.js +19 -0
  9. package/lib/dialects/cockroachdb/index.js +13 -0
  10. package/lib/dialects/mssql/index.js +0 -11
  11. package/lib/dialects/mssql/query/mssql-querycompiler.js +122 -64
  12. package/lib/dialects/mssql/schema/mssql-columncompiler.js +41 -6
  13. package/lib/dialects/mssql/schema/mssql-compiler.js +3 -4
  14. package/lib/dialects/mssql/schema/mssql-tablecompiler.js +24 -9
  15. package/lib/dialects/mssql/schema/mssql-viewcompiler.js +15 -1
  16. package/lib/dialects/mysql/query/mysql-querycompiler.js +93 -5
  17. package/lib/dialects/mysql/schema/mysql-columncompiler.js +32 -5
  18. package/lib/dialects/mysql/schema/mysql-tablecompiler.js +33 -6
  19. package/lib/dialects/oracle/query/oracle-querycompiler.js +7 -6
  20. package/lib/dialects/oracle/schema/internal/trigger.js +1 -1
  21. package/lib/dialects/oracle/schema/oracle-columncompiler.js +10 -4
  22. package/lib/dialects/oracle/schema/oracle-tablecompiler.js +17 -6
  23. package/lib/dialects/oracledb/index.js +0 -4
  24. package/lib/dialects/oracledb/query/oracledb-querycompiler.js +89 -0
  25. package/lib/dialects/oracledb/schema/oracledb-columncompiler.js +23 -0
  26. package/lib/dialects/postgres/index.js +21 -6
  27. package/lib/dialects/postgres/query/pg-querybuilder.js +38 -0
  28. package/lib/dialects/postgres/query/pg-querycompiler.js +172 -9
  29. package/lib/dialects/postgres/schema/pg-columncompiler.js +24 -4
  30. package/lib/dialects/postgres/schema/pg-tablecompiler.js +63 -46
  31. package/lib/dialects/redshift/index.js +12 -0
  32. package/lib/dialects/redshift/query/redshift-querycompiler.js +62 -26
  33. package/lib/dialects/redshift/schema/redshift-columncompiler.js +2 -1
  34. package/lib/dialects/redshift/schema/redshift-tablecompiler.js +4 -1
  35. package/lib/dialects/sqlite3/index.js +23 -4
  36. package/lib/dialects/sqlite3/query/sqlite-querybuilder.js +33 -0
  37. package/lib/dialects/sqlite3/query/sqlite-querycompiler.js +87 -22
  38. package/lib/dialects/sqlite3/schema/ddl.js +274 -282
  39. package/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js +18 -8
  40. package/lib/dialects/sqlite3/schema/sqlite-columncompiler.js +20 -0
  41. package/lib/dialects/sqlite3/schema/sqlite-compiler.js +16 -12
  42. package/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js +15 -5
  43. package/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js +31 -2
  44. package/lib/execution/runner.js +37 -2
  45. package/lib/knex-builder/FunctionHelper.js +36 -0
  46. package/lib/migrations/common/MigrationsLoader.js +36 -0
  47. package/lib/migrations/migrate/MigrationGenerator.js +1 -1
  48. package/lib/migrations/migrate/Migrator.js +22 -24
  49. package/lib/migrations/migrate/migration-list-resolver.js +2 -5
  50. package/lib/migrations/migrate/{configuration-merger.js → migrator-configuration-merger.js} +2 -4
  51. package/lib/migrations/migrate/sources/fs-migrations.js +4 -29
  52. package/lib/migrations/migrate/stub/js.stub +8 -1
  53. package/lib/migrations/migrate/stub/knexfile-js.stub +3 -0
  54. package/lib/migrations/migrate/stub/knexfile-ts.stub +5 -2
  55. package/lib/migrations/migrate/table-creator.js +6 -5
  56. package/lib/migrations/seed/Seeder.js +25 -92
  57. package/lib/migrations/seed/seeder-configuration-merger.js +60 -0
  58. package/lib/migrations/seed/sources/fs-seeds.js +65 -0
  59. package/lib/migrations/seed/stub/js.stub +4 -1
  60. package/lib/migrations/util/import-file.js +0 -1
  61. package/lib/query/joinclause.js +24 -5
  62. package/lib/query/method-constants.js +37 -0
  63. package/lib/query/querybuilder.js +292 -53
  64. package/lib/query/querycompiler.js +309 -85
  65. package/lib/schema/columnbuilder.js +14 -1
  66. package/lib/schema/columncompiler.js +132 -5
  67. package/lib/schema/compiler.js +1 -0
  68. package/lib/schema/tablebuilder.js +41 -8
  69. package/lib/schema/tablecompiler.js +61 -4
  70. package/lib/schema/viewcompiler.js +13 -10
  71. package/package.json +37 -27
  72. package/scripts/docker-compose.yml +7 -7
  73. package/scripts/oracledb-install-driver-libs.sh +82 -0
  74. package/scripts/runkit-example.js +1 -1
  75. package/scripts/stress-test/docker-compose.yml +3 -3
  76. package/scripts/stress-test/knex-stress-test.js +1 -1
  77. package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +1 -1
  78. 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
- if (comment.length > 60)
45
+ const MAX_COMMENT_LENGTH = 1024;
46
+ if (comment.length > MAX_COMMENT_LENGTH)
46
47
  this.client.logger.warn(
47
- 'The max length for a table comment is 60 characters'
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
- // Add back the auto increment if the column had it, fix issue #2767
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
- columns
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.client.parameter(
319
- limit,
320
- this.builder,
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
- this.client.parameter(endRow, this.builder, this.bindingsHolder) +
332
+ (this.single.skipBinding['offset']
333
+ ? endRow
334
+ : this.client.parameter(endRow, this.builder, this.bindingsHolder)) +
334
335
  ') ' +
335
336
  'where rownum_ > ' +
336
- this.client.parameter(offset, this.builder, this.bindingsHolder)
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 = true } = {}) {
18
+ increments(options = { primaryKey: true }) {
19
19
  createAutoIncrementTriggerAndSequence(this);
20
- return 'integer not null' + (primaryKey ? ' primary key' : '');
20
+ return (
21
+ 'integer not null' +
22
+ (this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
23
+ );
21
24
  }
22
25
 
23
- bigincrements({ primaryKey = true } = {}) {
26
+ bigincrements(options = { primaryKey: true }) {
24
27
  createAutoIncrementTriggerAndSequence(this);
25
- return 'number(20, 0) not null' + (primaryKey ? ' primary key' : '');
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
- columns
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
- if (returning === '*' || Array.isArray(returning)) {
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 { wrapString } = require('../../../formatter/wrappingFormatter');
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: 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
- // Compiles an `update` query, allowing for a return value.
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
- const sql = super.del(...arguments);
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 (${this.formatter.columnize(columns)}) do nothing`;
148
+ return ` on conflict ${this._onConflictClause(columns)} do nothing`;
83
149
  }
84
150
 
85
151
  _merge(updates, columns, insert) {
86
- let sql = ` on conflict (${this.formatter.columnize(
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
- let sql =
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;