knex 2.5.0 → 3.0.0

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 (190) hide show
  1. package/CHANGELOG.md +78 -59
  2. package/CONTRIBUTING.md +194 -194
  3. package/LICENSE +22 -22
  4. package/README.md +149 -147
  5. package/UPGRADING.md +245 -233
  6. package/bin/cli.js +475 -473
  7. package/bin/utils/cli-config-utils.js +212 -210
  8. package/bin/utils/constants.js +7 -7
  9. package/bin/utils/migrationsLister.js +37 -37
  10. package/knex.js +23 -23
  11. package/knex.mjs +11 -11
  12. package/lib/builder-interface-augmenter.js +120 -120
  13. package/lib/client.js +495 -495
  14. package/lib/constants.js +61 -61
  15. package/lib/dialects/better-sqlite3/index.js +77 -77
  16. package/lib/dialects/cockroachdb/crdb-columncompiler.js +14 -14
  17. package/lib/dialects/cockroachdb/crdb-querybuilder.js +11 -11
  18. package/lib/dialects/cockroachdb/crdb-querycompiler.js +122 -122
  19. package/lib/dialects/cockroachdb/crdb-tablecompiler.js +37 -37
  20. package/lib/dialects/cockroachdb/crdb-viewcompiler.js +15 -15
  21. package/lib/dialects/cockroachdb/index.js +86 -86
  22. package/lib/dialects/mssql/index.js +500 -500
  23. package/lib/dialects/mssql/mssql-formatter.js +34 -34
  24. package/lib/dialects/mssql/query/mssql-querycompiler.js +601 -601
  25. package/lib/dialects/mssql/schema/mssql-columncompiler.js +185 -185
  26. package/lib/dialects/mssql/schema/mssql-compiler.js +91 -91
  27. package/lib/dialects/mssql/schema/mssql-tablecompiler.js +378 -378
  28. package/lib/dialects/mssql/schema/mssql-viewcompiler.js +55 -55
  29. package/lib/dialects/mssql/transaction.js +176 -176
  30. package/lib/dialects/mysql/index.js +201 -201
  31. package/lib/dialects/mysql/query/mysql-querycompiler.js +274 -274
  32. package/lib/dialects/mysql/schema/mysql-columncompiler.js +193 -193
  33. package/lib/dialects/mysql/schema/mysql-compiler.js +60 -60
  34. package/lib/dialects/mysql/schema/mysql-tablecompiler.js +381 -381
  35. package/lib/dialects/mysql/schema/mysql-viewbuilder.js +21 -21
  36. package/lib/dialects/mysql/schema/mysql-viewcompiler.js +15 -15
  37. package/lib/dialects/mysql/transaction.js +46 -46
  38. package/lib/dialects/mysql2/index.js +53 -53
  39. package/lib/dialects/mysql2/transaction.js +44 -44
  40. package/lib/dialects/oracle/DEAD_CODE.md +5 -5
  41. package/lib/dialects/oracle/index.js +92 -92
  42. package/lib/dialects/oracle/query/oracle-querycompiler.js +343 -343
  43. package/lib/dialects/oracle/schema/internal/incrementUtils.js +20 -20
  44. package/lib/dialects/oracle/schema/internal/trigger.js +135 -135
  45. package/lib/dialects/oracle/schema/oracle-columnbuilder.js +17 -17
  46. package/lib/dialects/oracle/schema/oracle-columncompiler.js +126 -126
  47. package/lib/dialects/oracle/schema/oracle-compiler.js +122 -122
  48. package/lib/dialects/oracle/schema/oracle-tablecompiler.js +190 -190
  49. package/lib/dialects/oracle/utils.js +87 -87
  50. package/lib/dialects/oracledb/index.js +327 -327
  51. package/lib/dialects/oracledb/query/oracledb-querycompiler.js +481 -481
  52. package/lib/dialects/oracledb/schema/oracledb-columncompiler.js +61 -61
  53. package/lib/dialects/oracledb/schema/oracledb-tablecompiler.js +19 -19
  54. package/lib/dialects/oracledb/schema/oracledb-viewbuilder.js +13 -13
  55. package/lib/dialects/oracledb/schema/oracledb-viewcompiler.js +19 -19
  56. package/lib/dialects/oracledb/transaction.js +98 -98
  57. package/lib/dialects/oracledb/utils.js +208 -208
  58. package/lib/dialects/pgnative/index.js +60 -60
  59. package/lib/dialects/postgres/execution/pg-transaction.js +19 -19
  60. package/lib/dialects/postgres/index.js +358 -358
  61. package/lib/dialects/postgres/query/pg-querybuilder.js +43 -43
  62. package/lib/dialects/postgres/query/pg-querycompiler.js +400 -400
  63. package/lib/dialects/postgres/schema/pg-columncompiler.js +156 -156
  64. package/lib/dialects/postgres/schema/pg-compiler.js +138 -138
  65. package/lib/dialects/postgres/schema/pg-tablecompiler.js +304 -304
  66. package/lib/dialects/postgres/schema/pg-viewbuilder.js +21 -21
  67. package/lib/dialects/postgres/schema/pg-viewcompiler.js +35 -35
  68. package/lib/dialects/redshift/index.js +86 -86
  69. package/lib/dialects/redshift/query/redshift-querycompiler.js +163 -163
  70. package/lib/dialects/redshift/schema/redshift-columnbuilder.js +22 -22
  71. package/lib/dialects/redshift/schema/redshift-columncompiler.js +67 -67
  72. package/lib/dialects/redshift/schema/redshift-compiler.js +14 -14
  73. package/lib/dialects/redshift/schema/redshift-tablecompiler.js +122 -122
  74. package/lib/dialects/redshift/schema/redshift-viewcompiler.js +11 -11
  75. package/lib/dialects/redshift/transaction.js +32 -32
  76. package/lib/dialects/sqlite3/execution/sqlite-transaction.js +25 -25
  77. package/lib/dialects/sqlite3/index.js +250 -250
  78. package/lib/dialects/sqlite3/query/sqlite-querybuilder.js +33 -33
  79. package/lib/dialects/sqlite3/query/sqlite-querycompiler.js +334 -334
  80. package/lib/dialects/sqlite3/schema/ddl.js +400 -400
  81. package/lib/dialects/sqlite3/schema/internal/compiler.js +327 -327
  82. package/lib/dialects/sqlite3/schema/internal/parser-combinator.js +161 -161
  83. package/lib/dialects/sqlite3/schema/internal/parser.js +638 -638
  84. package/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js +41 -41
  85. package/lib/dialects/sqlite3/schema/internal/tokenizer.js +38 -38
  86. package/lib/dialects/sqlite3/schema/internal/utils.js +12 -12
  87. package/lib/dialects/sqlite3/schema/sqlite-columncompiler.js +50 -50
  88. package/lib/dialects/sqlite3/schema/sqlite-compiler.js +80 -80
  89. package/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js +347 -347
  90. package/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js +40 -40
  91. package/lib/execution/batch-insert.js +51 -51
  92. package/lib/execution/internal/delay.js +6 -6
  93. package/lib/execution/internal/ensure-connection-callback.js +41 -41
  94. package/lib/execution/internal/query-executioner.js +62 -62
  95. package/lib/execution/runner.js +325 -325
  96. package/lib/execution/transaction.js +409 -409
  97. package/lib/formatter/formatterUtils.js +42 -42
  98. package/lib/formatter/rawFormatter.js +84 -84
  99. package/lib/formatter/wrappingFormatter.js +250 -250
  100. package/lib/formatter.js +25 -25
  101. package/lib/index.js +3 -3
  102. package/lib/knex-builder/FunctionHelper.js +80 -80
  103. package/lib/knex-builder/Knex.js +59 -59
  104. package/lib/knex-builder/internal/config-resolver.js +57 -57
  105. package/lib/knex-builder/internal/parse-connection.js +87 -87
  106. package/lib/knex-builder/make-knex.js +345 -345
  107. package/lib/logger.js +76 -76
  108. package/lib/migrations/common/MigrationsLoader.js +36 -36
  109. package/lib/migrations/migrate/MigrationGenerator.js +84 -84
  110. package/lib/migrations/migrate/Migrator.js +599 -598
  111. package/lib/migrations/migrate/migrate-stub.js +17 -17
  112. package/lib/migrations/migrate/migration-list-resolver.js +33 -33
  113. package/lib/migrations/migrate/migrator-configuration-merger.js +58 -58
  114. package/lib/migrations/migrate/sources/fs-migrations.js +74 -74
  115. package/lib/migrations/migrate/stub/cjs.stub +15 -15
  116. package/lib/migrations/migrate/stub/coffee.stub +13 -13
  117. package/lib/migrations/migrate/stub/eg.stub +14 -14
  118. package/lib/migrations/migrate/stub/js-schema.stub +22 -22
  119. package/lib/migrations/migrate/stub/js.stub +22 -22
  120. package/lib/migrations/migrate/stub/knexfile-coffee.stub +34 -34
  121. package/lib/migrations/migrate/stub/knexfile-eg.stub +43 -43
  122. package/lib/migrations/migrate/stub/knexfile-js.stub +47 -47
  123. package/lib/migrations/migrate/stub/knexfile-ls.stub +35 -35
  124. package/lib/migrations/migrate/stub/knexfile-ts.stub +47 -47
  125. package/lib/migrations/migrate/stub/ls.stub +14 -14
  126. package/lib/migrations/migrate/stub/mjs.stub +23 -23
  127. package/lib/migrations/migrate/stub/ts-schema.stub +21 -21
  128. package/lib/migrations/migrate/stub/ts.stub +21 -21
  129. package/lib/migrations/migrate/table-creator.js +77 -77
  130. package/lib/migrations/migrate/table-resolver.js +27 -27
  131. package/lib/migrations/seed/Seeder.js +137 -137
  132. package/lib/migrations/seed/seed-stub.js +13 -13
  133. package/lib/migrations/seed/seeder-configuration-merger.js +60 -60
  134. package/lib/migrations/seed/sources/fs-seeds.js +65 -65
  135. package/lib/migrations/seed/stub/coffee.stub +9 -9
  136. package/lib/migrations/seed/stub/eg.stub +11 -11
  137. package/lib/migrations/seed/stub/js.stub +13 -13
  138. package/lib/migrations/seed/stub/ls.stub +11 -11
  139. package/lib/migrations/seed/stub/mjs.stub +12 -12
  140. package/lib/migrations/seed/stub/ts.stub +13 -13
  141. package/lib/migrations/util/fs.js +86 -86
  142. package/lib/migrations/util/import-file.js +12 -12
  143. package/lib/migrations/util/is-module-type.js +9 -9
  144. package/lib/migrations/util/template.js +52 -52
  145. package/lib/migrations/util/timestamp.js +14 -14
  146. package/lib/query/analytic.js +52 -52
  147. package/lib/query/constants.js +15 -15
  148. package/lib/query/joinclause.js +270 -270
  149. package/lib/query/method-constants.js +136 -136
  150. package/lib/query/querybuilder.js +1793 -1793
  151. package/lib/query/querycompiler.js +1591 -1591
  152. package/lib/raw.js +139 -139
  153. package/lib/ref.js +39 -39
  154. package/lib/schema/builder.js +115 -115
  155. package/lib/schema/columnbuilder.js +146 -146
  156. package/lib/schema/columncompiler.js +307 -307
  157. package/lib/schema/compiler.js +187 -187
  158. package/lib/schema/internal/helpers.js +55 -55
  159. package/lib/schema/tablebuilder.js +376 -376
  160. package/lib/schema/tablecompiler.js +433 -433
  161. package/lib/schema/viewbuilder.js +92 -92
  162. package/lib/schema/viewcompiler.js +138 -138
  163. package/lib/util/finally-mixin.js +13 -13
  164. package/lib/util/helpers.js +95 -95
  165. package/lib/util/is.js +32 -32
  166. package/lib/util/nanoid.js +40 -40
  167. package/lib/util/noop.js +1 -1
  168. package/lib/util/save-async-stack.js +14 -14
  169. package/lib/util/security.js +26 -26
  170. package/lib/util/string.js +190 -190
  171. package/lib/util/timeout.js +29 -29
  172. package/package.json +13 -12
  173. package/scripts/build.js +125 -125
  174. package/scripts/clean.js +31 -31
  175. package/scripts/docker-compose.yml +152 -152
  176. package/scripts/next-release-howto.md +24 -24
  177. package/scripts/oracledb-install-driver-libs.sh +82 -82
  178. package/scripts/release.sh +36 -34
  179. package/scripts/runkit-example.js +35 -34
  180. package/scripts/stress-test/README.txt +18 -18
  181. package/scripts/stress-test/docker-compose.yml +57 -57
  182. package/scripts/stress-test/knex-stress-test.js +212 -208
  183. package/scripts/stress-test/mysql2-random-hanging-every-now-and-then.js +149 -145
  184. package/scripts/stress-test/mysql2-sudden-exit-without-error.js +101 -100
  185. package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +188 -184
  186. package/scripts/update_gitignore_for_tsc_output.js +90 -90
  187. package/types/index.d.ts +3272 -3273
  188. package/types/result.d.ts +27 -27
  189. package/types/tables.d.ts +4 -4
  190. package/lib/dialects/index.js +0 -34
@@ -1,325 +1,325 @@
1
- const { KnexTimeoutError } = require('../util/timeout');
2
- const { timeout } = require('../util/timeout');
3
- const {
4
- ensureConnectionCallback,
5
- ensureConnectionStreamCallback,
6
- } = require('./internal/ensure-connection-callback');
7
-
8
- let Transform;
9
-
10
- // The "Runner" constructor takes a "builder" (query, schema, or raw)
11
- // and runs through each of the query statements, calling any additional
12
- // "output" method provided alongside the query and bindings.
13
- class Runner {
14
- constructor(client, builder) {
15
- this.client = client;
16
- this.builder = builder;
17
- this.queries = [];
18
-
19
- // The "connection" object is set on the runner when
20
- // "run" is called.
21
- this.connection = undefined;
22
- }
23
-
24
- // "Run" the target, calling "toSQL" on the builder, returning
25
- // an object or array of queries to run, each of which are run on
26
- // a single connection.
27
- async run() {
28
- const runner = this;
29
- try {
30
- const res = await this.ensureConnection(ensureConnectionCallback);
31
-
32
- // Fire a single "end" event on the builder when
33
- // all queries have successfully completed.
34
- runner.builder.emit('end');
35
- return res;
36
-
37
- // If there are any "error" listeners, we fire an error event
38
- // and then re-throw the error to be eventually handled by
39
- // the promise chain. Useful if you're wrapping in a custom `Promise`.
40
- } catch (err) {
41
- if (runner.builder._events && runner.builder._events.error) {
42
- runner.builder.emit('error', err);
43
- }
44
- throw err;
45
- }
46
- }
47
-
48
- // Stream the result set, by passing through to the dialect's streaming
49
- // capabilities. If the options are
50
- stream(optionsOrHandler, handlerOrNil) {
51
- const firstOptionIsHandler =
52
- typeof optionsOrHandler === 'function' && arguments.length === 1;
53
-
54
- const options = firstOptionIsHandler ? {} : optionsOrHandler;
55
- const handler = firstOptionIsHandler ? optionsOrHandler : handlerOrNil;
56
-
57
- // Determines whether we emit an error or throw here.
58
- const hasHandler = typeof handler === 'function';
59
-
60
- // Lazy-load the "Transform" dependency.
61
- Transform = Transform || require('stream').Transform;
62
-
63
- const queryContext = this.builder.queryContext();
64
-
65
- const stream = new Transform({
66
- objectMode: true,
67
- transform: (chunk, _, callback) => {
68
- callback(null, this.client.postProcessResponse(chunk, queryContext));
69
- },
70
- });
71
- stream.on('close', () => {
72
- this.client.releaseConnection(this.connection);
73
- });
74
-
75
- // If the stream is manually destroyed, the close event is not
76
- // propagated to the top of the pipe chain. We need to manually verify
77
- // that the source stream is closed and if not, manually destroy it.
78
- stream.on('pipe', (sourceStream) => {
79
- const cleanSourceStream = () => {
80
- if (!sourceStream.closed) {
81
- sourceStream.destroy();
82
- }
83
- };
84
-
85
- // Stream already closed, cleanup immediately
86
- if (stream.closed) {
87
- cleanSourceStream();
88
- } else {
89
- stream.on('close', cleanSourceStream);
90
- }
91
- });
92
-
93
- const connectionAcquirePromise = this.ensureConnection(
94
- ensureConnectionStreamCallback,
95
- {
96
- options,
97
- hasHandler,
98
- stream,
99
- }
100
- )
101
- // Emit errors on the stream if the error occurred before a connection
102
- // could be acquired.
103
- // If the connection was acquired, assume the error occurred in the client
104
- // code and has already been emitted on the stream. Don't emit it twice.
105
- .catch((err) => {
106
- if (!this.connection) {
107
- stream.emit('error', err);
108
- }
109
- });
110
-
111
- // If a function is passed to handle the stream, send the stream
112
- // there and return the promise, otherwise just return the stream
113
- // and the promise will take care of itself.
114
- if (hasHandler) {
115
- handler(stream);
116
- return connectionAcquirePromise;
117
- }
118
- return stream;
119
- }
120
-
121
- // Allow you to pipe the stream to a writable stream.
122
- pipe(writable, options) {
123
- return this.stream(options).pipe(writable);
124
- }
125
-
126
- // "Runs" a query, returning a promise. All queries specified by the builder are guaranteed
127
- // to run in sequence, and on the same connection, especially helpful when schema building
128
- // and dealing with foreign key constraints, etc.
129
- async query(obj) {
130
- const { __knexUid, __knexTxId } = this.connection;
131
-
132
- this.builder.emit('query', Object.assign({ __knexUid, __knexTxId }, obj));
133
-
134
- const runner = this;
135
- const queryContext = this.builder.queryContext();
136
- // query-error events are emitted before the queryPromise continuations.
137
- // pass queryContext into client.query so it can be raised properly.
138
- if (obj !== null && typeof obj === 'object') {
139
- obj.queryContext = queryContext;
140
- }
141
- let queryPromise = this.client.query(this.connection, obj);
142
-
143
- if (obj.timeout) {
144
- queryPromise = timeout(queryPromise, obj.timeout);
145
- }
146
-
147
- // Await the return value of client.processResponse; in the case of sqlite3's
148
- // dropColumn()/renameColumn(), it will be a Promise for the transaction
149
- // containing the complete rename procedure.
150
- return queryPromise
151
- .then((resp) => this.client.processResponse(resp, runner))
152
- .then((processedResponse) => {
153
- const postProcessedResponse = this.client.postProcessResponse(
154
- processedResponse,
155
- queryContext
156
- );
157
-
158
- this.builder.emit(
159
- 'query-response',
160
- postProcessedResponse,
161
- Object.assign({ __knexUid, __knexTxId }, obj),
162
- this.builder
163
- );
164
-
165
- this.client.emit(
166
- 'query-response',
167
- postProcessedResponse,
168
- Object.assign({ __knexUid, __knexTxId }, obj),
169
- this.builder
170
- );
171
-
172
- return postProcessedResponse;
173
- })
174
- .catch((error) => {
175
- if (!(error instanceof KnexTimeoutError)) {
176
- return Promise.reject(error);
177
- }
178
- const { timeout, sql, bindings } = obj;
179
-
180
- let cancelQuery;
181
- if (obj.cancelOnTimeout) {
182
- cancelQuery = this.client.cancelQuery(this.connection);
183
- } else {
184
- // If we don't cancel the query, we need to mark the connection as disposed so that
185
- // it gets destroyed by the pool and is never used again. If we don't do this and
186
- // return the connection to the pool, it will be useless until the current operation
187
- // that timed out, finally finishes.
188
- this.connection.__knex__disposed = error;
189
- cancelQuery = Promise.resolve();
190
- }
191
-
192
- return cancelQuery
193
- .catch((cancelError) => {
194
- // If the cancellation failed, we need to mark the connection as disposed so that
195
- // it gets destroyed by the pool and is never used again. If we don't do this and
196
- // return the connection to the pool, it will be useless until the current operation
197
- // that timed out, finally finishes.
198
- this.connection.__knex__disposed = error;
199
-
200
- // cancellation failed
201
- throw Object.assign(cancelError, {
202
- message: `After query timeout of ${timeout}ms exceeded, cancelling of query failed.`,
203
- sql,
204
- bindings,
205
- timeout,
206
- });
207
- })
208
- .then(() => {
209
- // cancellation succeeded, rethrow timeout error
210
- throw Object.assign(error, {
211
- message: `Defined query timeout of ${timeout}ms exceeded when running query.`,
212
- sql,
213
- bindings,
214
- timeout,
215
- });
216
- });
217
- })
218
- .catch((error) => {
219
- this.builder.emit(
220
- 'query-error',
221
- error,
222
- Object.assign({ __knexUid, __knexTxId, queryContext }, obj)
223
- );
224
- throw error;
225
- });
226
- }
227
-
228
- // In the case of the "schema builder" we call `queryArray`, which runs each
229
- // of the queries in sequence.
230
- async queryArray(queries) {
231
- if (queries.length === 1) {
232
- const query = queries[0];
233
-
234
- if (!query.statementsProducer) {
235
- return this.query(query);
236
- }
237
-
238
- const statements = await query.statementsProducer(
239
- undefined,
240
- this.connection
241
- );
242
-
243
- const sqlQueryObjects = statements.sql.map((statement) => ({
244
- sql: statement,
245
- bindings: query.bindings,
246
- }));
247
- const preQueryObjects = statements.pre.map((statement) => ({
248
- sql: statement,
249
- bindings: query.bindings,
250
- }));
251
- const postQueryObjects = statements.post.map((statement) => ({
252
- sql: statement,
253
- bindings: query.bindings,
254
- }));
255
-
256
- let results = [];
257
-
258
- await this.queryArray(preQueryObjects);
259
-
260
- try {
261
- await this.client.transaction(
262
- async (trx) => {
263
- const transactionRunner = new Runner(trx.client, this.builder);
264
- transactionRunner.connection = this.connection;
265
-
266
- results = await transactionRunner.queryArray(sqlQueryObjects);
267
-
268
- if (statements.check) {
269
- const foreignViolations = await trx.raw(statements.check);
270
-
271
- if (foreignViolations.length > 0) {
272
- throw new Error('FOREIGN KEY constraint failed');
273
- }
274
- }
275
- },
276
- { connection: this.connection }
277
- );
278
- } finally {
279
- await this.queryArray(postQueryObjects);
280
- }
281
-
282
- return results;
283
- }
284
-
285
- const results = [];
286
- for (const query of queries) {
287
- results.push(await this.queryArray([query]));
288
- }
289
- return results;
290
- }
291
-
292
- // Check whether there's a transaction flag, and that it has a connection.
293
- async ensureConnection(cb, cbParams) {
294
- // Use override from a builder if passed
295
- if (this.builder._connection) {
296
- this.connection = this.builder._connection;
297
- }
298
-
299
- if (this.connection) {
300
- return cb(this, cbParams);
301
- }
302
-
303
- let acquiredConnection;
304
- try {
305
- acquiredConnection = await this.client.acquireConnection();
306
- } catch (error) {
307
- if (!(error instanceof KnexTimeoutError)) {
308
- return Promise.reject(error);
309
- }
310
- if (this.builder) {
311
- error.sql = this.builder.sql;
312
- error.bindings = this.builder.bindings;
313
- }
314
- throw error;
315
- }
316
- try {
317
- this.connection = acquiredConnection;
318
- return await cb(this, cbParams);
319
- } finally {
320
- await this.client.releaseConnection(acquiredConnection);
321
- }
322
- }
323
- }
324
-
325
- module.exports = Runner;
1
+ const { KnexTimeoutError } = require('../util/timeout');
2
+ const { timeout } = require('../util/timeout');
3
+ const {
4
+ ensureConnectionCallback,
5
+ ensureConnectionStreamCallback,
6
+ } = require('./internal/ensure-connection-callback');
7
+
8
+ let Transform;
9
+
10
+ // The "Runner" constructor takes a "builder" (query, schema, or raw)
11
+ // and runs through each of the query statements, calling any additional
12
+ // "output" method provided alongside the query and bindings.
13
+ class Runner {
14
+ constructor(client, builder) {
15
+ this.client = client;
16
+ this.builder = builder;
17
+ this.queries = [];
18
+
19
+ // The "connection" object is set on the runner when
20
+ // "run" is called.
21
+ this.connection = undefined;
22
+ }
23
+
24
+ // "Run" the target, calling "toSQL" on the builder, returning
25
+ // an object or array of queries to run, each of which are run on
26
+ // a single connection.
27
+ async run() {
28
+ const runner = this;
29
+ try {
30
+ const res = await this.ensureConnection(ensureConnectionCallback);
31
+
32
+ // Fire a single "end" event on the builder when
33
+ // all queries have successfully completed.
34
+ runner.builder.emit('end');
35
+ return res;
36
+
37
+ // If there are any "error" listeners, we fire an error event
38
+ // and then re-throw the error to be eventually handled by
39
+ // the promise chain. Useful if you're wrapping in a custom `Promise`.
40
+ } catch (err) {
41
+ if (runner.builder._events && runner.builder._events.error) {
42
+ runner.builder.emit('error', err);
43
+ }
44
+ throw err;
45
+ }
46
+ }
47
+
48
+ // Stream the result set, by passing through to the dialect's streaming
49
+ // capabilities. If the options are
50
+ stream(optionsOrHandler, handlerOrNil) {
51
+ const firstOptionIsHandler =
52
+ typeof optionsOrHandler === 'function' && arguments.length === 1;
53
+
54
+ const options = firstOptionIsHandler ? {} : optionsOrHandler;
55
+ const handler = firstOptionIsHandler ? optionsOrHandler : handlerOrNil;
56
+
57
+ // Determines whether we emit an error or throw here.
58
+ const hasHandler = typeof handler === 'function';
59
+
60
+ // Lazy-load the "Transform" dependency.
61
+ Transform = Transform || require('stream').Transform;
62
+
63
+ const queryContext = this.builder.queryContext();
64
+
65
+ const stream = new Transform({
66
+ objectMode: true,
67
+ transform: (chunk, _, callback) => {
68
+ callback(null, this.client.postProcessResponse(chunk, queryContext));
69
+ },
70
+ });
71
+ stream.on('close', () => {
72
+ this.client.releaseConnection(this.connection);
73
+ });
74
+
75
+ // If the stream is manually destroyed, the close event is not
76
+ // propagated to the top of the pipe chain. We need to manually verify
77
+ // that the source stream is closed and if not, manually destroy it.
78
+ stream.on('pipe', (sourceStream) => {
79
+ const cleanSourceStream = () => {
80
+ if (!sourceStream.closed) {
81
+ sourceStream.destroy();
82
+ }
83
+ };
84
+
85
+ // Stream already closed, cleanup immediately
86
+ if (stream.closed) {
87
+ cleanSourceStream();
88
+ } else {
89
+ stream.on('close', cleanSourceStream);
90
+ }
91
+ });
92
+
93
+ const connectionAcquirePromise = this.ensureConnection(
94
+ ensureConnectionStreamCallback,
95
+ {
96
+ options,
97
+ hasHandler,
98
+ stream,
99
+ }
100
+ )
101
+ // Emit errors on the stream if the error occurred before a connection
102
+ // could be acquired.
103
+ // If the connection was acquired, assume the error occurred in the client
104
+ // code and has already been emitted on the stream. Don't emit it twice.
105
+ .catch((err) => {
106
+ if (!this.connection) {
107
+ stream.emit('error', err);
108
+ }
109
+ });
110
+
111
+ // If a function is passed to handle the stream, send the stream
112
+ // there and return the promise, otherwise just return the stream
113
+ // and the promise will take care of itself.
114
+ if (hasHandler) {
115
+ handler(stream);
116
+ return connectionAcquirePromise;
117
+ }
118
+ return stream;
119
+ }
120
+
121
+ // Allow you to pipe the stream to a writable stream.
122
+ pipe(writable, options) {
123
+ return this.stream(options).pipe(writable);
124
+ }
125
+
126
+ // "Runs" a query, returning a promise. All queries specified by the builder are guaranteed
127
+ // to run in sequence, and on the same connection, especially helpful when schema building
128
+ // and dealing with foreign key constraints, etc.
129
+ async query(obj) {
130
+ const { __knexUid, __knexTxId } = this.connection;
131
+
132
+ this.builder.emit('query', Object.assign({ __knexUid, __knexTxId }, obj));
133
+
134
+ const runner = this;
135
+ const queryContext = this.builder.queryContext();
136
+ // query-error events are emitted before the queryPromise continuations.
137
+ // pass queryContext into client.query so it can be raised properly.
138
+ if (obj !== null && typeof obj === 'object') {
139
+ obj.queryContext = queryContext;
140
+ }
141
+ let queryPromise = this.client.query(this.connection, obj);
142
+
143
+ if (obj.timeout) {
144
+ queryPromise = timeout(queryPromise, obj.timeout);
145
+ }
146
+
147
+ // Await the return value of client.processResponse; in the case of sqlite3's
148
+ // dropColumn()/renameColumn(), it will be a Promise for the transaction
149
+ // containing the complete rename procedure.
150
+ return queryPromise
151
+ .then((resp) => this.client.processResponse(resp, runner))
152
+ .then((processedResponse) => {
153
+ const postProcessedResponse = this.client.postProcessResponse(
154
+ processedResponse,
155
+ queryContext
156
+ );
157
+
158
+ this.builder.emit(
159
+ 'query-response',
160
+ postProcessedResponse,
161
+ Object.assign({ __knexUid, __knexTxId }, obj),
162
+ this.builder
163
+ );
164
+
165
+ this.client.emit(
166
+ 'query-response',
167
+ postProcessedResponse,
168
+ Object.assign({ __knexUid, __knexTxId }, obj),
169
+ this.builder
170
+ );
171
+
172
+ return postProcessedResponse;
173
+ })
174
+ .catch((error) => {
175
+ if (!(error instanceof KnexTimeoutError)) {
176
+ return Promise.reject(error);
177
+ }
178
+ const { timeout, sql, bindings } = obj;
179
+
180
+ let cancelQuery;
181
+ if (obj.cancelOnTimeout) {
182
+ cancelQuery = this.client.cancelQuery(this.connection);
183
+ } else {
184
+ // If we don't cancel the query, we need to mark the connection as disposed so that
185
+ // it gets destroyed by the pool and is never used again. If we don't do this and
186
+ // return the connection to the pool, it will be useless until the current operation
187
+ // that timed out, finally finishes.
188
+ this.connection.__knex__disposed = error;
189
+ cancelQuery = Promise.resolve();
190
+ }
191
+
192
+ return cancelQuery
193
+ .catch((cancelError) => {
194
+ // If the cancellation failed, we need to mark the connection as disposed so that
195
+ // it gets destroyed by the pool and is never used again. If we don't do this and
196
+ // return the connection to the pool, it will be useless until the current operation
197
+ // that timed out, finally finishes.
198
+ this.connection.__knex__disposed = error;
199
+
200
+ // cancellation failed
201
+ throw Object.assign(cancelError, {
202
+ message: `After query timeout of ${timeout}ms exceeded, cancelling of query failed.`,
203
+ sql,
204
+ bindings,
205
+ timeout,
206
+ });
207
+ })
208
+ .then(() => {
209
+ // cancellation succeeded, rethrow timeout error
210
+ throw Object.assign(error, {
211
+ message: `Defined query timeout of ${timeout}ms exceeded when running query.`,
212
+ sql,
213
+ bindings,
214
+ timeout,
215
+ });
216
+ });
217
+ })
218
+ .catch((error) => {
219
+ this.builder.emit(
220
+ 'query-error',
221
+ error,
222
+ Object.assign({ __knexUid, __knexTxId, queryContext }, obj)
223
+ );
224
+ throw error;
225
+ });
226
+ }
227
+
228
+ // In the case of the "schema builder" we call `queryArray`, which runs each
229
+ // of the queries in sequence.
230
+ async queryArray(queries) {
231
+ if (queries.length === 1) {
232
+ const query = queries[0];
233
+
234
+ if (!query.statementsProducer) {
235
+ return this.query(query);
236
+ }
237
+
238
+ const statements = await query.statementsProducer(
239
+ undefined,
240
+ this.connection
241
+ );
242
+
243
+ const sqlQueryObjects = statements.sql.map((statement) => ({
244
+ sql: statement,
245
+ bindings: query.bindings,
246
+ }));
247
+ const preQueryObjects = statements.pre.map((statement) => ({
248
+ sql: statement,
249
+ bindings: query.bindings,
250
+ }));
251
+ const postQueryObjects = statements.post.map((statement) => ({
252
+ sql: statement,
253
+ bindings: query.bindings,
254
+ }));
255
+
256
+ let results = [];
257
+
258
+ await this.queryArray(preQueryObjects);
259
+
260
+ try {
261
+ await this.client.transaction(
262
+ async (trx) => {
263
+ const transactionRunner = new Runner(trx.client, this.builder);
264
+ transactionRunner.connection = this.connection;
265
+
266
+ results = await transactionRunner.queryArray(sqlQueryObjects);
267
+
268
+ if (statements.check) {
269
+ const foreignViolations = await trx.raw(statements.check);
270
+
271
+ if (foreignViolations.length > 0) {
272
+ throw new Error('FOREIGN KEY constraint failed');
273
+ }
274
+ }
275
+ },
276
+ { connection: this.connection }
277
+ );
278
+ } finally {
279
+ await this.queryArray(postQueryObjects);
280
+ }
281
+
282
+ return results;
283
+ }
284
+
285
+ const results = [];
286
+ for (const query of queries) {
287
+ results.push(await this.queryArray([query]));
288
+ }
289
+ return results;
290
+ }
291
+
292
+ // Check whether there's a transaction flag, and that it has a connection.
293
+ async ensureConnection(cb, cbParams) {
294
+ // Use override from a builder if passed
295
+ if (this.builder._connection) {
296
+ this.connection = this.builder._connection;
297
+ }
298
+
299
+ if (this.connection) {
300
+ return cb(this, cbParams);
301
+ }
302
+
303
+ let acquiredConnection;
304
+ try {
305
+ acquiredConnection = await this.client.acquireConnection();
306
+ } catch (error) {
307
+ if (!(error instanceof KnexTimeoutError)) {
308
+ return Promise.reject(error);
309
+ }
310
+ if (this.builder) {
311
+ error.sql = this.builder.sql;
312
+ error.bindings = this.builder.bindings;
313
+ }
314
+ throw error;
315
+ }
316
+ try {
317
+ this.connection = acquiredConnection;
318
+ return await cb(this, cbParams);
319
+ } finally {
320
+ await this.client.releaseConnection(acquiredConnection);
321
+ }
322
+ }
323
+ }
324
+
325
+ module.exports = Runner;