knex 0.20.9 → 0.20.10
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.
- package/CHANGELOG.md +17 -0
- package/bin/cli.js +15 -14
- package/lib/client.js +10 -5
- package/lib/dialects/mysql/index.js +11 -21
- package/lib/dialects/oracledb/index.js +11 -14
- package/lib/dialects/oracledb/transaction.js +18 -15
- package/lib/knex.js +4 -0
- package/lib/runner.js +11 -3
- package/lib/transaction.js +17 -9
- package/lib/util/timeout.js +20 -0
- package/package.json +4 -4
- package/types/index.d.ts +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Master (Unreleased)
|
|
2
2
|
|
|
3
|
+
# 0.20.10 - 13 February, 2020
|
|
4
|
+
|
|
5
|
+
### Bug fixes:
|
|
6
|
+
|
|
7
|
+
- Oracle: commit was a no-op causing race conditions #3668
|
|
8
|
+
- CLI: Knex calls process.chdir() before opening Knexfile #3661
|
|
9
|
+
- Fixed unresolved promise in cancelQuery() #3666
|
|
10
|
+
|
|
11
|
+
### Typings:
|
|
12
|
+
|
|
13
|
+
- `fn.now` takes optionally a precision argument. #3662
|
|
14
|
+
- PG: Include SSL in connection definition #3659
|
|
15
|
+
|
|
16
|
+
### Test / internal changes:
|
|
17
|
+
|
|
18
|
+
- replace Bluebird.timeout #3634
|
|
19
|
+
|
|
3
20
|
# 0.20.9 - 08 February, 2020
|
|
4
21
|
|
|
5
22
|
### Bug fixes:
|
package/bin/cli.js
CHANGED
|
@@ -28,26 +28,18 @@ const fsPromised = {
|
|
|
28
28
|
writeFile: promisify(fs.writeFile),
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
// enable esm interop via 'esm' module
|
|
34
|
-
require = require('esm')(module);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
env.configuration = env.configPath
|
|
38
|
-
? require(env.configPath)
|
|
39
|
-
: mkConfigObj(opts);
|
|
31
|
+
function openKnexfile(configPath) {
|
|
32
|
+
const config = require(configPath);
|
|
40
33
|
|
|
41
34
|
// FYI: By default, the extension for the migration files is inferred
|
|
42
35
|
// from the knexfile's extension. So, the following lines are in
|
|
43
36
|
// place for backwards compatibility purposes.
|
|
44
|
-
|
|
45
|
-
const p = env.configPath || opts.knexpath;
|
|
37
|
+
config.ext = config.ext || path.extname(configPath).replace('.', '');
|
|
46
38
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
39
|
+
return config;
|
|
40
|
+
}
|
|
50
41
|
|
|
42
|
+
function initKnex(env, opts) {
|
|
51
43
|
checkLocalModule(env);
|
|
52
44
|
if (process.cwd() !== env.cwd) {
|
|
53
45
|
process.chdir(env.cwd);
|
|
@@ -57,6 +49,15 @@ function initKnex(env, opts) {
|
|
|
57
49
|
);
|
|
58
50
|
}
|
|
59
51
|
|
|
52
|
+
if (opts.esm) {
|
|
53
|
+
// enable esm interop via 'esm' module
|
|
54
|
+
require = require('esm')(module);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
env.configuration = env.configPath
|
|
58
|
+
? openKnexfile(env.configPath)
|
|
59
|
+
: mkConfigObj(opts);
|
|
60
|
+
|
|
60
61
|
const resolvedConfig = resolveEnvironmentConfig(opts, env.configuration);
|
|
61
62
|
const knex = require(env.modulePath);
|
|
62
63
|
return knex(resolvedConfig);
|
package/lib/client.js
CHANGED
|
@@ -25,6 +25,7 @@ const { makeEscape } = require('./query/string');
|
|
|
25
25
|
const { uniqueId, cloneDeep, defaults } = require('lodash');
|
|
26
26
|
|
|
27
27
|
const Logger = require('./logger');
|
|
28
|
+
const { KnexTimeoutError } = require('./util/timeout');
|
|
28
29
|
|
|
29
30
|
const debug = require('debug')('knex:client');
|
|
30
31
|
const _debugQuery = require('debug')('knex:query');
|
|
@@ -344,11 +345,15 @@ Object.assign(Client.prototype, {
|
|
|
344
345
|
debug('acquired connection from pool: %s', connection.__knexUid);
|
|
345
346
|
return connection;
|
|
346
347
|
})
|
|
347
|
-
.catch(
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
348
|
+
.catch((error) => {
|
|
349
|
+
let convertedError = error;
|
|
350
|
+
if (error instanceof TimeoutError) {
|
|
351
|
+
convertedError = new KnexTimeoutError(
|
|
352
|
+
'Knex: Timeout acquiring a connection. The pool is probably full. ' +
|
|
353
|
+
'Are you missing a .transacting(trx) call?'
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
throw convertedError;
|
|
352
357
|
});
|
|
353
358
|
} catch (e) {
|
|
354
359
|
return Bluebird.reject(e);
|
|
@@ -170,28 +170,18 @@ Object.assign(Client_MySQL.prototype, {
|
|
|
170
170
|
|
|
171
171
|
canCancelQuery: true,
|
|
172
172
|
|
|
173
|
-
cancelQuery(connectionToKill) {
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
.timeout(100)
|
|
182
|
-
.then((conn) =>
|
|
183
|
-
this.query(conn, {
|
|
184
|
-
method: 'raw',
|
|
185
|
-
sql: 'KILL QUERY ?',
|
|
186
|
-
bindings: [connectionToKill.threadId],
|
|
187
|
-
options: {},
|
|
188
|
-
})
|
|
189
|
-
)
|
|
190
|
-
.finally(() => {
|
|
191
|
-
// NOT returning this promise because we want to release the connection
|
|
192
|
-
// in a non-blocking fashion
|
|
193
|
-
acquiringConn.then((conn) => this.releaseConnection(conn));
|
|
173
|
+
async cancelQuery(connectionToKill) {
|
|
174
|
+
const conn = await this.acquireConnection();
|
|
175
|
+
try {
|
|
176
|
+
return await this.query(conn, {
|
|
177
|
+
method: 'raw',
|
|
178
|
+
sql: 'KILL QUERY ?',
|
|
179
|
+
bindings: [connectionToKill.threadId],
|
|
180
|
+
options: {},
|
|
194
181
|
});
|
|
182
|
+
} finally {
|
|
183
|
+
await this.releaseConnection(conn);
|
|
184
|
+
}
|
|
195
185
|
},
|
|
196
186
|
});
|
|
197
187
|
|
|
@@ -108,9 +108,6 @@ Client_Oracledb.prototype.acquireRawConnection = function() {
|
|
|
108
108
|
}
|
|
109
109
|
connection.commitAsync = function() {
|
|
110
110
|
return new Bluebird((commitResolve, commitReject) => {
|
|
111
|
-
if (connection.isTransaction) {
|
|
112
|
-
return commitResolve();
|
|
113
|
-
}
|
|
114
111
|
this.commit(function(err) {
|
|
115
112
|
if (err) {
|
|
116
113
|
return commitReject(err);
|
|
@@ -293,7 +290,9 @@ Client_Oracledb.prototype._query = function(connection, obj) {
|
|
|
293
290
|
}
|
|
294
291
|
|
|
295
292
|
if (!obj.returning && outBinds.length === 0) {
|
|
296
|
-
|
|
293
|
+
if (!connection.isTransaction) {
|
|
294
|
+
await connection.commitAsync();
|
|
295
|
+
}
|
|
297
296
|
return obj;
|
|
298
297
|
}
|
|
299
298
|
const rowIds = [];
|
|
@@ -335,17 +334,15 @@ Client_Oracledb.prototype._query = function(connection, obj) {
|
|
|
335
334
|
});
|
|
336
335
|
}
|
|
337
336
|
}
|
|
338
|
-
|
|
339
|
-
if (obj.returningSql) {
|
|
340
|
-
return connection
|
|
341
|
-
.executeAsync(obj.returningSql(), rowIds, { resultSet: true })
|
|
342
|
-
.then(function(response) {
|
|
343
|
-
obj.response = response.rows;
|
|
344
|
-
return obj;
|
|
345
|
-
});
|
|
346
|
-
}
|
|
337
|
+
if (connection.isTransaction) {
|
|
347
338
|
return obj;
|
|
348
|
-
}
|
|
339
|
+
}
|
|
340
|
+
await connection.commitAsync();
|
|
341
|
+
if (obj.returningSql) {
|
|
342
|
+
const response = await connection.executeAsync(obj.returningSql(), rowIds, { resultSet: true })
|
|
343
|
+
obj.response = response.rows;
|
|
344
|
+
}
|
|
345
|
+
return obj;
|
|
349
346
|
});
|
|
350
347
|
};
|
|
351
348
|
|
|
@@ -2,6 +2,7 @@ const { isUndefined } = require('lodash');
|
|
|
2
2
|
|
|
3
3
|
const Bluebird = require('bluebird');
|
|
4
4
|
const Transaction = require('../../transaction');
|
|
5
|
+
const { timeout, KnexTimeoutError } = require('../../util/timeout');
|
|
5
6
|
const debugTx = require('debug')('knex:tx');
|
|
6
7
|
|
|
7
8
|
module.exports = class Oracle_Transaction extends Transaction {
|
|
@@ -10,12 +11,14 @@ module.exports = class Oracle_Transaction extends Transaction {
|
|
|
10
11
|
return Bluebird.resolve();
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
commit(conn, value) {
|
|
14
|
+
async commit(conn, value) {
|
|
14
15
|
this._completed = true;
|
|
15
|
-
|
|
16
|
-
.commitAsync()
|
|
17
|
-
.
|
|
18
|
-
|
|
16
|
+
try {
|
|
17
|
+
await conn.commitAsync();
|
|
18
|
+
this._resolver(value);
|
|
19
|
+
} catch (err) {
|
|
20
|
+
this._rejecter(err);
|
|
21
|
+
}
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
release(conn, value) {
|
|
@@ -23,24 +26,24 @@ module.exports = class Oracle_Transaction extends Transaction {
|
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
rollback(conn, err) {
|
|
26
|
-
const self = this;
|
|
27
29
|
this._completed = true;
|
|
28
30
|
debugTx('%s: rolling back', this.txid);
|
|
29
|
-
return conn
|
|
30
|
-
.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
return timeout(conn.rollbackAsync(), 5000)
|
|
32
|
+
.catch((e) => {
|
|
33
|
+
if (!(e instanceof KnexTimeoutError)) {
|
|
34
|
+
return Promise.reject(e);
|
|
35
|
+
}
|
|
36
|
+
this._rejecter(e);
|
|
34
37
|
})
|
|
35
|
-
.then(
|
|
38
|
+
.then(() => {
|
|
36
39
|
if (isUndefined(err)) {
|
|
37
|
-
if (
|
|
38
|
-
|
|
40
|
+
if (this.doNotRejectOnRollback) {
|
|
41
|
+
this._resolver();
|
|
39
42
|
return;
|
|
40
43
|
}
|
|
41
44
|
err = new Error(`Transaction rejected with non-error: ${err}`);
|
|
42
45
|
}
|
|
43
|
-
|
|
46
|
+
this._rejecter(err);
|
|
44
47
|
});
|
|
45
48
|
}
|
|
46
49
|
|
package/lib/knex.js
CHANGED
|
@@ -5,6 +5,7 @@ const QueryInterface = require('./query/methods');
|
|
|
5
5
|
|
|
6
6
|
const makeKnex = require('./util/make-knex');
|
|
7
7
|
const parseConnection = require('./util/parse-connection');
|
|
8
|
+
const { KnexTimeoutError } = require('./util/timeout');
|
|
8
9
|
const fakeClient = require('./util/fake-client');
|
|
9
10
|
const { SUPPORTED_CLIENTS } = require('./constants');
|
|
10
11
|
const { resolveClientNameWithAliases } = require('./helpers');
|
|
@@ -58,6 +59,9 @@ function Knex(config) {
|
|
|
58
59
|
|
|
59
60
|
// Expose Client on the main Knex namespace.
|
|
60
61
|
Knex.Client = Client;
|
|
62
|
+
|
|
63
|
+
Knex.KnexTimeoutError = KnexTimeoutError;
|
|
64
|
+
|
|
61
65
|
Knex.QueryBuilder = {
|
|
62
66
|
extend: function(methodName, fn) {
|
|
63
67
|
QueryBuilder.extend(methodName, fn);
|
package/lib/runner.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
const Bluebird = require('bluebird');
|
|
2
|
+
const { KnexTimeoutError } = require('./util/timeout');
|
|
3
|
+
const { timeout } = require('./util/timeout');
|
|
2
4
|
|
|
3
5
|
let PassThrough;
|
|
4
6
|
|
|
@@ -133,7 +135,7 @@ Object.assign(Runner.prototype, {
|
|
|
133
135
|
let queryPromise = this.client.query(this.connection, obj);
|
|
134
136
|
|
|
135
137
|
if (obj.timeout) {
|
|
136
|
-
queryPromise =
|
|
138
|
+
queryPromise = timeout(queryPromise, obj.timeout);
|
|
137
139
|
}
|
|
138
140
|
|
|
139
141
|
// Await the return value of client.processResponse; in the case of sqlite3's
|
|
@@ -164,7 +166,10 @@ Object.assign(Runner.prototype, {
|
|
|
164
166
|
|
|
165
167
|
return postProcessedResponse;
|
|
166
168
|
})
|
|
167
|
-
.catch(
|
|
169
|
+
.catch((error) => {
|
|
170
|
+
if (!(error instanceof KnexTimeoutError)) {
|
|
171
|
+
return Promise.reject(error);
|
|
172
|
+
}
|
|
168
173
|
const { timeout, sql, bindings } = obj;
|
|
169
174
|
|
|
170
175
|
let cancelQuery;
|
|
@@ -241,7 +246,10 @@ Object.assign(Runner.prototype, {
|
|
|
241
246
|
}
|
|
242
247
|
return this.client
|
|
243
248
|
.acquireConnection()
|
|
244
|
-
.catch(
|
|
249
|
+
.catch((error) => {
|
|
250
|
+
if (!(error instanceof KnexTimeoutError)) {
|
|
251
|
+
return Promise.reject(error);
|
|
252
|
+
}
|
|
245
253
|
if (this.builder) {
|
|
246
254
|
error.sql = this.builder.sql;
|
|
247
255
|
error.bindings = this.builder.bindings;
|
package/lib/transaction.js
CHANGED
|
@@ -5,6 +5,7 @@ const { EventEmitter } = require('events');
|
|
|
5
5
|
const Debug = require('debug');
|
|
6
6
|
|
|
7
7
|
const makeKnex = require('./util/make-knex');
|
|
8
|
+
const { timeout, KnexTimeoutError } = require('./util/timeout');
|
|
8
9
|
|
|
9
10
|
const debug = Debug('knex:tx');
|
|
10
11
|
|
|
@@ -150,19 +151,26 @@ class Transaction extends EventEmitter {
|
|
|
150
151
|
}
|
|
151
152
|
|
|
152
153
|
rollback(conn, error) {
|
|
153
|
-
return this.query(conn, 'ROLLBACK', 2, error)
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
return timeout(this.query(conn, 'ROLLBACK', 2, error), 5000).catch(
|
|
155
|
+
(err) => {
|
|
156
|
+
if (!(err instanceof KnexTimeoutError)) {
|
|
157
|
+
return Promise.reject(err);
|
|
158
|
+
}
|
|
156
159
|
this._rejecter(error);
|
|
157
|
-
}
|
|
160
|
+
}
|
|
161
|
+
);
|
|
158
162
|
}
|
|
159
163
|
|
|
160
164
|
rollbackTo(conn, error) {
|
|
161
|
-
return
|
|
162
|
-
.
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
return timeout(
|
|
166
|
+
this.query(conn, `ROLLBACK TO SAVEPOINT ${this.txid}`, 2, error),
|
|
167
|
+
5000
|
|
168
|
+
).catch((err) => {
|
|
169
|
+
if (!(err instanceof KnexTimeoutError)) {
|
|
170
|
+
return Promise.reject(err);
|
|
171
|
+
}
|
|
172
|
+
this._rejecter(error);
|
|
173
|
+
});
|
|
166
174
|
}
|
|
167
175
|
|
|
168
176
|
query(conn, sql, status, value) {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const Bluebird = require('bluebird');
|
|
2
|
+
const delay = require('./delay');
|
|
3
|
+
|
|
4
|
+
class KnexTimeoutError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'KnexTimeoutError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
module.exports.KnexTimeoutError = KnexTimeoutError;
|
|
12
|
+
module.exports.timeout = (promise, ms) =>
|
|
13
|
+
Bluebird.resolve(
|
|
14
|
+
Promise.race([
|
|
15
|
+
promise,
|
|
16
|
+
delay(ms).then(() =>
|
|
17
|
+
Promise.reject(new KnexTimeoutError('operation timed out'))
|
|
18
|
+
),
|
|
19
|
+
])
|
|
20
|
+
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knex",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.10",
|
|
4
4
|
"description": "A batteries-included SQL query & schema builder for Postgres, MySQL and SQLite3 and the Browser",
|
|
5
5
|
"main": "knex.js",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
]
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
|
-
"@types/node": "^10.17.
|
|
79
|
+
"@types/node": "^10.17.15",
|
|
80
80
|
"JSONStream": "^1.3.5",
|
|
81
81
|
"chai": "^4.2.0",
|
|
82
82
|
"chai-subset-in-order": "^2.1.3",
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"pg": "^7.18.1",
|
|
100
100
|
"pg-query-stream": "^2.1.2",
|
|
101
101
|
"prettier": "1.18.2",
|
|
102
|
-
"rimraf": "^3.0.
|
|
102
|
+
"rimraf": "^3.0.2",
|
|
103
103
|
"sinon": "^8.1.1",
|
|
104
104
|
"sinon-chai": "^3.4.0",
|
|
105
105
|
"source-map-support": "^0.5.16",
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"toxiproxy-node-client": "^2.0.6",
|
|
110
110
|
"ts-node": "^8.6.2",
|
|
111
111
|
"typescript": "3.7.4",
|
|
112
|
-
"webpack-cli": "^3.3.
|
|
112
|
+
"webpack-cli": "^3.3.1"
|
|
113
113
|
},
|
|
114
114
|
"buildDependencies": [
|
|
115
115
|
"rimraf"
|
package/types/index.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ import events = require('events');
|
|
|
13
13
|
import stream = require('stream');
|
|
14
14
|
import ResultTypes = require('./result');
|
|
15
15
|
|
|
16
|
+
import { ConnectionOptions } from "tls";
|
|
17
|
+
|
|
16
18
|
// # Generic type-level utilities
|
|
17
19
|
|
|
18
20
|
// If T is object then make it a partial otherwise fallback to any
|
|
@@ -1808,6 +1810,7 @@ declare namespace Knex {
|
|
|
1808
1810
|
statement_timeout?: false | number;
|
|
1809
1811
|
connectionTimeoutMillis?: number;
|
|
1810
1812
|
keepAliveInitialDelayMillis?: number;
|
|
1813
|
+
ssl?: boolean | ConnectionOptions;
|
|
1811
1814
|
}
|
|
1812
1815
|
|
|
1813
1816
|
type RedshiftConnectionConfig = PgConnectionConfig;
|
|
@@ -1912,7 +1915,7 @@ declare namespace Knex {
|
|
|
1912
1915
|
}
|
|
1913
1916
|
|
|
1914
1917
|
interface FunctionHelper {
|
|
1915
|
-
now(): Raw;
|
|
1918
|
+
now(precision?: number): Raw;
|
|
1916
1919
|
}
|
|
1917
1920
|
|
|
1918
1921
|
interface EnumOptions {
|
|
@@ -1990,6 +1993,8 @@ declare namespace Knex {
|
|
|
1990
1993
|
) => QueryBuilder<TRecord, TResult>
|
|
1991
1994
|
): void;
|
|
1992
1995
|
}
|
|
1996
|
+
|
|
1997
|
+
export class KnexTimeoutError extends Error {}
|
|
1993
1998
|
}
|
|
1994
1999
|
|
|
1995
2000
|
export = Knex;
|