knex 0.21.20 → 0.21.21

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 (141) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/CONTRIBUTING.md +184 -184
  3. package/LICENSE +22 -22
  4. package/README.md +95 -95
  5. package/bin/cli.js +414 -414
  6. package/bin/utils/cli-config-utils.js +151 -151
  7. package/bin/utils/constants.js +7 -7
  8. package/bin/utils/migrationsLister.js +37 -37
  9. package/knex.js +8 -8
  10. package/lib/client.js +413 -413
  11. package/lib/config-resolver.js +61 -61
  12. package/lib/constants.js +44 -44
  13. package/lib/dialects/mssql/index.js +390 -390
  14. package/lib/dialects/mssql/query/compiler.js +444 -444
  15. package/lib/dialects/mssql/schema/columncompiler.js +103 -103
  16. package/lib/dialects/mssql/schema/compiler.js +59 -59
  17. package/lib/dialects/mssql/schema/tablecompiler.js +245 -245
  18. package/lib/dialects/mssql/transaction.js +97 -97
  19. package/lib/dialects/mysql/index.js +191 -191
  20. package/lib/dialects/mysql/query/compiler.js +142 -142
  21. package/lib/dialects/mysql/schema/columncompiler.js +171 -171
  22. package/lib/dialects/mysql/schema/compiler.js +60 -60
  23. package/lib/dialects/mysql/schema/tablecompiler.js +262 -262
  24. package/lib/dialects/mysql/transaction.js +48 -48
  25. package/lib/dialects/mysql2/index.js +35 -35
  26. package/lib/dialects/mysql2/transaction.js +46 -46
  27. package/lib/dialects/oracle/DEAD_CODE.md +5 -5
  28. package/lib/dialects/oracle/formatter.js +20 -20
  29. package/lib/dialects/oracle/index.js +79 -79
  30. package/lib/dialects/oracle/query/compiler.js +327 -327
  31. package/lib/dialects/oracle/schema/columnbuilder.js +18 -18
  32. package/lib/dialects/oracle/schema/columncompiler.js +139 -139
  33. package/lib/dialects/oracle/schema/compiler.js +81 -81
  34. package/lib/dialects/oracle/schema/tablecompiler.js +165 -165
  35. package/lib/dialects/oracle/schema/trigger.js +126 -126
  36. package/lib/dialects/oracle/utils.js +86 -86
  37. package/lib/dialects/oracledb/index.js +489 -489
  38. package/lib/dialects/oracledb/query/compiler.js +363 -363
  39. package/lib/dialects/oracledb/schema/columncompiler.js +35 -35
  40. package/lib/dialects/oracledb/transaction.js +76 -76
  41. package/lib/dialects/oracledb/utils.js +14 -14
  42. package/lib/dialects/postgres/index.js +319 -319
  43. package/lib/dialects/postgres/query/compiler.js +206 -206
  44. package/lib/dialects/postgres/schema/columncompiler.js +125 -125
  45. package/lib/dialects/postgres/schema/compiler.js +109 -109
  46. package/lib/dialects/postgres/schema/tablecompiler.js +183 -183
  47. package/lib/dialects/redshift/index.js +73 -73
  48. package/lib/dialects/redshift/query/compiler.js +119 -119
  49. package/lib/dialects/redshift/schema/columnbuilder.js +20 -20
  50. package/lib/dialects/redshift/schema/columncompiler.js +60 -60
  51. package/lib/dialects/redshift/schema/compiler.js +14 -14
  52. package/lib/dialects/redshift/schema/tablecompiler.js +123 -123
  53. package/lib/dialects/redshift/transaction.js +18 -18
  54. package/lib/dialects/sqlite3/formatter.js +21 -21
  55. package/lib/dialects/sqlite3/index.js +169 -169
  56. package/lib/dialects/sqlite3/query/compiler.js +222 -222
  57. package/lib/dialects/sqlite3/schema/columncompiler.js +27 -27
  58. package/lib/dialects/sqlite3/schema/compiler.js +49 -49
  59. package/lib/dialects/sqlite3/schema/ddl.js +525 -525
  60. package/lib/dialects/sqlite3/schema/tablecompiler.js +238 -238
  61. package/lib/formatter.js +295 -295
  62. package/lib/functionhelper.js +14 -14
  63. package/lib/helpers.js +92 -92
  64. package/lib/index.js +3 -3
  65. package/lib/interface.js +115 -115
  66. package/lib/knex.js +42 -42
  67. package/lib/logger.js +76 -76
  68. package/lib/migrate/MigrationGenerator.js +82 -82
  69. package/lib/migrate/Migrator.js +611 -611
  70. package/lib/migrate/configuration-merger.js +60 -60
  71. package/lib/migrate/migrate-stub.js +17 -17
  72. package/lib/migrate/migration-list-resolver.js +36 -36
  73. package/lib/migrate/sources/fs-migrations.js +99 -99
  74. package/lib/migrate/stub/cjs.stub +15 -15
  75. package/lib/migrate/stub/coffee.stub +13 -13
  76. package/lib/migrate/stub/eg.stub +14 -14
  77. package/lib/migrate/stub/js.stub +15 -15
  78. package/lib/migrate/stub/knexfile-coffee.stub +34 -34
  79. package/lib/migrate/stub/knexfile-eg.stub +43 -43
  80. package/lib/migrate/stub/knexfile-js.stub +44 -44
  81. package/lib/migrate/stub/knexfile-ls.stub +35 -35
  82. package/lib/migrate/stub/knexfile-ts.stub +44 -44
  83. package/lib/migrate/stub/ls.stub +14 -14
  84. package/lib/migrate/stub/ts.stub +21 -21
  85. package/lib/migrate/table-creator.js +67 -67
  86. package/lib/migrate/table-resolver.js +27 -27
  87. package/lib/query/builder.js +1372 -1372
  88. package/lib/query/compiler.js +889 -889
  89. package/lib/query/constants.js +13 -13
  90. package/lib/query/joinclause.js +263 -263
  91. package/lib/query/methods.js +92 -92
  92. package/lib/query/string.js +190 -190
  93. package/lib/raw.js +188 -188
  94. package/lib/ref.js +39 -39
  95. package/lib/runner.js +285 -285
  96. package/lib/schema/builder.js +82 -82
  97. package/lib/schema/columnbuilder.js +117 -117
  98. package/lib/schema/columncompiler.js +177 -177
  99. package/lib/schema/compiler.js +101 -101
  100. package/lib/schema/helpers.js +51 -51
  101. package/lib/schema/tablebuilder.js +288 -288
  102. package/lib/schema/tablecompiler.js +296 -296
  103. package/lib/seed/Seeder.js +203 -203
  104. package/lib/seed/seed-stub.js +13 -13
  105. package/lib/seed/stub/coffee.stub +9 -9
  106. package/lib/seed/stub/eg.stub +11 -11
  107. package/lib/seed/stub/js.stub +13 -13
  108. package/lib/seed/stub/ls.stub +11 -11
  109. package/lib/seed/stub/ts.stub +13 -13
  110. package/lib/transaction.js +363 -363
  111. package/lib/util/batchInsert.js +59 -59
  112. package/lib/util/delay.js +6 -6
  113. package/lib/util/fake-client.js +9 -9
  114. package/lib/util/finally-mixin.js +13 -13
  115. package/lib/util/fs.js +76 -76
  116. package/lib/util/import-file.js +13 -13
  117. package/lib/util/is-module-type.js +14 -14
  118. package/lib/util/is.js +32 -32
  119. package/lib/util/make-knex.js +338 -338
  120. package/lib/util/nanoid.js +29 -29
  121. package/lib/util/noop.js +1 -1
  122. package/lib/util/parse-connection.js +66 -66
  123. package/lib/util/save-async-stack.js +14 -14
  124. package/lib/util/template.js +52 -52
  125. package/lib/util/timeout.js +29 -29
  126. package/lib/util/timestamp.js +16 -16
  127. package/package.json +1 -1
  128. package/scripts/build.js +125 -125
  129. package/scripts/docker-compose.yml +111 -111
  130. package/scripts/next-release-howto.md +24 -24
  131. package/scripts/release.sh +34 -34
  132. package/scripts/runkit-example.js +34 -34
  133. package/scripts/stress-test/README.txt +18 -18
  134. package/scripts/stress-test/docker-compose.yml +47 -47
  135. package/scripts/stress-test/knex-stress-test.js +196 -196
  136. package/scripts/stress-test/mysql2-random-hanging-every-now-and-then.js +145 -145
  137. package/scripts/stress-test/mysql2-sudden-exit-without-error.js +100 -100
  138. package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +184 -184
  139. package/types/index.d.ts +2249 -2249
  140. package/types/result.d.ts +27 -27
  141. package/types/tables.d.ts +4 -4
@@ -1,1372 +1,1372 @@
1
- // Builder
2
- // -------
3
- const assert = require('assert');
4
- const { inherits } = require('util');
5
- const { EventEmitter } = require('events');
6
-
7
- const Raw = require('../raw');
8
- const helpers = require('../helpers');
9
- const JoinClause = require('./joinclause');
10
- const assign = require('lodash/assign');
11
- const clone = require('lodash/clone');
12
- const each = require('lodash/each');
13
- const isEmpty = require('lodash/isEmpty');
14
- const isPlainObject = require('lodash/isPlainObject');
15
- const last = require('lodash/last');
16
- const reject = require('lodash/reject');
17
- const tail = require('lodash/tail');
18
- const toArray = require('lodash/toArray');
19
- const saveAsyncStack = require('../util/save-async-stack');
20
- const { isBoolean, isNumber, isObject, isString } = require('../util/is');
21
-
22
- const { lockMode, waitMode } = require('./constants');
23
-
24
- // Sub-builder for onConflict clauses
25
- function OnConflictBuilder(builder, columns) {
26
- this.builder = builder;
27
- this._columns = columns;
28
- }
29
-
30
- assign(OnConflictBuilder.prototype, {
31
- // Sets insert query to ignore conflicts
32
- ignore() {
33
- this.builder._single.onConflict = this._columns;
34
- this.builder._single.ignore = true;
35
- return this.builder;
36
- },
37
-
38
- // Sets insert query to update on conflict
39
- merge(updates) {
40
- this.builder._single.onConflict = this._columns;
41
- this.builder._single.merge = { updates };
42
- return this.builder;
43
- },
44
-
45
- // Prevent
46
- then() {
47
- throw new Error(
48
- 'Incomplete onConflict clause. .onConflict() must be diretly followed by either .merge() or .ignore()'
49
- );
50
- },
51
- });
52
-
53
- // Typically called from `knex.builder`,
54
- // start a new query building chain.
55
- function Builder(client) {
56
- this.client = client;
57
- this.and = this;
58
- this._single = {};
59
- this._statements = [];
60
- this._method = 'select';
61
- if (client.config) {
62
- saveAsyncStack(this, 5);
63
- this._debug = client.config.debug;
64
- }
65
- // Internal flags used in the builder.
66
- this._joinFlag = 'inner';
67
- this._boolFlag = 'and';
68
- this._notFlag = false;
69
- this._asColumnFlag = false;
70
- }
71
-
72
- inherits(Builder, EventEmitter);
73
-
74
- const validateWithArgs = function (alias, statement, method) {
75
- if (typeof alias !== 'string') {
76
- throw new Error(`${method}() first argument must be a string`);
77
- }
78
- if (
79
- typeof statement === 'function' ||
80
- statement instanceof Builder ||
81
- statement instanceof Raw
82
- ) {
83
- return;
84
- }
85
- throw new Error(
86
- `${method}() second argument must be a function / QueryBuilder or a raw`
87
- );
88
- };
89
-
90
- assign(Builder.prototype, {
91
- toString() {
92
- return this.toQuery();
93
- },
94
-
95
- // Convert the current query "toSQL"
96
- toSQL(method, tz) {
97
- return this.client.queryCompiler(this).toSQL(method || this._method, tz);
98
- },
99
-
100
- // Create a shallow clone of the current query builder.
101
- clone() {
102
- const cloned = new this.constructor(this.client);
103
- cloned._method = this._method;
104
- cloned._single = clone(this._single);
105
- cloned._statements = clone(this._statements);
106
- cloned._debug = this._debug;
107
-
108
- // `_option` is assigned by the `Interface` mixin.
109
- if (this._options !== undefined) {
110
- cloned._options = clone(this._options);
111
- }
112
- if (this._queryContext !== undefined) {
113
- cloned._queryContext = clone(this._queryContext);
114
- }
115
- if (this._connection !== undefined) {
116
- cloned._connection = this._connection;
117
- }
118
-
119
- return cloned;
120
- },
121
-
122
- timeout(ms, { cancel } = {}) {
123
- if (isNumber(ms) && ms > 0) {
124
- this._timeout = ms;
125
- if (cancel) {
126
- this.client.assertCanCancelQuery();
127
- this._cancelOnTimeout = true;
128
- }
129
- }
130
- return this;
131
- },
132
-
133
- // With
134
- // ------
135
-
136
- with(alias, statement) {
137
- validateWithArgs(alias, statement, 'with');
138
- return this.withWrapped(alias, statement);
139
- },
140
-
141
- // Helper for compiling any advanced `with` queries.
142
- withWrapped(alias, query) {
143
- this._statements.push({
144
- grouping: 'with',
145
- type: 'withWrapped',
146
- alias: alias,
147
- value: query,
148
- });
149
- return this;
150
- },
151
-
152
- // With Recursive
153
- // ------
154
-
155
- withRecursive(alias, statement) {
156
- validateWithArgs(alias, statement, 'withRecursive');
157
- return this.withRecursiveWrapped(alias, statement);
158
- },
159
-
160
- // Helper for compiling any advanced `withRecursive` queries.
161
- withRecursiveWrapped(alias, query) {
162
- this.withWrapped(alias, query);
163
- this._statements[this._statements.length - 1].recursive = true;
164
- return this;
165
- },
166
-
167
- // Select
168
- // ------
169
-
170
- // Adds a column or columns to the list of "columns"
171
- // being selected on the query.
172
- columns(column) {
173
- if (!column && column !== 0) return this;
174
- this._statements.push({
175
- grouping: 'columns',
176
- value: helpers.normalizeArr.apply(null, arguments),
177
- });
178
- return this;
179
- },
180
-
181
- // Allow for a sub-select to be explicitly aliased as a column,
182
- // without needing to compile the query in a where.
183
- as(column) {
184
- this._single.as = column;
185
- return this;
186
- },
187
-
188
- // Adds a single hint or an array of hits to the list of "hintComments" on the query.
189
- hintComment(hints) {
190
- hints = Array.isArray(hints) ? hints : [hints]
191
- if (hints.some((hint) => !isString(hint))) {
192
- throw new Error('Hint comment must be a string');
193
- }
194
- if (hints.some((hint) => hint.includes('/*') || hint.includes('*/'))) {
195
- throw new Error('Hint comment cannot include "/*" or "*/"');
196
- }
197
- if (hints.some((hint) => hint.includes('?'))) {
198
- throw new Error('Hint comment cannot include "?"');
199
- }
200
- this._statements.push({
201
- grouping: 'hintComments',
202
- value: hints,
203
- })
204
- return this;
205
- },
206
-
207
- // Prepends the `schemaName` on `tableName` defined by `.table` and `.join`.
208
- withSchema(schemaName) {
209
- this._single.schema = schemaName;
210
- return this;
211
- },
212
-
213
- // Sets the `tableName` on the query.
214
- // Alias to "from" for select and "into" for insert statements
215
- // e.g. builder.insert({a: value}).into('tableName')
216
- // `options`: options object containing keys:
217
- // - `only`: whether the query should use SQL's ONLY to not return
218
- // inheriting table data. Defaults to false.
219
- table(tableName, options = {}) {
220
- this._single.table = tableName;
221
- this._single.only = options.only === true;
222
- return this;
223
- },
224
-
225
- // Adds a `distinct` clause to the query.
226
- distinct() {
227
- this._statements.push({
228
- grouping: 'columns',
229
- value: helpers.normalizeArr.apply(null, arguments),
230
- distinct: true,
231
- });
232
- return this;
233
- },
234
-
235
- distinctOn() {
236
- const value = helpers.normalizeArr.apply(null, arguments);
237
- if (isEmpty(value)) {
238
- throw new Error('distinctOn requires atleast on argument');
239
- }
240
- this._statements.push({
241
- grouping: 'columns',
242
- value,
243
- distinctOn: true,
244
- });
245
- return this;
246
- },
247
-
248
- // Adds a join clause to the query, allowing for advanced joins
249
- // with an anonymous function as the second argument.
250
- // function(table, first, operator, second)
251
- join(table, first) {
252
- let join;
253
- const { schema } = this._single;
254
- const joinType = this._joinType();
255
- if (typeof first === 'function') {
256
- join = new JoinClause(table, joinType, schema);
257
- first.call(join, join);
258
- } else if (joinType === 'raw') {
259
- join = new JoinClause(this.client.raw(table, first), 'raw');
260
- } else {
261
- join = new JoinClause(
262
- table,
263
- joinType,
264
- table instanceof Builder ? undefined : schema
265
- );
266
- if (arguments.length > 1) {
267
- join.on.apply(join, toArray(arguments).slice(1));
268
- }
269
- }
270
- this._statements.push(join);
271
- return this;
272
- },
273
-
274
- // JOIN blocks:
275
- innerJoin() {
276
- return this._joinType('inner').join.apply(this, arguments);
277
- },
278
- leftJoin() {
279
- return this._joinType('left').join.apply(this, arguments);
280
- },
281
- leftOuterJoin() {
282
- return this._joinType('left outer').join.apply(this, arguments);
283
- },
284
- rightJoin() {
285
- return this._joinType('right').join.apply(this, arguments);
286
- },
287
- rightOuterJoin() {
288
- return this._joinType('right outer').join.apply(this, arguments);
289
- },
290
- outerJoin() {
291
- return this._joinType('outer').join.apply(this, arguments);
292
- },
293
- fullOuterJoin() {
294
- return this._joinType('full outer').join.apply(this, arguments);
295
- },
296
- crossJoin() {
297
- return this._joinType('cross').join.apply(this, arguments);
298
- },
299
- joinRaw() {
300
- return this._joinType('raw').join.apply(this, arguments);
301
- },
302
-
303
- // The where function can be used in several ways:
304
- // The most basic is `where(key, value)`, which expands to
305
- // where key = value.
306
- where(column, operator, value) {
307
- // Support "where true || where false"
308
- if (column === false || column === true) {
309
- return this.where(1, '=', column ? 1 : 0);
310
- }
311
-
312
- // Check if the column is a function, in which case it's
313
- // a where statement wrapped in parens.
314
- if (typeof column === 'function') {
315
- return this.whereWrapped(column);
316
- }
317
-
318
- // Allow a raw statement to be passed along to the query.
319
- if (column instanceof Raw && arguments.length === 1)
320
- return this.whereRaw(column);
321
-
322
- // Allows `where({id: 2})` syntax.
323
- if (isObject(column) && !(column instanceof Raw))
324
- return this._objectWhere(column);
325
-
326
- // Enable the where('key', value) syntax, only when there
327
- // are explicitly two arguments passed, so it's not possible to
328
- // do where('key', '!=') and have that turn into where key != null
329
- if (arguments.length === 2) {
330
- value = operator;
331
- operator = '=';
332
-
333
- // If the value is null, and it's a two argument query,
334
- // we assume we're going for a `whereNull`.
335
- if (value === null) {
336
- return this.whereNull(column);
337
- }
338
- }
339
-
340
- // lower case the operator for comparison purposes
341
- const checkOperator = `${operator}`.toLowerCase().trim();
342
-
343
- // If there are 3 arguments, check whether 'in' is one of them.
344
- if (arguments.length === 3) {
345
- if (checkOperator === 'in' || checkOperator === 'not in') {
346
- return this._not(checkOperator === 'not in').whereIn(
347
- arguments[0],
348
- arguments[2]
349
- );
350
- }
351
- if (checkOperator === 'between' || checkOperator === 'not between') {
352
- return this._not(checkOperator === 'not between').whereBetween(
353
- arguments[0],
354
- arguments[2]
355
- );
356
- }
357
- }
358
-
359
- // If the value is still null, check whether they're meaning
360
- // where value is null
361
- if (value === null) {
362
- // Check for .where(key, 'is', null) or .where(key, 'is not', 'null');
363
- if (checkOperator === 'is' || checkOperator === 'is not') {
364
- return this._not(checkOperator === 'is not').whereNull(column);
365
- }
366
- }
367
-
368
- // Push onto the where statement stack.
369
- this._statements.push({
370
- grouping: 'where',
371
- type: 'whereBasic',
372
- column,
373
- operator,
374
- value,
375
- not: this._not(),
376
- bool: this._bool(),
377
- asColumn: this._asColumnFlag,
378
- });
379
- return this;
380
- },
381
-
382
- whereColumn(column, operator, rightColumn) {
383
- this._asColumnFlag = true;
384
- this.where.apply(this, arguments);
385
- this._asColumnFlag = false;
386
- return this;
387
- },
388
-
389
- // Adds an `or where` clause to the query.
390
- orWhere() {
391
- this._bool('or');
392
- const obj = arguments[0];
393
- if (isObject(obj) && !(obj instanceof Raw)) {
394
- return this.whereWrapped(function () {
395
- for (const key in obj) {
396
- this.andWhere(key, obj[key]);
397
- }
398
- });
399
- }
400
- return this.where.apply(this, arguments);
401
- },
402
-
403
- orWhereColumn() {
404
- this._bool('or');
405
- const obj = arguments[0];
406
- if (isObject(obj) && !(obj instanceof Raw)) {
407
- return this.whereWrapped(function () {
408
- for (const key in obj) {
409
- this.andWhereColumn(key, '=', obj[key]);
410
- }
411
- });
412
- }
413
- return this.whereColumn.apply(this, arguments);
414
- },
415
-
416
- // Adds an `not where` clause to the query.
417
- whereNot() {
418
- if (arguments.length >= 2) {
419
- if (arguments[1] === 'in' || arguments[1] === 'between') {
420
- this.client.logger.warn(
421
- 'whereNot is not suitable for "in" and "between" type subqueries. You should use "not in" and "not between" instead.'
422
- );
423
- }
424
- }
425
- return this._not(true).where.apply(this, arguments);
426
- },
427
-
428
- whereNotColumn() {
429
- return this._not(true).whereColumn.apply(this, arguments);
430
- },
431
-
432
- // Adds an `or not where` clause to the query.
433
- orWhereNot() {
434
- return this._bool('or').whereNot.apply(this, arguments);
435
- },
436
-
437
- orWhereNotColumn() {
438
- return this._bool('or').whereNotColumn.apply(this, arguments);
439
- },
440
-
441
- // Processes an object literal provided in a "where" clause.
442
- _objectWhere(obj) {
443
- const boolVal = this._bool();
444
- const notVal = this._not() ? 'Not' : '';
445
- for (const key in obj) {
446
- this[boolVal + 'Where' + notVal](key, obj[key]);
447
- }
448
- return this;
449
- },
450
-
451
- // Adds a raw `where` clause to the query.
452
- whereRaw(sql, bindings) {
453
- const raw = sql instanceof Raw ? sql : this.client.raw(sql, bindings);
454
- this._statements.push({
455
- grouping: 'where',
456
- type: 'whereRaw',
457
- value: raw,
458
- not: this._not(),
459
- bool: this._bool(),
460
- });
461
- return this;
462
- },
463
-
464
- orWhereRaw(sql, bindings) {
465
- return this._bool('or').whereRaw(sql, bindings);
466
- },
467
-
468
- // Helper for compiling any advanced `where` queries.
469
- whereWrapped(callback) {
470
- this._statements.push({
471
- grouping: 'where',
472
- type: 'whereWrapped',
473
- value: callback,
474
- not: this._not(),
475
- bool: this._bool(),
476
- });
477
- return this;
478
- },
479
-
480
- // Adds a `where exists` clause to the query.
481
- whereExists(callback) {
482
- this._statements.push({
483
- grouping: 'where',
484
- type: 'whereExists',
485
- value: callback,
486
- not: this._not(),
487
- bool: this._bool(),
488
- });
489
- return this;
490
- },
491
-
492
- // Adds an `or where exists` clause to the query.
493
- orWhereExists(callback) {
494
- return this._bool('or').whereExists(callback);
495
- },
496
-
497
- // Adds a `where not exists` clause to the query.
498
- whereNotExists(callback) {
499
- return this._not(true).whereExists(callback);
500
- },
501
-
502
- // Adds a `or where not exists` clause to the query.
503
- orWhereNotExists(callback) {
504
- return this._bool('or').whereNotExists(callback);
505
- },
506
-
507
- // Adds a `where in` clause to the query.
508
- whereIn(column, values) {
509
- if (Array.isArray(values) && isEmpty(values))
510
- return this.where(this._not());
511
- this._statements.push({
512
- grouping: 'where',
513
- type: 'whereIn',
514
- column,
515
- value: values,
516
- not: this._not(),
517
- bool: this._bool(),
518
- });
519
- return this;
520
- },
521
-
522
- // Adds a `or where in` clause to the query.
523
- orWhereIn(column, values) {
524
- return this._bool('or').whereIn(column, values);
525
- },
526
-
527
- // Adds a `where not in` clause to the query.
528
- whereNotIn(column, values) {
529
- return this._not(true).whereIn(column, values);
530
- },
531
-
532
- // Adds a `or where not in` clause to the query.
533
- orWhereNotIn(column, values) {
534
- return this._bool('or')._not(true).whereIn(column, values);
535
- },
536
-
537
- // Adds a `where null` clause to the query.
538
- whereNull(column) {
539
- this._statements.push({
540
- grouping: 'where',
541
- type: 'whereNull',
542
- column,
543
- not: this._not(),
544
- bool: this._bool(),
545
- });
546
- return this;
547
- },
548
-
549
- // Adds a `or where null` clause to the query.
550
- orWhereNull(column) {
551
- return this._bool('or').whereNull(column);
552
- },
553
-
554
- // Adds a `where not null` clause to the query.
555
- whereNotNull(column) {
556
- return this._not(true).whereNull(column);
557
- },
558
-
559
- // Adds a `or where not null` clause to the query.
560
- orWhereNotNull(column) {
561
- return this._bool('or').whereNotNull(column);
562
- },
563
-
564
- // Adds a `where between` clause to the query.
565
- whereBetween(column, values) {
566
- assert(
567
- Array.isArray(values),
568
- 'The second argument to whereBetween must be an array.'
569
- );
570
- assert(
571
- values.length === 2,
572
- 'You must specify 2 values for the whereBetween clause'
573
- );
574
- this._statements.push({
575
- grouping: 'where',
576
- type: 'whereBetween',
577
- column,
578
- value: values,
579
- not: this._not(),
580
- bool: this._bool(),
581
- });
582
- return this;
583
- },
584
-
585
- // Adds a `where not between` clause to the query.
586
- whereNotBetween(column, values) {
587
- return this._not(true).whereBetween(column, values);
588
- },
589
-
590
- // Adds a `or where between` clause to the query.
591
- orWhereBetween(column, values) {
592
- return this._bool('or').whereBetween(column, values);
593
- },
594
-
595
- // Adds a `or where not between` clause to the query.
596
- orWhereNotBetween(column, values) {
597
- return this._bool('or').whereNotBetween(column, values);
598
- },
599
-
600
- // Adds a `group by` clause to the query.
601
- groupBy(item) {
602
- if (item instanceof Raw) {
603
- return this.groupByRaw.apply(this, arguments);
604
- }
605
- this._statements.push({
606
- grouping: 'group',
607
- type: 'groupByBasic',
608
- value: helpers.normalizeArr.apply(null, arguments),
609
- });
610
- return this;
611
- },
612
-
613
- // Adds a raw `group by` clause to the query.
614
- groupByRaw(sql, bindings) {
615
- const raw = sql instanceof Raw ? sql : this.client.raw(sql, bindings);
616
- this._statements.push({
617
- grouping: 'group',
618
- type: 'groupByRaw',
619
- value: raw,
620
- });
621
- return this;
622
- },
623
-
624
- // Adds a `order by` clause to the query.
625
- orderBy(column, direction) {
626
- if (Array.isArray(column)) {
627
- return this._orderByArray(column);
628
- }
629
- this._statements.push({
630
- grouping: 'order',
631
- type: 'orderByBasic',
632
- value: column,
633
- direction,
634
- });
635
- return this;
636
- },
637
-
638
- // Adds a `order by` with multiple columns to the query.
639
- _orderByArray(columnDefs) {
640
- for (let i = 0; i < columnDefs.length; i++) {
641
- const columnInfo = columnDefs[i];
642
- if (isObject(columnInfo)) {
643
- this._statements.push({
644
- grouping: 'order',
645
- type: 'orderByBasic',
646
- value: columnInfo['column'],
647
- direction: columnInfo['order'],
648
- });
649
- } else if (isString(columnInfo)) {
650
- this._statements.push({
651
- grouping: 'order',
652
- type: 'orderByBasic',
653
- value: columnInfo,
654
- });
655
- }
656
- }
657
- return this;
658
- },
659
-
660
- // Add a raw `order by` clause to the query.
661
- orderByRaw(sql, bindings) {
662
- const raw = sql instanceof Raw ? sql : this.client.raw(sql, bindings);
663
- this._statements.push({
664
- grouping: 'order',
665
- type: 'orderByRaw',
666
- value: raw,
667
- });
668
- return this;
669
- },
670
-
671
- _union(clause, args) {
672
- let callbacks = args[0];
673
- let wrap = args[1];
674
- if (args.length === 1 || (args.length === 2 && isBoolean(wrap))) {
675
- if (!Array.isArray(callbacks)) {
676
- callbacks = [callbacks];
677
- }
678
- for (let i = 0, l = callbacks.length; i < l; i++) {
679
- this._statements.push({
680
- grouping: 'union',
681
- clause: clause,
682
- value: callbacks[i],
683
- wrap: wrap || false,
684
- });
685
- }
686
- } else {
687
- callbacks = toArray(args).slice(0, args.length - 1);
688
- wrap = args[args.length - 1];
689
- if (!isBoolean(wrap)) {
690
- callbacks.push(wrap);
691
- wrap = false;
692
- }
693
- this._union(clause, [callbacks, wrap]);
694
- }
695
- return this;
696
- },
697
-
698
- // Add a union statement to the query.
699
- union(...args) {
700
- return this._union('union', args);
701
- },
702
-
703
- // Adds a union all statement to the query.
704
- unionAll(...args) {
705
- return this._union('union all', args);
706
- },
707
-
708
- // Adds an intersect statement to the query
709
- intersect(callbacks, wrap) {
710
- if (arguments.length === 1 || (arguments.length === 2 && isBoolean(wrap))) {
711
- if (!Array.isArray(callbacks)) {
712
- callbacks = [callbacks];
713
- }
714
- for (let i = 0, l = callbacks.length; i < l; i++) {
715
- this._statements.push({
716
- grouping: 'union',
717
- clause: 'intersect',
718
- value: callbacks[i],
719
- wrap: wrap || false,
720
- });
721
- }
722
- } else {
723
- callbacks = toArray(arguments).slice(0, arguments.length - 1);
724
- wrap = arguments[arguments.length - 1];
725
- if (!isBoolean(wrap)) {
726
- callbacks.push(wrap);
727
- wrap = false;
728
- }
729
- this.intersect(callbacks, wrap);
730
- }
731
- return this;
732
- },
733
-
734
- // Adds a `having` clause to the query.
735
- having(column, operator, value) {
736
- if (column instanceof Raw && arguments.length === 1) {
737
- return this.havingRaw(column);
738
- }
739
-
740
- // Check if the column is a function, in which case it's
741
- // a having statement wrapped in parens.
742
- if (typeof column === 'function') {
743
- return this.havingWrapped(column);
744
- }
745
-
746
- this._statements.push({
747
- grouping: 'having',
748
- type: 'havingBasic',
749
- column,
750
- operator,
751
- value,
752
- bool: this._bool(),
753
- not: this._not(),
754
- });
755
- return this;
756
- },
757
-
758
- orHaving: function orHaving() {
759
- this._bool('or');
760
- const obj = arguments[0];
761
- if (isObject(obj) && !(obj instanceof Raw)) {
762
- return this.havingWrapped(function () {
763
- for (const key in obj) {
764
- this.andHaving(key, obj[key]);
765
- }
766
- });
767
- }
768
- return this.having.apply(this, arguments);
769
- },
770
-
771
- // Helper for compiling any advanced `having` queries.
772
- havingWrapped(callback) {
773
- this._statements.push({
774
- grouping: 'having',
775
- type: 'havingWrapped',
776
- value: callback,
777
- bool: this._bool(),
778
- not: this._not(),
779
- });
780
- return this;
781
- },
782
-
783
- havingNull(column) {
784
- this._statements.push({
785
- grouping: 'having',
786
- type: 'havingNull',
787
- column,
788
- not: this._not(),
789
- bool: this._bool(),
790
- });
791
- return this;
792
- },
793
-
794
- orHavingNull(callback) {
795
- return this._bool('or').havingNull(callback);
796
- },
797
-
798
- havingNotNull(callback) {
799
- return this._not(true).havingNull(callback);
800
- },
801
-
802
- orHavingNotNull(callback) {
803
- return this._not(true)._bool('or').havingNull(callback);
804
- },
805
-
806
- havingExists(callback) {
807
- this._statements.push({
808
- grouping: 'having',
809
- type: 'havingExists',
810
- value: callback,
811
- not: this._not(),
812
- bool: this._bool(),
813
- });
814
- return this;
815
- },
816
-
817
- orHavingExists(callback) {
818
- return this._bool('or').havingExists(callback);
819
- },
820
-
821
- havingNotExists(callback) {
822
- return this._not(true).havingExists(callback);
823
- },
824
-
825
- orHavingNotExists(callback) {
826
- return this._not(true)._bool('or').havingExists(callback);
827
- },
828
-
829
- havingBetween(column, values) {
830
- assert(
831
- Array.isArray(values),
832
- 'The second argument to havingBetween must be an array.'
833
- );
834
- assert(
835
- values.length === 2,
836
- 'You must specify 2 values for the havingBetween clause'
837
- );
838
- this._statements.push({
839
- grouping: 'having',
840
- type: 'havingBetween',
841
- column,
842
- value: values,
843
- not: this._not(),
844
- bool: this._bool(),
845
- });
846
- return this;
847
- },
848
-
849
- orHavingBetween(column, values) {
850
- return this._bool('or').havingBetween(column, values);
851
- },
852
-
853
- havingNotBetween(column, values) {
854
- return this._not(true).havingBetween(column, values);
855
- },
856
-
857
- orHavingNotBetween(column, values) {
858
- return this._not(true)._bool('or').havingBetween(column, values);
859
- },
860
-
861
- havingIn(column, values) {
862
- if (Array.isArray(values) && isEmpty(values))
863
- return this.where(this._not());
864
- this._statements.push({
865
- grouping: 'having',
866
- type: 'havingIn',
867
- column,
868
- value: values,
869
- not: this._not(),
870
- bool: this._bool(),
871
- });
872
- return this;
873
- },
874
-
875
- // Adds a `or where in` clause to the query.
876
- orHavingIn(column, values) {
877
- return this._bool('or').havingIn(column, values);
878
- },
879
-
880
- // Adds a `where not in` clause to the query.
881
- havingNotIn(column, values) {
882
- return this._not(true).havingIn(column, values);
883
- },
884
-
885
- // Adds a `or where not in` clause to the query.
886
- orHavingNotIn(column, values) {
887
- return this._bool('or')._not(true).havingIn(column, values);
888
- },
889
-
890
- // Adds a raw `having` clause to the query.
891
- havingRaw(sql, bindings) {
892
- const raw = sql instanceof Raw ? sql : this.client.raw(sql, bindings);
893
- this._statements.push({
894
- grouping: 'having',
895
- type: 'havingRaw',
896
- value: raw,
897
- bool: this._bool(),
898
- not: this._not(),
899
- });
900
- return this;
901
- },
902
-
903
- orHavingRaw(sql, bindings) {
904
- return this._bool('or').havingRaw(sql, bindings);
905
- },
906
-
907
- // Only allow a single "offset" to be set for the current query.
908
- offset(value) {
909
- if (value == null || value instanceof Raw || value instanceof Builder) {
910
- // Builder for backward compatibility
911
- this._single.offset = value;
912
- } else {
913
- const val = parseInt(value, 10);
914
- if (isNaN(val)) {
915
- this.client.logger.warn('A valid integer must be provided to offset');
916
- } else {
917
- this._single.offset = val;
918
- }
919
- }
920
- return this;
921
- },
922
-
923
- // Only allow a single "limit" to be set for the current query.
924
- limit(value) {
925
- const val = parseInt(value, 10);
926
- if (isNaN(val)) {
927
- this.client.logger.warn('A valid integer must be provided to limit');
928
- } else {
929
- this._single.limit = val;
930
- }
931
- return this;
932
- },
933
-
934
- // Retrieve the "count" result of the query.
935
- count(column, options) {
936
- return this._aggregate('count', column || '*', options);
937
- },
938
-
939
- // Retrieve the minimum value of a given column.
940
- min(column, options) {
941
- return this._aggregate('min', column, options);
942
- },
943
-
944
- // Retrieve the maximum value of a given column.
945
- max(column, options) {
946
- return this._aggregate('max', column, options);
947
- },
948
-
949
- // Retrieve the sum of the values of a given column.
950
- sum(column, options) {
951
- return this._aggregate('sum', column, options);
952
- },
953
-
954
- // Retrieve the average of the values of a given column.
955
- avg(column, options) {
956
- return this._aggregate('avg', column, options);
957
- },
958
-
959
- // Retrieve the "count" of the distinct results of the query.
960
- countDistinct() {
961
- let columns = helpers.normalizeArr.apply(null, arguments);
962
- let options;
963
- if (columns.length > 1 && isPlainObject(last(columns))) {
964
- [options] = columns.splice(columns.length - 1, 1);
965
- }
966
-
967
- if (!columns.length) {
968
- columns = '*';
969
- } else if (columns.length === 1) {
970
- columns = columns[0];
971
- }
972
-
973
- return this._aggregate('count', columns, { ...options, distinct: true });
974
- },
975
-
976
- // Retrieve the sum of the distinct values of a given column.
977
- sumDistinct(column, options) {
978
- return this._aggregate('sum', column, { ...options, distinct: true });
979
- },
980
-
981
- // Retrieve the vg of the distinct results of the query.
982
- avgDistinct(column, options) {
983
- return this._aggregate('avg', column, { ...options, distinct: true });
984
- },
985
-
986
- // Increments a column's value by the specified amount.
987
- increment(column, amount = 1) {
988
- if (isObject(column)) {
989
- for (const key in column) {
990
- this._counter(key, column[key]);
991
- }
992
-
993
- return this;
994
- }
995
-
996
- return this._counter(column, amount);
997
- },
998
-
999
- // Decrements a column's value by the specified amount.
1000
- decrement(column, amount = 1) {
1001
- if (isObject(column)) {
1002
- for (const key in column) {
1003
- this._counter(key, -column[key]);
1004
- }
1005
-
1006
- return this;
1007
- }
1008
-
1009
- return this._counter(column, -amount);
1010
- },
1011
-
1012
- // Clears increments/decrements
1013
- clearCounters() {
1014
- this._single.counter = {};
1015
- return this;
1016
- },
1017
-
1018
- // Sets the values for a `select` query, informing that only the first
1019
- // row should be returned (limit 1).
1020
- first() {
1021
- if (!this._isSelectQuery()) {
1022
- throw new Error(`Cannot chain .first() on "${this._method}" query!`);
1023
- }
1024
-
1025
- const args = new Array(arguments.length);
1026
- for (let i = 0; i < args.length; i++) {
1027
- args[i] = arguments[i];
1028
- }
1029
- this.select.apply(this, args);
1030
- this._method = 'first';
1031
- this.limit(1);
1032
- return this;
1033
- },
1034
-
1035
- // Use existing connection to execute the query
1036
- // Same value that client.acquireConnection() for an according client returns should be passed
1037
- connection(_connection) {
1038
- this._connection = _connection;
1039
- return this;
1040
- },
1041
-
1042
- // Pluck a column from a query.
1043
- pluck(column) {
1044
- this._method = 'pluck';
1045
- this._single.pluck = column;
1046
- this._statements.push({
1047
- grouping: 'columns',
1048
- type: 'pluck',
1049
- value: column,
1050
- });
1051
- return this;
1052
- },
1053
-
1054
- // Deprecated. Remove everything from select clause
1055
- clearSelect() {
1056
- this._clearGrouping('columns');
1057
- return this;
1058
- },
1059
-
1060
- // Deprecated. Remove everything from where clause
1061
- clearWhere() {
1062
- this._clearGrouping('where');
1063
- return this;
1064
- },
1065
-
1066
- // Deprecated. Remove everything from group clause
1067
- clearGroup() {
1068
- this._clearGrouping('group');
1069
- return this;
1070
- },
1071
-
1072
- // Deprecated. Remove everything from order clause
1073
- clearOrder() {
1074
- this._clearGrouping('order');
1075
- return this;
1076
- },
1077
-
1078
- // Deprecated. Remove everything from having clause
1079
- clearHaving() {
1080
- this._clearGrouping('having');
1081
- return this;
1082
- },
1083
-
1084
- // Remove everything from statement clause
1085
- clear(statement) {
1086
- if (!['with', 'select', 'columns', 'hintComments', 'where', 'union', 'join', 'group', 'order', 'having', 'limit', 'offset', 'counter', 'counters'].includes(statement))
1087
- throw new Error(`Knex Error: unknown statement '${statement}'`);
1088
- if (statement.startsWith('counter')) return this.clearCounters();
1089
- if (statement === 'select') { statement = 'columns'; }
1090
- this._clearGrouping(statement);
1091
- return this;
1092
- },
1093
-
1094
- // Insert & Update
1095
- // ------
1096
-
1097
- // Sets the values for an `insert` query.
1098
- insert(values, returning, options) {
1099
- this._method = 'insert';
1100
- if (!isEmpty(returning)) this.returning(returning, options);
1101
- this._single.insert = values;
1102
- return this;
1103
- },
1104
-
1105
- // Sets the values for an `update`, allowing for both
1106
- // `.update(key, value, [returning])` and `.update(obj, [returning])` syntaxes.
1107
- update(values, returning, options) {
1108
- let ret;
1109
- const obj = this._single.update || {};
1110
- this._method = 'update';
1111
- if (isString(values)) {
1112
- obj[values] = returning;
1113
- if (arguments.length > 2) {
1114
- ret = arguments[2];
1115
- }
1116
- } else {
1117
- const keys = Object.keys(values);
1118
- if (this._single.update) {
1119
- this.client.logger.warn('Update called multiple times with objects.');
1120
- }
1121
- let i = -1;
1122
- while (++i < keys.length) {
1123
- obj[keys[i]] = values[keys[i]];
1124
- }
1125
- ret = arguments[1];
1126
- }
1127
- if (!isEmpty(ret)) this.returning(ret, options);
1128
- this._single.update = obj;
1129
- return this;
1130
- },
1131
-
1132
- // Sets the returning value for the query.
1133
- returning(returning, options) {
1134
- this._single.returning = returning;
1135
- this._single.options = options;
1136
- return this;
1137
- },
1138
-
1139
-
1140
- onConflict(columns) {
1141
- if (typeof columns === 'string') {
1142
- columns = [columns];
1143
- }
1144
- return new OnConflictBuilder(this, columns || true);
1145
- },
1146
-
1147
- // Delete
1148
- // ------
1149
-
1150
- // Executes a delete statement on the query;
1151
- delete(ret, options) {
1152
- this._method = 'del';
1153
- if (!isEmpty(ret)) this.returning(ret, options);
1154
- return this;
1155
- },
1156
-
1157
- // Truncates a table, ends the query chain.
1158
- truncate(tableName) {
1159
- this._method = 'truncate';
1160
- if (tableName) {
1161
- this._single.table = tableName;
1162
- }
1163
- return this;
1164
- },
1165
-
1166
- // Retrieves columns for the table specified by `knex(tableName)`
1167
- columnInfo(column) {
1168
- this._method = 'columnInfo';
1169
- this._single.columnInfo = column;
1170
- return this;
1171
- },
1172
-
1173
- // Set a lock for update constraint.
1174
- forUpdate() {
1175
- this._single.lock = lockMode.forUpdate;
1176
- this._single.lockTables = helpers.normalizeArr.apply(null, arguments);
1177
- return this;
1178
- },
1179
-
1180
- // Set a lock for share constraint.
1181
- forShare() {
1182
- this._single.lock = lockMode.forShare;
1183
- this._single.lockTables = helpers.normalizeArr.apply(null, arguments);
1184
- return this;
1185
- },
1186
-
1187
- // Skips locked rows when using a lock constraint.
1188
- skipLocked() {
1189
- if (!this._isSelectQuery()) {
1190
- throw new Error(`Cannot chain .skipLocked() on "${this._method}" query!`);
1191
- }
1192
- if (!this._hasLockMode()) {
1193
- throw new Error(
1194
- '.skipLocked() can only be used after a call to .forShare() or .forUpdate()!'
1195
- );
1196
- }
1197
- if (this._single.waitMode === waitMode.noWait) {
1198
- throw new Error('.skipLocked() cannot be used together with .noWait()!');
1199
- }
1200
- this._single.waitMode = waitMode.skipLocked;
1201
- return this;
1202
- },
1203
-
1204
- // Causes error when acessing a locked row instead of waiting for it to be released.
1205
- noWait() {
1206
- if (!this._isSelectQuery()) {
1207
- throw new Error(`Cannot chain .noWait() on "${this._method}" query!`);
1208
- }
1209
- if (!this._hasLockMode()) {
1210
- throw new Error(
1211
- '.noWait() can only be used after a call to .forShare() or .forUpdate()!'
1212
- );
1213
- }
1214
- if (this._single.waitMode === waitMode.skipLocked) {
1215
- throw new Error('.noWait() cannot be used together with .skipLocked()!');
1216
- }
1217
- this._single.waitMode = waitMode.noWait;
1218
- return this;
1219
- },
1220
-
1221
- // Takes a JS object of methods to call and calls them
1222
- fromJS(obj) {
1223
- each(obj, (val, key) => {
1224
- if (typeof this[key] !== 'function') {
1225
- this.client.logger.warn(`Knex Error: unknown key ${key}`);
1226
- }
1227
- if (Array.isArray(val)) {
1228
- this[key].apply(this, val);
1229
- } else {
1230
- this[key](val);
1231
- }
1232
- });
1233
- return this;
1234
- },
1235
-
1236
- // Passes query to provided callback function, useful for e.g. composing
1237
- // domain-specific helpers
1238
- modify(callback) {
1239
- callback.apply(this, [this].concat(tail(arguments)));
1240
- return this;
1241
- },
1242
-
1243
- // ----------------------------------------------------------------------
1244
-
1245
- // Helper for the incrementing/decrementing queries.
1246
- _counter(column, amount) {
1247
- amount = parseFloat(amount);
1248
-
1249
- this._method = 'update';
1250
-
1251
- this._single.counter = this._single.counter || {};
1252
-
1253
- this._single.counter[column] = amount;
1254
-
1255
- return this;
1256
- },
1257
-
1258
- // Helper to get or set the "boolFlag" value.
1259
- _bool(val) {
1260
- if (arguments.length === 1) {
1261
- this._boolFlag = val;
1262
- return this;
1263
- }
1264
- const ret = this._boolFlag;
1265
- this._boolFlag = 'and';
1266
- return ret;
1267
- },
1268
-
1269
- // Helper to get or set the "notFlag" value.
1270
- _not(val) {
1271
- if (arguments.length === 1) {
1272
- this._notFlag = val;
1273
- return this;
1274
- }
1275
- const ret = this._notFlag;
1276
- this._notFlag = false;
1277
- return ret;
1278
- },
1279
-
1280
- // Helper to get or set the "joinFlag" value.
1281
- _joinType(val) {
1282
- if (arguments.length === 1) {
1283
- this._joinFlag = val;
1284
- return this;
1285
- }
1286
- const ret = this._joinFlag || 'inner';
1287
- this._joinFlag = 'inner';
1288
- return ret;
1289
- },
1290
-
1291
- // Helper for compiling any aggregate queries.
1292
- _aggregate(method, column, options = {}) {
1293
- this._statements.push({
1294
- grouping: 'columns',
1295
- type: column instanceof Raw ? 'aggregateRaw' : 'aggregate',
1296
- method,
1297
- value: column,
1298
- aggregateDistinct: options.distinct || false,
1299
- alias: options.as,
1300
- });
1301
- return this;
1302
- },
1303
-
1304
- // Helper function for clearing or reseting a grouping type from the builder
1305
- _clearGrouping(grouping) {
1306
- if (grouping in this._single) {
1307
- this._single[grouping] = undefined;
1308
- } else {
1309
- this._statements = reject(this._statements, { grouping });
1310
- }
1311
- },
1312
-
1313
- // Helper function that checks if the builder will emit a select query
1314
- _isSelectQuery() {
1315
- return ['pluck', 'first', 'select'].includes(this._method);
1316
- },
1317
-
1318
- // Helper function that checks if the query has a lock mode set
1319
- _hasLockMode() {
1320
- return [lockMode.forShare, lockMode.forUpdate].includes(this._single.lock);
1321
- },
1322
- });
1323
-
1324
- Object.defineProperty(Builder.prototype, 'or', {
1325
- get() {
1326
- return this._bool('or');
1327
- },
1328
- });
1329
-
1330
- Object.defineProperty(Builder.prototype, 'not', {
1331
- get() {
1332
- return this._not(true);
1333
- },
1334
- });
1335
-
1336
- Builder.prototype.select = Builder.prototype.columns;
1337
- Builder.prototype.column = Builder.prototype.columns;
1338
- Builder.prototype.andWhereNot = Builder.prototype.whereNot;
1339
- Builder.prototype.andWhereNotColumn = Builder.prototype.whereNotColumn;
1340
- Builder.prototype.andWhere = Builder.prototype.where;
1341
- Builder.prototype.andWhereColumn = Builder.prototype.whereColumn;
1342
- Builder.prototype.andWhereRaw = Builder.prototype.whereRaw;
1343
- Builder.prototype.andWhereBetween = Builder.prototype.whereBetween;
1344
- Builder.prototype.andWhereNotBetween = Builder.prototype.whereNotBetween;
1345
- Builder.prototype.andHaving = Builder.prototype.having;
1346
- Builder.prototype.andHavingIn = Builder.prototype.havingIn;
1347
- Builder.prototype.andHavingNotIn = Builder.prototype.havingNotIn;
1348
- Builder.prototype.andHavingNull = Builder.prototype.havingNull;
1349
- Builder.prototype.andHavingNotNull = Builder.prototype.havingNotNull;
1350
- Builder.prototype.andHavingExists = Builder.prototype.havingExists;
1351
- Builder.prototype.andHavingNotExists = Builder.prototype.havingNotExists;
1352
- Builder.prototype.andHavingBetween = Builder.prototype.havingBetween;
1353
- Builder.prototype.andHavingNotBetween = Builder.prototype.havingNotBetween;
1354
- Builder.prototype.from = Builder.prototype.table;
1355
- Builder.prototype.into = Builder.prototype.table;
1356
- Builder.prototype.del = Builder.prototype.delete;
1357
-
1358
- // Attach all of the top level promise methods that should be chainable.
1359
- require('../interface')(Builder);
1360
- helpers.addQueryContext(Builder);
1361
-
1362
- Builder.extend = (methodName, fn) => {
1363
- if (Object.prototype.hasOwnProperty.call(Builder.prototype, methodName)) {
1364
- throw new Error(
1365
- `Can't extend QueryBuilder with existing method ('${methodName}').`
1366
- );
1367
- }
1368
-
1369
- assign(Builder.prototype, { [methodName]: fn });
1370
- };
1371
-
1372
- module.exports = Builder;
1
+ // Builder
2
+ // -------
3
+ const assert = require('assert');
4
+ const { inherits } = require('util');
5
+ const { EventEmitter } = require('events');
6
+
7
+ const Raw = require('../raw');
8
+ const helpers = require('../helpers');
9
+ const JoinClause = require('./joinclause');
10
+ const assign = require('lodash/assign');
11
+ const clone = require('lodash/clone');
12
+ const each = require('lodash/each');
13
+ const isEmpty = require('lodash/isEmpty');
14
+ const isPlainObject = require('lodash/isPlainObject');
15
+ const last = require('lodash/last');
16
+ const reject = require('lodash/reject');
17
+ const tail = require('lodash/tail');
18
+ const toArray = require('lodash/toArray');
19
+ const saveAsyncStack = require('../util/save-async-stack');
20
+ const { isBoolean, isNumber, isObject, isString } = require('../util/is');
21
+
22
+ const { lockMode, waitMode } = require('./constants');
23
+
24
+ // Sub-builder for onConflict clauses
25
+ function OnConflictBuilder(builder, columns) {
26
+ this.builder = builder;
27
+ this._columns = columns;
28
+ }
29
+
30
+ assign(OnConflictBuilder.prototype, {
31
+ // Sets insert query to ignore conflicts
32
+ ignore() {
33
+ this.builder._single.onConflict = this._columns;
34
+ this.builder._single.ignore = true;
35
+ return this.builder;
36
+ },
37
+
38
+ // Sets insert query to update on conflict
39
+ merge(updates) {
40
+ this.builder._single.onConflict = this._columns;
41
+ this.builder._single.merge = { updates };
42
+ return this.builder;
43
+ },
44
+
45
+ // Prevent
46
+ then() {
47
+ throw new Error(
48
+ 'Incomplete onConflict clause. .onConflict() must be diretly followed by either .merge() or .ignore()'
49
+ );
50
+ },
51
+ });
52
+
53
+ // Typically called from `knex.builder`,
54
+ // start a new query building chain.
55
+ function Builder(client) {
56
+ this.client = client;
57
+ this.and = this;
58
+ this._single = {};
59
+ this._statements = [];
60
+ this._method = 'select';
61
+ if (client.config) {
62
+ saveAsyncStack(this, 5);
63
+ this._debug = client.config.debug;
64
+ }
65
+ // Internal flags used in the builder.
66
+ this._joinFlag = 'inner';
67
+ this._boolFlag = 'and';
68
+ this._notFlag = false;
69
+ this._asColumnFlag = false;
70
+ }
71
+
72
+ inherits(Builder, EventEmitter);
73
+
74
+ const validateWithArgs = function (alias, statement, method) {
75
+ if (typeof alias !== 'string') {
76
+ throw new Error(`${method}() first argument must be a string`);
77
+ }
78
+ if (
79
+ typeof statement === 'function' ||
80
+ statement instanceof Builder ||
81
+ statement instanceof Raw
82
+ ) {
83
+ return;
84
+ }
85
+ throw new Error(
86
+ `${method}() second argument must be a function / QueryBuilder or a raw`
87
+ );
88
+ };
89
+
90
+ assign(Builder.prototype, {
91
+ toString() {
92
+ return this.toQuery();
93
+ },
94
+
95
+ // Convert the current query "toSQL"
96
+ toSQL(method, tz) {
97
+ return this.client.queryCompiler(this).toSQL(method || this._method, tz);
98
+ },
99
+
100
+ // Create a shallow clone of the current query builder.
101
+ clone() {
102
+ const cloned = new this.constructor(this.client);
103
+ cloned._method = this._method;
104
+ cloned._single = clone(this._single);
105
+ cloned._statements = clone(this._statements);
106
+ cloned._debug = this._debug;
107
+
108
+ // `_option` is assigned by the `Interface` mixin.
109
+ if (this._options !== undefined) {
110
+ cloned._options = clone(this._options);
111
+ }
112
+ if (this._queryContext !== undefined) {
113
+ cloned._queryContext = clone(this._queryContext);
114
+ }
115
+ if (this._connection !== undefined) {
116
+ cloned._connection = this._connection;
117
+ }
118
+
119
+ return cloned;
120
+ },
121
+
122
+ timeout(ms, { cancel } = {}) {
123
+ if (isNumber(ms) && ms > 0) {
124
+ this._timeout = ms;
125
+ if (cancel) {
126
+ this.client.assertCanCancelQuery();
127
+ this._cancelOnTimeout = true;
128
+ }
129
+ }
130
+ return this;
131
+ },
132
+
133
+ // With
134
+ // ------
135
+
136
+ with(alias, statement) {
137
+ validateWithArgs(alias, statement, 'with');
138
+ return this.withWrapped(alias, statement);
139
+ },
140
+
141
+ // Helper for compiling any advanced `with` queries.
142
+ withWrapped(alias, query) {
143
+ this._statements.push({
144
+ grouping: 'with',
145
+ type: 'withWrapped',
146
+ alias: alias,
147
+ value: query,
148
+ });
149
+ return this;
150
+ },
151
+
152
+ // With Recursive
153
+ // ------
154
+
155
+ withRecursive(alias, statement) {
156
+ validateWithArgs(alias, statement, 'withRecursive');
157
+ return this.withRecursiveWrapped(alias, statement);
158
+ },
159
+
160
+ // Helper for compiling any advanced `withRecursive` queries.
161
+ withRecursiveWrapped(alias, query) {
162
+ this.withWrapped(alias, query);
163
+ this._statements[this._statements.length - 1].recursive = true;
164
+ return this;
165
+ },
166
+
167
+ // Select
168
+ // ------
169
+
170
+ // Adds a column or columns to the list of "columns"
171
+ // being selected on the query.
172
+ columns(column) {
173
+ if (!column && column !== 0) return this;
174
+ this._statements.push({
175
+ grouping: 'columns',
176
+ value: helpers.normalizeArr.apply(null, arguments),
177
+ });
178
+ return this;
179
+ },
180
+
181
+ // Allow for a sub-select to be explicitly aliased as a column,
182
+ // without needing to compile the query in a where.
183
+ as(column) {
184
+ this._single.as = column;
185
+ return this;
186
+ },
187
+
188
+ // Adds a single hint or an array of hits to the list of "hintComments" on the query.
189
+ hintComment(hints) {
190
+ hints = Array.isArray(hints) ? hints : [hints]
191
+ if (hints.some((hint) => !isString(hint))) {
192
+ throw new Error('Hint comment must be a string');
193
+ }
194
+ if (hints.some((hint) => hint.includes('/*') || hint.includes('*/'))) {
195
+ throw new Error('Hint comment cannot include "/*" or "*/"');
196
+ }
197
+ if (hints.some((hint) => hint.includes('?'))) {
198
+ throw new Error('Hint comment cannot include "?"');
199
+ }
200
+ this._statements.push({
201
+ grouping: 'hintComments',
202
+ value: hints,
203
+ })
204
+ return this;
205
+ },
206
+
207
+ // Prepends the `schemaName` on `tableName` defined by `.table` and `.join`.
208
+ withSchema(schemaName) {
209
+ this._single.schema = schemaName;
210
+ return this;
211
+ },
212
+
213
+ // Sets the `tableName` on the query.
214
+ // Alias to "from" for select and "into" for insert statements
215
+ // e.g. builder.insert({a: value}).into('tableName')
216
+ // `options`: options object containing keys:
217
+ // - `only`: whether the query should use SQL's ONLY to not return
218
+ // inheriting table data. Defaults to false.
219
+ table(tableName, options = {}) {
220
+ this._single.table = tableName;
221
+ this._single.only = options.only === true;
222
+ return this;
223
+ },
224
+
225
+ // Adds a `distinct` clause to the query.
226
+ distinct() {
227
+ this._statements.push({
228
+ grouping: 'columns',
229
+ value: helpers.normalizeArr.apply(null, arguments),
230
+ distinct: true,
231
+ });
232
+ return this;
233
+ },
234
+
235
+ distinctOn() {
236
+ const value = helpers.normalizeArr.apply(null, arguments);
237
+ if (isEmpty(value)) {
238
+ throw new Error('distinctOn requires atleast on argument');
239
+ }
240
+ this._statements.push({
241
+ grouping: 'columns',
242
+ value,
243
+ distinctOn: true,
244
+ });
245
+ return this;
246
+ },
247
+
248
+ // Adds a join clause to the query, allowing for advanced joins
249
+ // with an anonymous function as the second argument.
250
+ // function(table, first, operator, second)
251
+ join(table, first) {
252
+ let join;
253
+ const { schema } = this._single;
254
+ const joinType = this._joinType();
255
+ if (typeof first === 'function') {
256
+ join = new JoinClause(table, joinType, schema);
257
+ first.call(join, join);
258
+ } else if (joinType === 'raw') {
259
+ join = new JoinClause(this.client.raw(table, first), 'raw');
260
+ } else {
261
+ join = new JoinClause(
262
+ table,
263
+ joinType,
264
+ table instanceof Builder ? undefined : schema
265
+ );
266
+ if (arguments.length > 1) {
267
+ join.on.apply(join, toArray(arguments).slice(1));
268
+ }
269
+ }
270
+ this._statements.push(join);
271
+ return this;
272
+ },
273
+
274
+ // JOIN blocks:
275
+ innerJoin() {
276
+ return this._joinType('inner').join.apply(this, arguments);
277
+ },
278
+ leftJoin() {
279
+ return this._joinType('left').join.apply(this, arguments);
280
+ },
281
+ leftOuterJoin() {
282
+ return this._joinType('left outer').join.apply(this, arguments);
283
+ },
284
+ rightJoin() {
285
+ return this._joinType('right').join.apply(this, arguments);
286
+ },
287
+ rightOuterJoin() {
288
+ return this._joinType('right outer').join.apply(this, arguments);
289
+ },
290
+ outerJoin() {
291
+ return this._joinType('outer').join.apply(this, arguments);
292
+ },
293
+ fullOuterJoin() {
294
+ return this._joinType('full outer').join.apply(this, arguments);
295
+ },
296
+ crossJoin() {
297
+ return this._joinType('cross').join.apply(this, arguments);
298
+ },
299
+ joinRaw() {
300
+ return this._joinType('raw').join.apply(this, arguments);
301
+ },
302
+
303
+ // The where function can be used in several ways:
304
+ // The most basic is `where(key, value)`, which expands to
305
+ // where key = value.
306
+ where(column, operator, value) {
307
+ // Support "where true || where false"
308
+ if (column === false || column === true) {
309
+ return this.where(1, '=', column ? 1 : 0);
310
+ }
311
+
312
+ // Check if the column is a function, in which case it's
313
+ // a where statement wrapped in parens.
314
+ if (typeof column === 'function') {
315
+ return this.whereWrapped(column);
316
+ }
317
+
318
+ // Allow a raw statement to be passed along to the query.
319
+ if (column instanceof Raw && arguments.length === 1)
320
+ return this.whereRaw(column);
321
+
322
+ // Allows `where({id: 2})` syntax.
323
+ if (isObject(column) && !(column instanceof Raw))
324
+ return this._objectWhere(column);
325
+
326
+ // Enable the where('key', value) syntax, only when there
327
+ // are explicitly two arguments passed, so it's not possible to
328
+ // do where('key', '!=') and have that turn into where key != null
329
+ if (arguments.length === 2) {
330
+ value = operator;
331
+ operator = '=';
332
+
333
+ // If the value is null, and it's a two argument query,
334
+ // we assume we're going for a `whereNull`.
335
+ if (value === null) {
336
+ return this.whereNull(column);
337
+ }
338
+ }
339
+
340
+ // lower case the operator for comparison purposes
341
+ const checkOperator = `${operator}`.toLowerCase().trim();
342
+
343
+ // If there are 3 arguments, check whether 'in' is one of them.
344
+ if (arguments.length === 3) {
345
+ if (checkOperator === 'in' || checkOperator === 'not in') {
346
+ return this._not(checkOperator === 'not in').whereIn(
347
+ arguments[0],
348
+ arguments[2]
349
+ );
350
+ }
351
+ if (checkOperator === 'between' || checkOperator === 'not between') {
352
+ return this._not(checkOperator === 'not between').whereBetween(
353
+ arguments[0],
354
+ arguments[2]
355
+ );
356
+ }
357
+ }
358
+
359
+ // If the value is still null, check whether they're meaning
360
+ // where value is null
361
+ if (value === null) {
362
+ // Check for .where(key, 'is', null) or .where(key, 'is not', 'null');
363
+ if (checkOperator === 'is' || checkOperator === 'is not') {
364
+ return this._not(checkOperator === 'is not').whereNull(column);
365
+ }
366
+ }
367
+
368
+ // Push onto the where statement stack.
369
+ this._statements.push({
370
+ grouping: 'where',
371
+ type: 'whereBasic',
372
+ column,
373
+ operator,
374
+ value,
375
+ not: this._not(),
376
+ bool: this._bool(),
377
+ asColumn: this._asColumnFlag,
378
+ });
379
+ return this;
380
+ },
381
+
382
+ whereColumn(column, operator, rightColumn) {
383
+ this._asColumnFlag = true;
384
+ this.where.apply(this, arguments);
385
+ this._asColumnFlag = false;
386
+ return this;
387
+ },
388
+
389
+ // Adds an `or where` clause to the query.
390
+ orWhere() {
391
+ this._bool('or');
392
+ const obj = arguments[0];
393
+ if (isObject(obj) && !(obj instanceof Raw)) {
394
+ return this.whereWrapped(function () {
395
+ for (const key in obj) {
396
+ this.andWhere(key, obj[key]);
397
+ }
398
+ });
399
+ }
400
+ return this.where.apply(this, arguments);
401
+ },
402
+
403
+ orWhereColumn() {
404
+ this._bool('or');
405
+ const obj = arguments[0];
406
+ if (isObject(obj) && !(obj instanceof Raw)) {
407
+ return this.whereWrapped(function () {
408
+ for (const key in obj) {
409
+ this.andWhereColumn(key, '=', obj[key]);
410
+ }
411
+ });
412
+ }
413
+ return this.whereColumn.apply(this, arguments);
414
+ },
415
+
416
+ // Adds an `not where` clause to the query.
417
+ whereNot() {
418
+ if (arguments.length >= 2) {
419
+ if (arguments[1] === 'in' || arguments[1] === 'between') {
420
+ this.client.logger.warn(
421
+ 'whereNot is not suitable for "in" and "between" type subqueries. You should use "not in" and "not between" instead.'
422
+ );
423
+ }
424
+ }
425
+ return this._not(true).where.apply(this, arguments);
426
+ },
427
+
428
+ whereNotColumn() {
429
+ return this._not(true).whereColumn.apply(this, arguments);
430
+ },
431
+
432
+ // Adds an `or not where` clause to the query.
433
+ orWhereNot() {
434
+ return this._bool('or').whereNot.apply(this, arguments);
435
+ },
436
+
437
+ orWhereNotColumn() {
438
+ return this._bool('or').whereNotColumn.apply(this, arguments);
439
+ },
440
+
441
+ // Processes an object literal provided in a "where" clause.
442
+ _objectWhere(obj) {
443
+ const boolVal = this._bool();
444
+ const notVal = this._not() ? 'Not' : '';
445
+ for (const key in obj) {
446
+ this[boolVal + 'Where' + notVal](key, obj[key]);
447
+ }
448
+ return this;
449
+ },
450
+
451
+ // Adds a raw `where` clause to the query.
452
+ whereRaw(sql, bindings) {
453
+ const raw = sql instanceof Raw ? sql : this.client.raw(sql, bindings);
454
+ this._statements.push({
455
+ grouping: 'where',
456
+ type: 'whereRaw',
457
+ value: raw,
458
+ not: this._not(),
459
+ bool: this._bool(),
460
+ });
461
+ return this;
462
+ },
463
+
464
+ orWhereRaw(sql, bindings) {
465
+ return this._bool('or').whereRaw(sql, bindings);
466
+ },
467
+
468
+ // Helper for compiling any advanced `where` queries.
469
+ whereWrapped(callback) {
470
+ this._statements.push({
471
+ grouping: 'where',
472
+ type: 'whereWrapped',
473
+ value: callback,
474
+ not: this._not(),
475
+ bool: this._bool(),
476
+ });
477
+ return this;
478
+ },
479
+
480
+ // Adds a `where exists` clause to the query.
481
+ whereExists(callback) {
482
+ this._statements.push({
483
+ grouping: 'where',
484
+ type: 'whereExists',
485
+ value: callback,
486
+ not: this._not(),
487
+ bool: this._bool(),
488
+ });
489
+ return this;
490
+ },
491
+
492
+ // Adds an `or where exists` clause to the query.
493
+ orWhereExists(callback) {
494
+ return this._bool('or').whereExists(callback);
495
+ },
496
+
497
+ // Adds a `where not exists` clause to the query.
498
+ whereNotExists(callback) {
499
+ return this._not(true).whereExists(callback);
500
+ },
501
+
502
+ // Adds a `or where not exists` clause to the query.
503
+ orWhereNotExists(callback) {
504
+ return this._bool('or').whereNotExists(callback);
505
+ },
506
+
507
+ // Adds a `where in` clause to the query.
508
+ whereIn(column, values) {
509
+ if (Array.isArray(values) && isEmpty(values))
510
+ return this.where(this._not());
511
+ this._statements.push({
512
+ grouping: 'where',
513
+ type: 'whereIn',
514
+ column,
515
+ value: values,
516
+ not: this._not(),
517
+ bool: this._bool(),
518
+ });
519
+ return this;
520
+ },
521
+
522
+ // Adds a `or where in` clause to the query.
523
+ orWhereIn(column, values) {
524
+ return this._bool('or').whereIn(column, values);
525
+ },
526
+
527
+ // Adds a `where not in` clause to the query.
528
+ whereNotIn(column, values) {
529
+ return this._not(true).whereIn(column, values);
530
+ },
531
+
532
+ // Adds a `or where not in` clause to the query.
533
+ orWhereNotIn(column, values) {
534
+ return this._bool('or')._not(true).whereIn(column, values);
535
+ },
536
+
537
+ // Adds a `where null` clause to the query.
538
+ whereNull(column) {
539
+ this._statements.push({
540
+ grouping: 'where',
541
+ type: 'whereNull',
542
+ column,
543
+ not: this._not(),
544
+ bool: this._bool(),
545
+ });
546
+ return this;
547
+ },
548
+
549
+ // Adds a `or where null` clause to the query.
550
+ orWhereNull(column) {
551
+ return this._bool('or').whereNull(column);
552
+ },
553
+
554
+ // Adds a `where not null` clause to the query.
555
+ whereNotNull(column) {
556
+ return this._not(true).whereNull(column);
557
+ },
558
+
559
+ // Adds a `or where not null` clause to the query.
560
+ orWhereNotNull(column) {
561
+ return this._bool('or').whereNotNull(column);
562
+ },
563
+
564
+ // Adds a `where between` clause to the query.
565
+ whereBetween(column, values) {
566
+ assert(
567
+ Array.isArray(values),
568
+ 'The second argument to whereBetween must be an array.'
569
+ );
570
+ assert(
571
+ values.length === 2,
572
+ 'You must specify 2 values for the whereBetween clause'
573
+ );
574
+ this._statements.push({
575
+ grouping: 'where',
576
+ type: 'whereBetween',
577
+ column,
578
+ value: values,
579
+ not: this._not(),
580
+ bool: this._bool(),
581
+ });
582
+ return this;
583
+ },
584
+
585
+ // Adds a `where not between` clause to the query.
586
+ whereNotBetween(column, values) {
587
+ return this._not(true).whereBetween(column, values);
588
+ },
589
+
590
+ // Adds a `or where between` clause to the query.
591
+ orWhereBetween(column, values) {
592
+ return this._bool('or').whereBetween(column, values);
593
+ },
594
+
595
+ // Adds a `or where not between` clause to the query.
596
+ orWhereNotBetween(column, values) {
597
+ return this._bool('or').whereNotBetween(column, values);
598
+ },
599
+
600
+ // Adds a `group by` clause to the query.
601
+ groupBy(item) {
602
+ if (item instanceof Raw) {
603
+ return this.groupByRaw.apply(this, arguments);
604
+ }
605
+ this._statements.push({
606
+ grouping: 'group',
607
+ type: 'groupByBasic',
608
+ value: helpers.normalizeArr.apply(null, arguments),
609
+ });
610
+ return this;
611
+ },
612
+
613
+ // Adds a raw `group by` clause to the query.
614
+ groupByRaw(sql, bindings) {
615
+ const raw = sql instanceof Raw ? sql : this.client.raw(sql, bindings);
616
+ this._statements.push({
617
+ grouping: 'group',
618
+ type: 'groupByRaw',
619
+ value: raw,
620
+ });
621
+ return this;
622
+ },
623
+
624
+ // Adds a `order by` clause to the query.
625
+ orderBy(column, direction) {
626
+ if (Array.isArray(column)) {
627
+ return this._orderByArray(column);
628
+ }
629
+ this._statements.push({
630
+ grouping: 'order',
631
+ type: 'orderByBasic',
632
+ value: column,
633
+ direction,
634
+ });
635
+ return this;
636
+ },
637
+
638
+ // Adds a `order by` with multiple columns to the query.
639
+ _orderByArray(columnDefs) {
640
+ for (let i = 0; i < columnDefs.length; i++) {
641
+ const columnInfo = columnDefs[i];
642
+ if (isObject(columnInfo)) {
643
+ this._statements.push({
644
+ grouping: 'order',
645
+ type: 'orderByBasic',
646
+ value: columnInfo['column'],
647
+ direction: columnInfo['order'],
648
+ });
649
+ } else if (isString(columnInfo)) {
650
+ this._statements.push({
651
+ grouping: 'order',
652
+ type: 'orderByBasic',
653
+ value: columnInfo,
654
+ });
655
+ }
656
+ }
657
+ return this;
658
+ },
659
+
660
+ // Add a raw `order by` clause to the query.
661
+ orderByRaw(sql, bindings) {
662
+ const raw = sql instanceof Raw ? sql : this.client.raw(sql, bindings);
663
+ this._statements.push({
664
+ grouping: 'order',
665
+ type: 'orderByRaw',
666
+ value: raw,
667
+ });
668
+ return this;
669
+ },
670
+
671
+ _union(clause, args) {
672
+ let callbacks = args[0];
673
+ let wrap = args[1];
674
+ if (args.length === 1 || (args.length === 2 && isBoolean(wrap))) {
675
+ if (!Array.isArray(callbacks)) {
676
+ callbacks = [callbacks];
677
+ }
678
+ for (let i = 0, l = callbacks.length; i < l; i++) {
679
+ this._statements.push({
680
+ grouping: 'union',
681
+ clause: clause,
682
+ value: callbacks[i],
683
+ wrap: wrap || false,
684
+ });
685
+ }
686
+ } else {
687
+ callbacks = toArray(args).slice(0, args.length - 1);
688
+ wrap = args[args.length - 1];
689
+ if (!isBoolean(wrap)) {
690
+ callbacks.push(wrap);
691
+ wrap = false;
692
+ }
693
+ this._union(clause, [callbacks, wrap]);
694
+ }
695
+ return this;
696
+ },
697
+
698
+ // Add a union statement to the query.
699
+ union(...args) {
700
+ return this._union('union', args);
701
+ },
702
+
703
+ // Adds a union all statement to the query.
704
+ unionAll(...args) {
705
+ return this._union('union all', args);
706
+ },
707
+
708
+ // Adds an intersect statement to the query
709
+ intersect(callbacks, wrap) {
710
+ if (arguments.length === 1 || (arguments.length === 2 && isBoolean(wrap))) {
711
+ if (!Array.isArray(callbacks)) {
712
+ callbacks = [callbacks];
713
+ }
714
+ for (let i = 0, l = callbacks.length; i < l; i++) {
715
+ this._statements.push({
716
+ grouping: 'union',
717
+ clause: 'intersect',
718
+ value: callbacks[i],
719
+ wrap: wrap || false,
720
+ });
721
+ }
722
+ } else {
723
+ callbacks = toArray(arguments).slice(0, arguments.length - 1);
724
+ wrap = arguments[arguments.length - 1];
725
+ if (!isBoolean(wrap)) {
726
+ callbacks.push(wrap);
727
+ wrap = false;
728
+ }
729
+ this.intersect(callbacks, wrap);
730
+ }
731
+ return this;
732
+ },
733
+
734
+ // Adds a `having` clause to the query.
735
+ having(column, operator, value) {
736
+ if (column instanceof Raw && arguments.length === 1) {
737
+ return this.havingRaw(column);
738
+ }
739
+
740
+ // Check if the column is a function, in which case it's
741
+ // a having statement wrapped in parens.
742
+ if (typeof column === 'function') {
743
+ return this.havingWrapped(column);
744
+ }
745
+
746
+ this._statements.push({
747
+ grouping: 'having',
748
+ type: 'havingBasic',
749
+ column,
750
+ operator,
751
+ value,
752
+ bool: this._bool(),
753
+ not: this._not(),
754
+ });
755
+ return this;
756
+ },
757
+
758
+ orHaving: function orHaving() {
759
+ this._bool('or');
760
+ const obj = arguments[0];
761
+ if (isObject(obj) && !(obj instanceof Raw)) {
762
+ return this.havingWrapped(function () {
763
+ for (const key in obj) {
764
+ this.andHaving(key, obj[key]);
765
+ }
766
+ });
767
+ }
768
+ return this.having.apply(this, arguments);
769
+ },
770
+
771
+ // Helper for compiling any advanced `having` queries.
772
+ havingWrapped(callback) {
773
+ this._statements.push({
774
+ grouping: 'having',
775
+ type: 'havingWrapped',
776
+ value: callback,
777
+ bool: this._bool(),
778
+ not: this._not(),
779
+ });
780
+ return this;
781
+ },
782
+
783
+ havingNull(column) {
784
+ this._statements.push({
785
+ grouping: 'having',
786
+ type: 'havingNull',
787
+ column,
788
+ not: this._not(),
789
+ bool: this._bool(),
790
+ });
791
+ return this;
792
+ },
793
+
794
+ orHavingNull(callback) {
795
+ return this._bool('or').havingNull(callback);
796
+ },
797
+
798
+ havingNotNull(callback) {
799
+ return this._not(true).havingNull(callback);
800
+ },
801
+
802
+ orHavingNotNull(callback) {
803
+ return this._not(true)._bool('or').havingNull(callback);
804
+ },
805
+
806
+ havingExists(callback) {
807
+ this._statements.push({
808
+ grouping: 'having',
809
+ type: 'havingExists',
810
+ value: callback,
811
+ not: this._not(),
812
+ bool: this._bool(),
813
+ });
814
+ return this;
815
+ },
816
+
817
+ orHavingExists(callback) {
818
+ return this._bool('or').havingExists(callback);
819
+ },
820
+
821
+ havingNotExists(callback) {
822
+ return this._not(true).havingExists(callback);
823
+ },
824
+
825
+ orHavingNotExists(callback) {
826
+ return this._not(true)._bool('or').havingExists(callback);
827
+ },
828
+
829
+ havingBetween(column, values) {
830
+ assert(
831
+ Array.isArray(values),
832
+ 'The second argument to havingBetween must be an array.'
833
+ );
834
+ assert(
835
+ values.length === 2,
836
+ 'You must specify 2 values for the havingBetween clause'
837
+ );
838
+ this._statements.push({
839
+ grouping: 'having',
840
+ type: 'havingBetween',
841
+ column,
842
+ value: values,
843
+ not: this._not(),
844
+ bool: this._bool(),
845
+ });
846
+ return this;
847
+ },
848
+
849
+ orHavingBetween(column, values) {
850
+ return this._bool('or').havingBetween(column, values);
851
+ },
852
+
853
+ havingNotBetween(column, values) {
854
+ return this._not(true).havingBetween(column, values);
855
+ },
856
+
857
+ orHavingNotBetween(column, values) {
858
+ return this._not(true)._bool('or').havingBetween(column, values);
859
+ },
860
+
861
+ havingIn(column, values) {
862
+ if (Array.isArray(values) && isEmpty(values))
863
+ return this.where(this._not());
864
+ this._statements.push({
865
+ grouping: 'having',
866
+ type: 'havingIn',
867
+ column,
868
+ value: values,
869
+ not: this._not(),
870
+ bool: this._bool(),
871
+ });
872
+ return this;
873
+ },
874
+
875
+ // Adds a `or where in` clause to the query.
876
+ orHavingIn(column, values) {
877
+ return this._bool('or').havingIn(column, values);
878
+ },
879
+
880
+ // Adds a `where not in` clause to the query.
881
+ havingNotIn(column, values) {
882
+ return this._not(true).havingIn(column, values);
883
+ },
884
+
885
+ // Adds a `or where not in` clause to the query.
886
+ orHavingNotIn(column, values) {
887
+ return this._bool('or')._not(true).havingIn(column, values);
888
+ },
889
+
890
+ // Adds a raw `having` clause to the query.
891
+ havingRaw(sql, bindings) {
892
+ const raw = sql instanceof Raw ? sql : this.client.raw(sql, bindings);
893
+ this._statements.push({
894
+ grouping: 'having',
895
+ type: 'havingRaw',
896
+ value: raw,
897
+ bool: this._bool(),
898
+ not: this._not(),
899
+ });
900
+ return this;
901
+ },
902
+
903
+ orHavingRaw(sql, bindings) {
904
+ return this._bool('or').havingRaw(sql, bindings);
905
+ },
906
+
907
+ // Only allow a single "offset" to be set for the current query.
908
+ offset(value) {
909
+ if (value == null || value instanceof Raw || value instanceof Builder) {
910
+ // Builder for backward compatibility
911
+ this._single.offset = value;
912
+ } else {
913
+ const val = parseInt(value, 10);
914
+ if (isNaN(val)) {
915
+ this.client.logger.warn('A valid integer must be provided to offset');
916
+ } else {
917
+ this._single.offset = val;
918
+ }
919
+ }
920
+ return this;
921
+ },
922
+
923
+ // Only allow a single "limit" to be set for the current query.
924
+ limit(value) {
925
+ const val = parseInt(value, 10);
926
+ if (isNaN(val)) {
927
+ this.client.logger.warn('A valid integer must be provided to limit');
928
+ } else {
929
+ this._single.limit = val;
930
+ }
931
+ return this;
932
+ },
933
+
934
+ // Retrieve the "count" result of the query.
935
+ count(column, options) {
936
+ return this._aggregate('count', column || '*', options);
937
+ },
938
+
939
+ // Retrieve the minimum value of a given column.
940
+ min(column, options) {
941
+ return this._aggregate('min', column, options);
942
+ },
943
+
944
+ // Retrieve the maximum value of a given column.
945
+ max(column, options) {
946
+ return this._aggregate('max', column, options);
947
+ },
948
+
949
+ // Retrieve the sum of the values of a given column.
950
+ sum(column, options) {
951
+ return this._aggregate('sum', column, options);
952
+ },
953
+
954
+ // Retrieve the average of the values of a given column.
955
+ avg(column, options) {
956
+ return this._aggregate('avg', column, options);
957
+ },
958
+
959
+ // Retrieve the "count" of the distinct results of the query.
960
+ countDistinct() {
961
+ let columns = helpers.normalizeArr.apply(null, arguments);
962
+ let options;
963
+ if (columns.length > 1 && isPlainObject(last(columns))) {
964
+ [options] = columns.splice(columns.length - 1, 1);
965
+ }
966
+
967
+ if (!columns.length) {
968
+ columns = '*';
969
+ } else if (columns.length === 1) {
970
+ columns = columns[0];
971
+ }
972
+
973
+ return this._aggregate('count', columns, { ...options, distinct: true });
974
+ },
975
+
976
+ // Retrieve the sum of the distinct values of a given column.
977
+ sumDistinct(column, options) {
978
+ return this._aggregate('sum', column, { ...options, distinct: true });
979
+ },
980
+
981
+ // Retrieve the vg of the distinct results of the query.
982
+ avgDistinct(column, options) {
983
+ return this._aggregate('avg', column, { ...options, distinct: true });
984
+ },
985
+
986
+ // Increments a column's value by the specified amount.
987
+ increment(column, amount = 1) {
988
+ if (isObject(column)) {
989
+ for (const key in column) {
990
+ this._counter(key, column[key]);
991
+ }
992
+
993
+ return this;
994
+ }
995
+
996
+ return this._counter(column, amount);
997
+ },
998
+
999
+ // Decrements a column's value by the specified amount.
1000
+ decrement(column, amount = 1) {
1001
+ if (isObject(column)) {
1002
+ for (const key in column) {
1003
+ this._counter(key, -column[key]);
1004
+ }
1005
+
1006
+ return this;
1007
+ }
1008
+
1009
+ return this._counter(column, -amount);
1010
+ },
1011
+
1012
+ // Clears increments/decrements
1013
+ clearCounters() {
1014
+ this._single.counter = {};
1015
+ return this;
1016
+ },
1017
+
1018
+ // Sets the values for a `select` query, informing that only the first
1019
+ // row should be returned (limit 1).
1020
+ first() {
1021
+ if (!this._isSelectQuery()) {
1022
+ throw new Error(`Cannot chain .first() on "${this._method}" query!`);
1023
+ }
1024
+
1025
+ const args = new Array(arguments.length);
1026
+ for (let i = 0; i < args.length; i++) {
1027
+ args[i] = arguments[i];
1028
+ }
1029
+ this.select.apply(this, args);
1030
+ this._method = 'first';
1031
+ this.limit(1);
1032
+ return this;
1033
+ },
1034
+
1035
+ // Use existing connection to execute the query
1036
+ // Same value that client.acquireConnection() for an according client returns should be passed
1037
+ connection(_connection) {
1038
+ this._connection = _connection;
1039
+ return this;
1040
+ },
1041
+
1042
+ // Pluck a column from a query.
1043
+ pluck(column) {
1044
+ this._method = 'pluck';
1045
+ this._single.pluck = column;
1046
+ this._statements.push({
1047
+ grouping: 'columns',
1048
+ type: 'pluck',
1049
+ value: column,
1050
+ });
1051
+ return this;
1052
+ },
1053
+
1054
+ // Deprecated. Remove everything from select clause
1055
+ clearSelect() {
1056
+ this._clearGrouping('columns');
1057
+ return this;
1058
+ },
1059
+
1060
+ // Deprecated. Remove everything from where clause
1061
+ clearWhere() {
1062
+ this._clearGrouping('where');
1063
+ return this;
1064
+ },
1065
+
1066
+ // Deprecated. Remove everything from group clause
1067
+ clearGroup() {
1068
+ this._clearGrouping('group');
1069
+ return this;
1070
+ },
1071
+
1072
+ // Deprecated. Remove everything from order clause
1073
+ clearOrder() {
1074
+ this._clearGrouping('order');
1075
+ return this;
1076
+ },
1077
+
1078
+ // Deprecated. Remove everything from having clause
1079
+ clearHaving() {
1080
+ this._clearGrouping('having');
1081
+ return this;
1082
+ },
1083
+
1084
+ // Remove everything from statement clause
1085
+ clear(statement) {
1086
+ if (!['with', 'select', 'columns', 'hintComments', 'where', 'union', 'join', 'group', 'order', 'having', 'limit', 'offset', 'counter', 'counters'].includes(statement))
1087
+ throw new Error(`Knex Error: unknown statement '${statement}'`);
1088
+ if (statement.startsWith('counter')) return this.clearCounters();
1089
+ if (statement === 'select') { statement = 'columns'; }
1090
+ this._clearGrouping(statement);
1091
+ return this;
1092
+ },
1093
+
1094
+ // Insert & Update
1095
+ // ------
1096
+
1097
+ // Sets the values for an `insert` query.
1098
+ insert(values, returning, options) {
1099
+ this._method = 'insert';
1100
+ if (!isEmpty(returning)) this.returning(returning, options);
1101
+ this._single.insert = values;
1102
+ return this;
1103
+ },
1104
+
1105
+ // Sets the values for an `update`, allowing for both
1106
+ // `.update(key, value, [returning])` and `.update(obj, [returning])` syntaxes.
1107
+ update(values, returning, options) {
1108
+ let ret;
1109
+ const obj = this._single.update || {};
1110
+ this._method = 'update';
1111
+ if (isString(values)) {
1112
+ obj[values] = returning;
1113
+ if (arguments.length > 2) {
1114
+ ret = arguments[2];
1115
+ }
1116
+ } else {
1117
+ const keys = Object.keys(values);
1118
+ if (this._single.update) {
1119
+ this.client.logger.warn('Update called multiple times with objects.');
1120
+ }
1121
+ let i = -1;
1122
+ while (++i < keys.length) {
1123
+ obj[keys[i]] = values[keys[i]];
1124
+ }
1125
+ ret = arguments[1];
1126
+ }
1127
+ if (!isEmpty(ret)) this.returning(ret, options);
1128
+ this._single.update = obj;
1129
+ return this;
1130
+ },
1131
+
1132
+ // Sets the returning value for the query.
1133
+ returning(returning, options) {
1134
+ this._single.returning = returning;
1135
+ this._single.options = options;
1136
+ return this;
1137
+ },
1138
+
1139
+
1140
+ onConflict(columns) {
1141
+ if (typeof columns === 'string') {
1142
+ columns = [columns];
1143
+ }
1144
+ return new OnConflictBuilder(this, columns || true);
1145
+ },
1146
+
1147
+ // Delete
1148
+ // ------
1149
+
1150
+ // Executes a delete statement on the query;
1151
+ delete(ret, options) {
1152
+ this._method = 'del';
1153
+ if (!isEmpty(ret)) this.returning(ret, options);
1154
+ return this;
1155
+ },
1156
+
1157
+ // Truncates a table, ends the query chain.
1158
+ truncate(tableName) {
1159
+ this._method = 'truncate';
1160
+ if (tableName) {
1161
+ this._single.table = tableName;
1162
+ }
1163
+ return this;
1164
+ },
1165
+
1166
+ // Retrieves columns for the table specified by `knex(tableName)`
1167
+ columnInfo(column) {
1168
+ this._method = 'columnInfo';
1169
+ this._single.columnInfo = column;
1170
+ return this;
1171
+ },
1172
+
1173
+ // Set a lock for update constraint.
1174
+ forUpdate() {
1175
+ this._single.lock = lockMode.forUpdate;
1176
+ this._single.lockTables = helpers.normalizeArr.apply(null, arguments);
1177
+ return this;
1178
+ },
1179
+
1180
+ // Set a lock for share constraint.
1181
+ forShare() {
1182
+ this._single.lock = lockMode.forShare;
1183
+ this._single.lockTables = helpers.normalizeArr.apply(null, arguments);
1184
+ return this;
1185
+ },
1186
+
1187
+ // Skips locked rows when using a lock constraint.
1188
+ skipLocked() {
1189
+ if (!this._isSelectQuery()) {
1190
+ throw new Error(`Cannot chain .skipLocked() on "${this._method}" query!`);
1191
+ }
1192
+ if (!this._hasLockMode()) {
1193
+ throw new Error(
1194
+ '.skipLocked() can only be used after a call to .forShare() or .forUpdate()!'
1195
+ );
1196
+ }
1197
+ if (this._single.waitMode === waitMode.noWait) {
1198
+ throw new Error('.skipLocked() cannot be used together with .noWait()!');
1199
+ }
1200
+ this._single.waitMode = waitMode.skipLocked;
1201
+ return this;
1202
+ },
1203
+
1204
+ // Causes error when acessing a locked row instead of waiting for it to be released.
1205
+ noWait() {
1206
+ if (!this._isSelectQuery()) {
1207
+ throw new Error(`Cannot chain .noWait() on "${this._method}" query!`);
1208
+ }
1209
+ if (!this._hasLockMode()) {
1210
+ throw new Error(
1211
+ '.noWait() can only be used after a call to .forShare() or .forUpdate()!'
1212
+ );
1213
+ }
1214
+ if (this._single.waitMode === waitMode.skipLocked) {
1215
+ throw new Error('.noWait() cannot be used together with .skipLocked()!');
1216
+ }
1217
+ this._single.waitMode = waitMode.noWait;
1218
+ return this;
1219
+ },
1220
+
1221
+ // Takes a JS object of methods to call and calls them
1222
+ fromJS(obj) {
1223
+ each(obj, (val, key) => {
1224
+ if (typeof this[key] !== 'function') {
1225
+ this.client.logger.warn(`Knex Error: unknown key ${key}`);
1226
+ }
1227
+ if (Array.isArray(val)) {
1228
+ this[key].apply(this, val);
1229
+ } else {
1230
+ this[key](val);
1231
+ }
1232
+ });
1233
+ return this;
1234
+ },
1235
+
1236
+ // Passes query to provided callback function, useful for e.g. composing
1237
+ // domain-specific helpers
1238
+ modify(callback) {
1239
+ callback.apply(this, [this].concat(tail(arguments)));
1240
+ return this;
1241
+ },
1242
+
1243
+ // ----------------------------------------------------------------------
1244
+
1245
+ // Helper for the incrementing/decrementing queries.
1246
+ _counter(column, amount) {
1247
+ amount = parseFloat(amount);
1248
+
1249
+ this._method = 'update';
1250
+
1251
+ this._single.counter = this._single.counter || {};
1252
+
1253
+ this._single.counter[column] = amount;
1254
+
1255
+ return this;
1256
+ },
1257
+
1258
+ // Helper to get or set the "boolFlag" value.
1259
+ _bool(val) {
1260
+ if (arguments.length === 1) {
1261
+ this._boolFlag = val;
1262
+ return this;
1263
+ }
1264
+ const ret = this._boolFlag;
1265
+ this._boolFlag = 'and';
1266
+ return ret;
1267
+ },
1268
+
1269
+ // Helper to get or set the "notFlag" value.
1270
+ _not(val) {
1271
+ if (arguments.length === 1) {
1272
+ this._notFlag = val;
1273
+ return this;
1274
+ }
1275
+ const ret = this._notFlag;
1276
+ this._notFlag = false;
1277
+ return ret;
1278
+ },
1279
+
1280
+ // Helper to get or set the "joinFlag" value.
1281
+ _joinType(val) {
1282
+ if (arguments.length === 1) {
1283
+ this._joinFlag = val;
1284
+ return this;
1285
+ }
1286
+ const ret = this._joinFlag || 'inner';
1287
+ this._joinFlag = 'inner';
1288
+ return ret;
1289
+ },
1290
+
1291
+ // Helper for compiling any aggregate queries.
1292
+ _aggregate(method, column, options = {}) {
1293
+ this._statements.push({
1294
+ grouping: 'columns',
1295
+ type: column instanceof Raw ? 'aggregateRaw' : 'aggregate',
1296
+ method,
1297
+ value: column,
1298
+ aggregateDistinct: options.distinct || false,
1299
+ alias: options.as,
1300
+ });
1301
+ return this;
1302
+ },
1303
+
1304
+ // Helper function for clearing or reseting a grouping type from the builder
1305
+ _clearGrouping(grouping) {
1306
+ if (grouping in this._single) {
1307
+ this._single[grouping] = undefined;
1308
+ } else {
1309
+ this._statements = reject(this._statements, { grouping });
1310
+ }
1311
+ },
1312
+
1313
+ // Helper function that checks if the builder will emit a select query
1314
+ _isSelectQuery() {
1315
+ return ['pluck', 'first', 'select'].includes(this._method);
1316
+ },
1317
+
1318
+ // Helper function that checks if the query has a lock mode set
1319
+ _hasLockMode() {
1320
+ return [lockMode.forShare, lockMode.forUpdate].includes(this._single.lock);
1321
+ },
1322
+ });
1323
+
1324
+ Object.defineProperty(Builder.prototype, 'or', {
1325
+ get() {
1326
+ return this._bool('or');
1327
+ },
1328
+ });
1329
+
1330
+ Object.defineProperty(Builder.prototype, 'not', {
1331
+ get() {
1332
+ return this._not(true);
1333
+ },
1334
+ });
1335
+
1336
+ Builder.prototype.select = Builder.prototype.columns;
1337
+ Builder.prototype.column = Builder.prototype.columns;
1338
+ Builder.prototype.andWhereNot = Builder.prototype.whereNot;
1339
+ Builder.prototype.andWhereNotColumn = Builder.prototype.whereNotColumn;
1340
+ Builder.prototype.andWhere = Builder.prototype.where;
1341
+ Builder.prototype.andWhereColumn = Builder.prototype.whereColumn;
1342
+ Builder.prototype.andWhereRaw = Builder.prototype.whereRaw;
1343
+ Builder.prototype.andWhereBetween = Builder.prototype.whereBetween;
1344
+ Builder.prototype.andWhereNotBetween = Builder.prototype.whereNotBetween;
1345
+ Builder.prototype.andHaving = Builder.prototype.having;
1346
+ Builder.prototype.andHavingIn = Builder.prototype.havingIn;
1347
+ Builder.prototype.andHavingNotIn = Builder.prototype.havingNotIn;
1348
+ Builder.prototype.andHavingNull = Builder.prototype.havingNull;
1349
+ Builder.prototype.andHavingNotNull = Builder.prototype.havingNotNull;
1350
+ Builder.prototype.andHavingExists = Builder.prototype.havingExists;
1351
+ Builder.prototype.andHavingNotExists = Builder.prototype.havingNotExists;
1352
+ Builder.prototype.andHavingBetween = Builder.prototype.havingBetween;
1353
+ Builder.prototype.andHavingNotBetween = Builder.prototype.havingNotBetween;
1354
+ Builder.prototype.from = Builder.prototype.table;
1355
+ Builder.prototype.into = Builder.prototype.table;
1356
+ Builder.prototype.del = Builder.prototype.delete;
1357
+
1358
+ // Attach all of the top level promise methods that should be chainable.
1359
+ require('../interface')(Builder);
1360
+ helpers.addQueryContext(Builder);
1361
+
1362
+ Builder.extend = (methodName, fn) => {
1363
+ if (Object.prototype.hasOwnProperty.call(Builder.prototype, methodName)) {
1364
+ throw new Error(
1365
+ `Can't extend QueryBuilder with existing method ('${methodName}').`
1366
+ );
1367
+ }
1368
+
1369
+ assign(Builder.prototype, { [methodName]: fn });
1370
+ };
1371
+
1372
+ module.exports = Builder;