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
@@ -10,6 +10,7 @@ class ColumnCompiler_PG extends ColumnCompiler {
10
10
  constructor(client, tableCompiler, columnBuilder) {
11
11
  super(client, tableCompiler, columnBuilder);
12
12
  this.modifiers = ['nullable', 'defaultTo', 'comment'];
13
+ this._addCheckModifiers();
13
14
  }
14
15
 
15
16
  // Types
@@ -64,6 +65,15 @@ class ColumnCompiler_PG extends ColumnCompiler {
64
65
  return jsonColumn(this.client, true);
65
66
  }
66
67
 
68
+ checkRegex(regex, constraintName) {
69
+ return this._check(
70
+ `${this.formatter.wrap(
71
+ this.getColumnName()
72
+ )} ~ ${this.client._escapeBinding(regex)}`,
73
+ constraintName
74
+ );
75
+ }
76
+
67
77
  datetime(withoutTz = false, precision) {
68
78
  let useTz;
69
79
  if (isObject(withoutTz)) {
@@ -100,12 +110,22 @@ class ColumnCompiler_PG extends ColumnCompiler {
100
110
  );
101
111
  }, comment);
102
112
  }
113
+
114
+ increments(options = { primaryKey: true }) {
115
+ return (
116
+ 'serial' +
117
+ (this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
118
+ );
119
+ }
120
+
121
+ bigincrements(options = { primaryKey: true }) {
122
+ return (
123
+ 'bigserial' +
124
+ (this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
125
+ );
126
+ }
103
127
  }
104
128
 
105
- ColumnCompiler_PG.prototype.bigincrements = ({ primaryKey = true } = {}) =>
106
- 'bigserial' + (primaryKey ? ' primary key' : '');
107
- ColumnCompiler_PG.prototype.increments = ({ primaryKey = true } = {}) =>
108
- 'serial' + (primaryKey ? ' primary key' : '');
109
129
  ColumnCompiler_PG.prototype.bigint = 'bigint';
110
130
  ColumnCompiler_PG.prototype.binary = 'bytea';
111
131
  ColumnCompiler_PG.prototype.bool = 'boolean';
@@ -44,12 +44,16 @@ class TableCompiler_PG extends TableCompiler {
44
44
  const createStatement = ifNot
45
45
  ? 'create table if not exists '
46
46
  : 'create table ';
47
- const columnsSql = ' (' + columns.sql.join(', ') + ')';
47
+ const columnsSql = ' (' + columns.sql.join(', ') + this._addChecks() + ')';
48
48
  let sql =
49
49
  createStatement +
50
50
  this.tableName() +
51
51
  (like && this.tableNameLike()
52
- ? ' (like ' + this.tableNameLike() + ' including all)'
52
+ ? ' (like ' +
53
+ this.tableNameLike() +
54
+ ' including all' +
55
+ (columns.sql.length ? ', ' + columns.sql.join(', ') : '') +
56
+ ')'
53
57
  : columnsSql);
54
58
  if (this.single.inherits)
55
59
  sql += ` inherits (${this.formatter.wrap(this.single.inherits)})`;
@@ -65,55 +69,68 @@ class TableCompiler_PG extends TableCompiler {
65
69
  if (prefix === this.alterColumnsPrefix) {
66
70
  // alter columns
67
71
  for (const col of colCompilers) {
68
- const quotedTableName = this.tableName();
69
- const type = col.getColumnType();
70
- // We'd prefer to call this.formatter.wrapAsIdentifier here instead, however the context passed to
71
- // `this` instance is not that of the column, but of the table. Thus, we unfortunately have to call
72
- // `wrapIdentifier` here as well (it is already called once on the initial column operation) to give
73
- // our `alter` operation the correct `queryContext`. Refer to issue #2606 and PR #2612.
74
- const colName = this.client.wrapIdentifier(
75
- col.getColumnName(),
76
- col.columnBuilder.queryContext()
77
- );
78
-
79
- // To alter enum columns they must be cast to text first
80
- const isEnum = col.type === 'enu';
72
+ this._addColumn(col);
73
+ }
74
+ } else {
75
+ // base class implementation for normal add
76
+ super.addColumns(columns, prefix);
77
+ }
78
+ }
81
79
 
80
+ _addColumn(col) {
81
+ const quotedTableName = this.tableName();
82
+ const type = col.getColumnType();
83
+ // We'd prefer to call this.formatter.wrapAsIdentifier here instead, however the context passed to
84
+ // `this` instance is not that of the column, but of the table. Thus, we unfortunately have to call
85
+ // `wrapIdentifier` here as well (it is already called once on the initial column operation) to give
86
+ // our `alter` operation the correct `queryContext`. Refer to issue #2606 and PR #2612.
87
+ const colName = this.client.wrapIdentifier(
88
+ col.getColumnName(),
89
+ col.columnBuilder.queryContext()
90
+ );
91
+
92
+ // To alter enum columns they must be cast to text first
93
+ const isEnum = col.type === 'enu';
94
+ this.pushQuery({
95
+ sql: `alter table ${quotedTableName} alter column ${colName} drop default`,
96
+ bindings: [],
97
+ });
98
+
99
+ const alterNullable = col.columnBuilder.alterNullable;
100
+ if (alterNullable) {
101
+ this.pushQuery({
102
+ sql: `alter table ${quotedTableName} alter column ${colName} drop not null`,
103
+ bindings: [],
104
+ });
105
+ }
106
+
107
+ const alterType = col.columnBuilder.alterType;
108
+ if (alterType) {
109
+ this.pushQuery({
110
+ sql: `alter table ${quotedTableName} alter column ${colName} type ${type} using (${colName}${
111
+ isEnum ? '::text::' : '::'
112
+ }${type})`,
113
+ bindings: [],
114
+ });
115
+ }
116
+
117
+ const defaultTo = col.modified['defaultTo'];
118
+ if (defaultTo) {
119
+ const modifier = col.defaultTo.apply(col, defaultTo);
120
+ this.pushQuery({
121
+ sql: `alter table ${quotedTableName} alter column ${colName} set ${modifier}`,
122
+ bindings: [],
123
+ });
124
+ }
125
+
126
+ if (alterNullable) {
127
+ const nullable = col.modified['nullable'];
128
+ if (nullable && nullable[0] === false) {
82
129
  this.pushQuery({
83
- sql: `alter table ${quotedTableName} alter column ${colName} drop default`,
84
- bindings: [],
85
- });
86
- this.pushQuery({
87
- sql: `alter table ${quotedTableName} alter column ${colName} drop not null`,
88
- bindings: [],
89
- });
90
- this.pushQuery({
91
- sql: `alter table ${quotedTableName} alter column ${colName} type ${type} using (${colName}${
92
- isEnum ? '::text::' : '::'
93
- }${type})`,
130
+ sql: `alter table ${quotedTableName} alter column ${colName} set not null`,
94
131
  bindings: [],
95
132
  });
96
-
97
- const defaultTo = col.modified['defaultTo'];
98
- if (defaultTo) {
99
- const modifier = col.defaultTo.apply(col, defaultTo);
100
- this.pushQuery({
101
- sql: `alter table ${quotedTableName} alter column ${colName} set ${modifier}`,
102
- bindings: [],
103
- });
104
- }
105
-
106
- const nullable = col.modified['nullable'];
107
- if (nullable && nullable[0] === false) {
108
- this.pushQuery({
109
- sql: `alter table ${quotedTableName} alter column ${colName} set not null`,
110
- bindings: [],
111
- });
112
- }
113
133
  }
114
- } else {
115
- // base class implementation for normal add
116
- super.addColumns(columns, prefix);
117
134
  }
118
135
  }
119
136
 
@@ -63,6 +63,18 @@ class Client_Redshift extends Client_PG {
63
63
  }
64
64
  return resp;
65
65
  }
66
+
67
+ toPathForJson(jsonPath, builder, bindingsHolder) {
68
+ return jsonPath
69
+ .replace(/^(\$\.)/, '') // remove the first dollar
70
+ .split('.')
71
+ .map(
72
+ function (v) {
73
+ return this.parameter(v, builder, bindingsHolder);
74
+ }.bind(this)
75
+ )
76
+ .join(', ');
77
+ }
66
78
  }
67
79
 
68
80
  Object.assign(Client_Redshift.prototype, {
@@ -4,7 +4,9 @@ const QueryCompiler = require('../../../query/querycompiler');
4
4
  const QueryCompiler_PG = require('../../postgres/query/pg-querycompiler');
5
5
 
6
6
  const identity = require('lodash/identity');
7
- const reduce = require('lodash/reduce');
7
+ const {
8
+ columnize: columnize_,
9
+ } = require('../../../formatter/wrappingFormatter');
8
10
 
9
11
  class QueryCompiler_Redshift extends QueryCompiler_PG {
10
12
  truncate() {
@@ -87,40 +89,74 @@ class QueryCompiler_Redshift extends QueryCompiler_PG {
87
89
  schema = this.client.customWrapIdentifier(schema, identity);
88
90
  }
89
91
 
90
- let sql =
92
+ const sql =
91
93
  'select * from information_schema.columns where table_name = ? and table_catalog = ?';
92
94
  const bindings = [
93
95
  table.toLowerCase(),
94
96
  this.client.database().toLowerCase(),
95
97
  ];
96
98
 
97
- if (schema) {
98
- sql += ' and table_schema = ?';
99
- bindings.push(schema);
99
+ return this._buildColumnInfoQuery(schema, sql, bindings, column);
100
+ }
101
+
102
+ jsonExtract(params) {
103
+ let extractions;
104
+ if (Array.isArray(params.column)) {
105
+ extractions = params.column;
100
106
  } else {
101
- sql += ' and table_schema = current_schema()';
107
+ extractions = [params];
102
108
  }
109
+ return extractions
110
+ .map((extraction) => {
111
+ const jsonCol = `json_extract_path_text(${columnize_(
112
+ extraction.column || extraction[0],
113
+ this.builder,
114
+ this.client,
115
+ this.bindingsHolder
116
+ )}, ${this.client.toPathForJson(
117
+ params.path || extraction[1],
118
+ this.builder,
119
+ this.bindingsHolder
120
+ )})`;
121
+ const alias = extraction.alias || extraction[2];
122
+ return alias
123
+ ? this.client.alias(jsonCol, this.formatter.wrap(alias))
124
+ : jsonCol;
125
+ })
126
+ .join(', ');
127
+ }
103
128
 
104
- return {
105
- sql,
106
- bindings,
107
- output(resp) {
108
- const out = reduce(
109
- resp.rows,
110
- function (columns, val) {
111
- columns[val.column_name] = {
112
- type: val.data_type,
113
- maxLength: val.character_maximum_length,
114
- nullable: val.is_nullable === 'YES',
115
- defaultValue: val.column_default,
116
- };
117
- return columns;
118
- },
119
- {}
120
- );
121
- return (column && out[column]) || out;
122
- },
123
- };
129
+ jsonSet(params) {
130
+ throw new Error('Json set is not supported by Redshift');
131
+ }
132
+
133
+ jsonInsert(params) {
134
+ throw new Error('Json insert is not supported by Redshift');
135
+ }
136
+
137
+ jsonRemove(params) {
138
+ throw new Error('Json remove is not supported by Redshift');
139
+ }
140
+
141
+ whereJsonPath(statement) {
142
+ return this._whereJsonPath(
143
+ 'json_extract_path_text',
144
+ Object.assign({}, statement, {
145
+ path: this.client.toPathForJson(statement.path),
146
+ })
147
+ );
148
+ }
149
+
150
+ whereJsonSupersetOf(statement) {
151
+ throw new Error('Json superset is not supported by Redshift');
152
+ }
153
+
154
+ whereJsonSubsetOf(statement) {
155
+ throw new Error('Json subset is not supported by Redshift');
156
+ }
157
+
158
+ onJsonPathEquals(clause) {
159
+ return this._onJsonPathEquals('json_extract_path_text', clause);
124
160
  }
125
161
  }
126
162
 
@@ -2,6 +2,7 @@
2
2
  // -------
3
3
 
4
4
  const ColumnCompiler_PG = require('../../postgres/schema/pg-columncompiler');
5
+ const ColumnCompiler = require('../../../schema/columncompiler');
5
6
 
6
7
  class ColumnCompiler_Redshift extends ColumnCompiler_PG {
7
8
  constructor() {
@@ -54,7 +55,7 @@ ColumnCompiler_Redshift.prototype.mediumblob = 'varchar(16777218)';
54
55
  ColumnCompiler_Redshift.prototype.set = 'text';
55
56
  ColumnCompiler_Redshift.prototype.text = 'varchar(max)';
56
57
  ColumnCompiler_Redshift.prototype.tinyblob = 'varchar(256)';
57
- ColumnCompiler_Redshift.prototype.uuid = 'char(36)';
58
+ ColumnCompiler_Redshift.prototype.uuid = ColumnCompiler.prototype.uuid;
58
59
  ColumnCompiler_Redshift.prototype.varbinary = 'varchar(max)';
59
60
  ColumnCompiler_Redshift.prototype.bigint = 'bigint';
60
61
  ColumnCompiler_Redshift.prototype.bool = 'boolean';
@@ -30,7 +30,7 @@ class TableCompiler_Redshift extends TableCompiler_PG {
30
30
  const createStatement = ifNot
31
31
  ? 'create table if not exists '
32
32
  : 'create table ';
33
- const columnsSql = ' (' + columns.sql.join(', ') + ')';
33
+ const columnsSql = ' (' + columns.sql.join(', ') + this._addChecks() + ')';
34
34
  let sql =
35
35
  createStatement +
36
36
  this.tableName() +
@@ -45,6 +45,9 @@ class TableCompiler_Redshift extends TableCompiler_PG {
45
45
  });
46
46
  const hasComment = has(this.single, 'comment');
47
47
  if (hasComment) this.comment(this.single.comment);
48
+ if (like) {
49
+ this.addColumns(columns, this.addColumnsPrefix);
50
+ }
48
51
  }
49
52
 
50
53
  primary(columns, constraintName) {
@@ -15,6 +15,7 @@ const TableCompiler = require('./schema/sqlite-tablecompiler');
15
15
  const ViewCompiler = require('./schema/sqlite-viewcompiler');
16
16
  const SQLite3_DDL = require('./schema/ddl');
17
17
  const Formatter = require('../../formatter');
18
+ const QueryBuilder = require('./query/sqlite-querybuilder');
18
19
 
19
20
  class Client_SQLite3 extends Client {
20
21
  constructor(config) {
@@ -29,7 +30,7 @@ class Client_SQLite3 extends Client {
29
30
  }
30
31
 
31
32
  _driver() {
32
- return require('sqlite3');
33
+ return require('@vscode/sqlite3');
33
34
  }
34
35
 
35
36
  schemaCompiler() {
@@ -44,6 +45,10 @@ class Client_SQLite3 extends Client {
44
45
  return new SqliteQueryCompiler(this, builder, formatter);
45
46
  }
46
47
 
48
+ queryBuilder() {
49
+ return new QueryBuilder(this);
50
+ }
51
+
47
52
  viewCompiler(builder, formatter) {
48
53
  return new ViewCompiler(this, builder, formatter);
49
54
  }
@@ -132,6 +137,7 @@ class Client_SQLite3 extends Client {
132
137
  // We need the context here, as it contains
133
138
  // the "this.lastID" or "this.changes"
134
139
  obj.context = this;
140
+
135
141
  return resolver(obj);
136
142
  });
137
143
  });
@@ -144,6 +150,7 @@ class Client_SQLite3 extends Client {
144
150
  return new Promise(function (resolver, rejecter) {
145
151
  stream.on('error', rejecter);
146
152
  stream.on('end', resolver);
153
+
147
154
  return client
148
155
  ._query(connection, obj)
149
156
  .then((obj) => obj.response)
@@ -160,7 +167,7 @@ class Client_SQLite3 extends Client {
160
167
  // Ensures the response is returned in the same format as other clients.
161
168
  processResponse(obj, runner) {
162
169
  const ctx = obj.context;
163
- const { response } = obj;
170
+ const { response, returning } = obj;
164
171
  if (obj.output) return obj.output.call(runner, response);
165
172
  switch (obj.method) {
166
173
  case 'select':
@@ -169,14 +176,26 @@ class Client_SQLite3 extends Client {
169
176
  return response[0];
170
177
  case 'pluck':
171
178
  return map(response, obj.pluck);
172
- case 'insert':
179
+ case 'insert': {
180
+ if (returning) {
181
+ if (response) {
182
+ return response;
183
+ }
184
+
185
+ // ToDo Implement after https://github.com/microsoft/vscode-node-sqlite3/issues/15 is resolved
186
+ this.logger.warn(
187
+ 'node-sqlite3 does not currently support RETURNING clause'
188
+ );
189
+ }
173
190
  return [ctx.lastID];
191
+ }
174
192
  case 'del':
175
193
  case 'update':
176
194
  case 'counter':
177
195
  return ctx.changes;
178
- default:
196
+ default: {
179
197
  return response;
198
+ }
180
199
  }
181
200
  }
182
201
 
@@ -0,0 +1,33 @@
1
+ const QueryBuilder = require('../../../query/querybuilder.js');
2
+
3
+ module.exports = class QueryBuilder_SQLite3 extends QueryBuilder {
4
+ withMaterialized(alias, statementOrColumnList, nothingOrStatement) {
5
+ this._validateWithArgs(
6
+ alias,
7
+ statementOrColumnList,
8
+ nothingOrStatement,
9
+ 'with'
10
+ );
11
+ return this.withWrapped(
12
+ alias,
13
+ statementOrColumnList,
14
+ nothingOrStatement,
15
+ true
16
+ );
17
+ }
18
+
19
+ withNotMaterialized(alias, statementOrColumnList, nothingOrStatement) {
20
+ this._validateWithArgs(
21
+ alias,
22
+ statementOrColumnList,
23
+ nothingOrStatement,
24
+ 'with'
25
+ );
26
+ return this.withWrapped(
27
+ alias,
28
+ statementOrColumnList,
29
+ nothingOrStatement,
30
+ false
31
+ );
32
+ }
33
+ };
@@ -9,7 +9,10 @@ const reduce = require('lodash/reduce');
9
9
  const QueryCompiler = require('../../../query/querycompiler');
10
10
  const noop = require('../../../util/noop');
11
11
  const { isString } = require('../../../util/is');
12
- const { wrapString } = require('../../../formatter/wrappingFormatter');
12
+ const {
13
+ wrapString,
14
+ columnize: columnize_,
15
+ } = require('../../../formatter/wrappingFormatter');
13
16
 
14
17
  const emptyStr = constant('');
15
18
 
@@ -17,14 +20,6 @@ class QueryCompiler_SQLite3 extends QueryCompiler {
17
20
  constructor(client, builder, formatter) {
18
21
  super(client, builder, formatter);
19
22
 
20
- const { returning } = this.single;
21
-
22
- if (returning) {
23
- this.client.logger.warn(
24
- '.returning() is not supported by sqlite3 and will not have any effect.'
25
- );
26
- }
27
-
28
23
  // The locks are not applicable in SQLite3
29
24
  this.forShare = emptyStr;
30
25
  this.forKeyShare = emptyStr;
@@ -47,20 +42,28 @@ class QueryCompiler_SQLite3 extends QueryCompiler {
47
42
  insertValues[0] &&
48
43
  isEmpty(insertValues[0])
49
44
  ) {
50
- return sql + this._emptyInsertValue;
45
+ return {
46
+ sql: sql + this._emptyInsertValue,
47
+ };
51
48
  }
52
49
  } else if (typeof insertValues === 'object' && isEmpty(insertValues)) {
53
- return sql + this._emptyInsertValue;
50
+ return {
51
+ sql: sql + this._emptyInsertValue,
52
+ };
54
53
  }
55
54
 
56
55
  const insertData = this._prepInsert(insertValues);
57
56
 
58
57
  if (isString(insertData)) {
59
- return sql + insertData;
58
+ return {
59
+ sql: sql + insertData,
60
+ };
60
61
  }
61
62
 
62
63
  if (insertData.columns.length === 0) {
63
- return '';
64
+ return {
65
+ sql: '',
66
+ };
64
67
  }
65
68
 
66
69
  sql += `(${this.formatter.columnize(insertData.columns)})`;
@@ -96,7 +99,15 @@ class QueryCompiler_SQLite3 extends QueryCompiler {
96
99
  if (wheres) sql += ` ${wheres}`;
97
100
  }
98
101
 
99
- return sql;
102
+ const { returning } = this.single;
103
+ if (returning) {
104
+ sql += this._returning(returning);
105
+ }
106
+
107
+ return {
108
+ sql,
109
+ returning,
110
+ };
100
111
  }
101
112
 
102
113
  const blocks = [];
@@ -129,20 +140,24 @@ class QueryCompiler_SQLite3 extends QueryCompiler {
129
140
  ' where true' + this._merge(merge.updates, onConflict, insertValues);
130
141
  }
131
142
 
132
- return sql;
143
+ const { returning } = this.single;
144
+ if (returning) sql += this._returning(returning);
145
+
146
+ return {
147
+ sql,
148
+ returning,
149
+ };
133
150
  }
134
151
 
135
152
  _ignore(columns) {
136
153
  if (columns === true) {
137
154
  return ' on conflict do nothing';
138
155
  }
139
- return ` on conflict (${this.formatter.columnize(columns)}) do nothing`;
156
+ return ` on conflict ${this._onConflictClause(columns)} do nothing`;
140
157
  }
141
158
 
142
159
  _merge(updates, columns, insert) {
143
- let sql = ` on conflict (${this.formatter.columnize(
144
- columns
145
- )}) do update set `;
160
+ let sql = ` on conflict ${this._onConflictClause(columns)} do update set `;
146
161
  if (updates && Array.isArray(updates)) {
147
162
  sql += updates
148
163
  .map((column) =>
@@ -185,6 +200,10 @@ class QueryCompiler_SQLite3 extends QueryCompiler {
185
200
  }
186
201
  }
187
202
 
203
+ _returning(value) {
204
+ return value ? ` returning ${this.formatter.columnize(value)}` : '';
205
+ }
206
+
188
207
  // Compile a truncate table statement into SQL.
189
208
  truncate() {
190
209
  const { table } = this.single;
@@ -241,11 +260,57 @@ class QueryCompiler_SQLite3 extends QueryCompiler {
241
260
 
242
261
  // Workaround for offset only,
243
262
  // see http://stackoverflow.com/questions/10491492/sqllite-with-skip-offset-only-not-limit
244
- return `limit ${this.client.parameter(
245
- noLimit ? -1 : this.single.limit,
263
+ this.single.limit = noLimit ? -1 : this.single.limit;
264
+ return `limit ${this._getValueOrParameterFromAttribute('limit')}`;
265
+ }
266
+
267
+ // Json functions
268
+ jsonExtract(params) {
269
+ return this._jsonExtract('json_extract', params);
270
+ }
271
+
272
+ jsonSet(params) {
273
+ return this._jsonSet('json_set', params);
274
+ }
275
+
276
+ jsonInsert(params) {
277
+ return this._jsonSet('json_insert', params);
278
+ }
279
+
280
+ jsonRemove(params) {
281
+ const jsonCol = `json_remove(${columnize_(
282
+ params.column,
283
+ this.builder,
284
+ this.client,
285
+ this.bindingsHolder
286
+ )},${this.client.parameter(
287
+ params.path,
246
288
  this.builder,
247
289
  this.bindingsHolder
248
- )}`;
290
+ )})`;
291
+ return params.alias
292
+ ? this.client.alias(jsonCol, this.formatter.wrap(params.alias))
293
+ : jsonCol;
294
+ }
295
+
296
+ whereJsonPath(statement) {
297
+ return this._whereJsonPath('json_extract', statement);
298
+ }
299
+
300
+ whereJsonSupersetOf(statement) {
301
+ throw new Error(
302
+ 'Json superset where clause not actually supported by SQLite'
303
+ );
304
+ }
305
+
306
+ whereJsonSubsetOf(statement) {
307
+ throw new Error(
308
+ 'Json subset where clause not actually supported by SQLite'
309
+ );
310
+ }
311
+
312
+ onJsonPathEquals(clause) {
313
+ return this._onJsonPathEquals('json_extract', clause);
249
314
  }
250
315
  }
251
316