knex 2.3.0 → 2.4.1

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