knex 2.4.1 → 2.5.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.
- package/CHANGELOG.md +59 -17
- package/README.md +0 -1
- package/bin/cli.js +7 -6
- package/knex.mjs +11 -0
- package/lib/client.js +20 -0
- package/lib/dialects/better-sqlite3/index.js +6 -1
- package/lib/dialects/index.js +33 -33
- package/lib/dialects/mssql/index.js +5 -0
- package/lib/dialects/mssql/query/mssql-querycompiler.js +1 -0
- package/lib/dialects/mysql2/index.js +20 -0
- package/lib/dialects/oracle/query/oracle-querycompiler.js +1 -0
- package/lib/dialects/oracledb/index.js +5 -5
- package/lib/dialects/oracledb/schema/oracledb-columncompiler.js +10 -4
- package/lib/dialects/postgres/execution/pg-transaction.js +10 -3
- package/lib/dialects/postgres/index.js +8 -8
- package/lib/dialects/postgres/query/pg-querybuilder.js +5 -0
- package/lib/dialects/postgres/query/pg-querycompiler.js +6 -1
- package/lib/dialects/postgres/schema/pg-compiler.js +3 -1
- package/lib/dialects/postgres/schema/pg-tablecompiler.js +9 -4
- package/lib/dialects/redshift/transaction.js +10 -3
- package/lib/dialects/sqlite3/execution/sqlite-transaction.js +7 -0
- package/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js +1 -1
- package/lib/execution/runner.js +18 -0
- package/lib/execution/transaction.js +15 -7
- package/lib/knex-builder/FunctionHelper.js +26 -0
- package/lib/knex-builder/Knex.js +1 -1
- package/lib/knex-builder/make-knex.js +5 -0
- package/lib/migrations/migrate/MigrationGenerator.js +3 -1
- package/lib/query/method-constants.js +1 -0
- package/lib/query/querybuilder.js +24 -25
- package/lib/query/querycompiler.js +11 -0
- package/lib/schema/builder.js +3 -2
- package/lib/schema/columnbuilder.js +3 -2
- package/lib/schema/tablebuilder.js +3 -2
- package/lib/schema/viewbuilder.js +0 -1
- package/lib/util/security.js +26 -0
- package/package.json +16 -12
- package/scripts/clean.js +18 -16
- package/scripts/update_gitignore_for_tsc_output.js +36 -32
- package/types/index.d.ts +51 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,54 @@
|
|
|
1
1
|
# Master (Unreleased)
|
|
2
2
|
|
|
3
|
-
# 2.
|
|
3
|
+
# 2.5.0 - 08 July, 2023
|
|
4
|
+
|
|
5
|
+
### New features
|
|
6
|
+
|
|
7
|
+
- Add uuid helper function #5617
|
|
8
|
+
- Add `nativeBindings` option to `better-sqlite3` options #5461
|
|
9
|
+
- Add QueryBuilder#updateFrom #5386
|
|
10
|
+
- Add readonly transaction access mode #5445
|
|
11
|
+
- Add readonly option to Better-SQLite3 #5530
|
|
12
|
+
- Add EXCEPT as a valid keyword #5357
|
|
13
|
+
- Add ability to prepend query comments #5289
|
|
14
|
+
- Add fetchAsString option #5484
|
|
15
|
+
|
|
16
|
+
### Bug fixes
|
|
17
|
+
|
|
18
|
+
- Avoid password leaks on query logs #5559
|
|
19
|
+
- Add knex.mjs to files in package.json #5518
|
|
20
|
+
- Handle numeric array elements in .orderBy() #5551
|
|
21
|
+
- Attach error handler early enough #5552
|
|
22
|
+
- Fix Returning * in Oracle #5598
|
|
23
|
+
- Fix indexType option in `Postgres` #5601
|
|
24
|
+
- Add mjs extension type #5616
|
|
25
|
+
- Use implicit check on json fields for OracleDB #5478
|
|
26
|
+
- Fix when manually close source stream #5466
|
|
27
|
+
- Fix case sensitive issue with get table #5509
|
|
28
|
+
|
|
29
|
+
### Typings
|
|
30
|
+
|
|
31
|
+
- Add Object syntax overload to increment method #5512
|
|
32
|
+
- Add object syntax overload to decrement method #5555
|
|
33
|
+
- Fix typing for toSql #5594
|
|
34
|
+
- Add ResolveTableType for `.merge()` #5605
|
|
35
|
+
- Add missing types for havingNull and havingNotNull #5529
|
|
36
|
+
- Add collate to the columnbuilder interface #5568
|
|
37
|
+
- TableBuilder methods return the SchemaBuilder. #5486
|
|
38
|
+
|
|
39
|
+
# 2.4.2 - 22 January, 2023
|
|
40
|
+
|
|
41
|
+
### Bug fixes
|
|
42
|
+
|
|
43
|
+
- CLI: Fix incorrent EOL causing errors on Linux #5455
|
|
44
|
+
|
|
45
|
+
# 2.4.1 - 18 January, 2023
|
|
4
46
|
|
|
5
47
|
### Bug fixes
|
|
6
48
|
|
|
7
49
|
- PostgreSQL: Fix Malformed array literal 2.4.0 Regression #5439
|
|
8
50
|
|
|
9
|
-
# 2.4.0 - 06 January,
|
|
51
|
+
# 2.4.0 - 06 January, 2023
|
|
10
52
|
|
|
11
53
|
### New features:
|
|
12
54
|
|
|
@@ -1361,7 +1403,7 @@ Note: there are many breaking changes in this version, particularly in TypeScrip
|
|
|
1361
1403
|
|
|
1362
1404
|
### New features:
|
|
1363
1405
|
|
|
1364
|
-
- Support passing explicit connection to query builder
|
|
1406
|
+
- Support passing explicit connection to query builder #2817
|
|
1365
1407
|
- Introduced abstraction for getting migrations to make migration bundling easier #2775
|
|
1366
1408
|
- Allow timestamp with timezone on mssql databases #2724
|
|
1367
1409
|
- Allow specifying multiple migration directories #2735
|
|
@@ -1418,7 +1460,7 @@ Note: there are many breaking changes in this version, particularly in TypeScrip
|
|
|
1418
1460
|
|
|
1419
1461
|
### Changes:
|
|
1420
1462
|
|
|
1421
|
-
- THIS RELEASE WAS UNPUBLISHED FROM NPM BECAUSE IT HAD BROKEN MIGRATIONS USING `postprocessResponse` FEATURE
|
|
1463
|
+
- THIS RELEASE WAS UNPUBLISHED FROM NPM BECAUSE IT HAD BROKEN MIGRATIONS USING `postprocessResponse` FEATURE #2644
|
|
1422
1464
|
|
|
1423
1465
|
# 0.15.2 - 19 Jul, 2018
|
|
1424
1466
|
|
|
@@ -1479,7 +1521,7 @@ Note: there are many breaking changes in this version, particularly in TypeScrip
|
|
|
1479
1521
|
|
|
1480
1522
|
### Bug fixes:
|
|
1481
1523
|
|
|
1482
|
-
- Restored functionality of query event #2566
|
|
1524
|
+
- Restored functionality of query event #2566 #2549
|
|
1483
1525
|
|
|
1484
1526
|
# 0.14.5 - 8 Apr, 2018
|
|
1485
1527
|
|
|
@@ -1507,23 +1549,23 @@ Note: there are many breaking changes in this version, particularly in TypeScrip
|
|
|
1507
1549
|
|
|
1508
1550
|
### Bug fixes:
|
|
1509
1551
|
|
|
1510
|
-
- containsUndefined only validate plain objects. Fixes #1898
|
|
1511
|
-
- Add warning when using .returning() in sqlite3. Fixes #1660
|
|
1512
|
-
- Throw an error if .update() results in an empty sql
|
|
1513
|
-
- Removed unnecessary createTableIfNotExist and replaced with createTable
|
|
1552
|
+
- containsUndefined only validate plain objects. Fixes #1898 #2468
|
|
1553
|
+
- Add warning when using .returning() in sqlite3. Fixes #1660 #2471
|
|
1554
|
+
- Throw an error if .update() results in an empty sql #2472
|
|
1555
|
+
- Removed unnecessary createTableIfNotExist and replaced with createTable #2473
|
|
1514
1556
|
|
|
1515
1557
|
### New Features:
|
|
1516
1558
|
|
|
1517
|
-
- Allow calling lock procedures (such as forUpdate) outside of transaction. Fixes #2403.
|
|
1518
|
-
- Added test and documentation for Event 'start'
|
|
1559
|
+
- Allow calling lock procedures (such as forUpdate) outside of transaction. Fixes #2403. #2475
|
|
1560
|
+
- Added test and documentation for Event 'start' #2488
|
|
1519
1561
|
|
|
1520
1562
|
### Test / internal changes:
|
|
1521
1563
|
|
|
1522
1564
|
- Added stress test, which uses TCP proxy to simulate flaky connection #2460
|
|
1523
|
-
- Removed old docker tests, new stress test setup
|
|
1524
|
-
- Removed unused property \_\_cid on the base client
|
|
1525
|
-
- Changed rm to rimraf in 'npm run dev'
|
|
1526
|
-
- Changed babel preset and use latest node as target when running dev
|
|
1565
|
+
- Removed old docker tests, new stress test setup #2474
|
|
1566
|
+
- Removed unused property \_\_cid on the base client #2481
|
|
1567
|
+
- Changed rm to rimraf in 'npm run dev' #2483
|
|
1568
|
+
- Changed babel preset and use latest node as target when running dev #2484
|
|
1527
1569
|
|
|
1528
1570
|
# 0.14.3 - 8 Feb, 2018
|
|
1529
1571
|
|
|
@@ -1674,8 +1716,8 @@ Note: there are many breaking changes in this version, particularly in TypeScrip
|
|
|
1674
1716
|
|
|
1675
1717
|
# 0.12.6 - 19 Oct, 2016
|
|
1676
1718
|
|
|
1677
|
-
- Address warnings mentioned in #1388
|
|
1678
|
-
- Remove postinstall script
|
|
1719
|
+
- Address warnings mentioned in #1388 #1740
|
|
1720
|
+
- Remove postinstall script #1746
|
|
1679
1721
|
|
|
1680
1722
|
# 0.12.5 - 12 Oct, 2016
|
|
1681
1723
|
|
package/README.md
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
[](https://coveralls.io/r/knex/knex?branch=master)
|
|
7
7
|
[](https://libraries.io/npm/knex)
|
|
8
8
|
[](https://gitter.im/tgriesser/knex)
|
|
9
|
-
[](https://lgtm.com/projects/g/knex/knex/context:javascript)
|
|
10
9
|
|
|
11
10
|
> **A SQL query builder that is _flexible_, _portable_, and _fun_ to use!**
|
|
12
11
|
|
package/bin/cli.js
CHANGED
|
@@ -85,7 +85,7 @@ async function initKnex(env, opts, useDefaultClientIfNotSpecified) {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
function invoke() {
|
|
88
|
-
const filetypes = ['js', 'coffee', 'ts', 'eg', 'ls'];
|
|
88
|
+
const filetypes = ['js', 'mjs', 'coffee', 'ts', 'eg', 'ls'];
|
|
89
89
|
|
|
90
90
|
const cwd = argv.knexfile
|
|
91
91
|
? path.dirname(path.resolve(argv.knexfile))
|
|
@@ -218,7 +218,7 @@ function invoke() {
|
|
|
218
218
|
.action(async (name) => {
|
|
219
219
|
try {
|
|
220
220
|
const opts = commander.opts();
|
|
221
|
-
const instance = await initKnex(env, opts, true);
|
|
221
|
+
const instance = await initKnex(env, opts, true); // Skip config check, we don't really care about client when creating migrations
|
|
222
222
|
const ext = getMigrationExtension(env, opts);
|
|
223
223
|
const configOverrides = { extension: ext };
|
|
224
224
|
|
|
@@ -233,7 +233,7 @@ function invoke() {
|
|
|
233
233
|
success(color.green(`Created Migration: ${name}`));
|
|
234
234
|
})
|
|
235
235
|
.catch(exit);
|
|
236
|
-
} catch(err) {
|
|
236
|
+
} catch (err) {
|
|
237
237
|
exit(err);
|
|
238
238
|
}
|
|
239
239
|
});
|
|
@@ -397,7 +397,8 @@ function invoke() {
|
|
|
397
397
|
}
|
|
398
398
|
|
|
399
399
|
if (opts.timestampFilenamePrefix) {
|
|
400
|
-
configOverrides.timestampFilenamePrefix =
|
|
400
|
+
configOverrides.timestampFilenamePrefix =
|
|
401
|
+
opts.timestampFilenamePrefix;
|
|
401
402
|
}
|
|
402
403
|
|
|
403
404
|
instance.seed
|
|
@@ -406,9 +407,9 @@ function invoke() {
|
|
|
406
407
|
success(color.green(`Created seed file: ${name}`));
|
|
407
408
|
})
|
|
408
409
|
.catch(exit);
|
|
409
|
-
} catch(err) {
|
|
410
|
+
} catch (err) {
|
|
410
411
|
exit(err);
|
|
411
|
-
}
|
|
412
|
+
}
|
|
412
413
|
});
|
|
413
414
|
|
|
414
415
|
commander
|
package/knex.mjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Knex.js
|
|
2
|
+
// --------------
|
|
3
|
+
// (c) 2013-present Tim Griesser
|
|
4
|
+
// Knex may be freely distributed under the MIT license.
|
|
5
|
+
// For details and documentation:
|
|
6
|
+
// http://knexjs.org
|
|
7
|
+
|
|
8
|
+
import knex from './lib/index.js';
|
|
9
|
+
|
|
10
|
+
export { knex }
|
|
11
|
+
export default knex
|
package/lib/client.js
CHANGED
|
@@ -31,6 +31,7 @@ const { POOL_CONFIG_OPTIONS } = require('./constants');
|
|
|
31
31
|
const ViewBuilder = require('./schema/viewbuilder.js');
|
|
32
32
|
const ViewCompiler = require('./schema/viewcompiler.js');
|
|
33
33
|
const isPlainObject = require('lodash/isPlainObject');
|
|
34
|
+
const { setHiddenProperty } = require('./util/security.js');
|
|
34
35
|
|
|
35
36
|
const debug = require('debug')('knex:client');
|
|
36
37
|
|
|
@@ -43,6 +44,10 @@ class Client extends EventEmitter {
|
|
|
43
44
|
this.config = config;
|
|
44
45
|
this.logger = new Logger(config);
|
|
45
46
|
|
|
47
|
+
if (this.config.connection && this.config.connection.password) {
|
|
48
|
+
setHiddenProperty(this.config.connection);
|
|
49
|
+
}
|
|
50
|
+
|
|
46
51
|
//Client is a required field, so throw error if it's not supplied.
|
|
47
52
|
//If 'this.dialect' is set, then this is a 'super()' call, in which case
|
|
48
53
|
//'client' does not have to be set as it's already assigned on the client prototype.
|
|
@@ -69,6 +74,9 @@ class Client extends EventEmitter {
|
|
|
69
74
|
this.connectionConfigExpirationChecker = () => true; // causes the provider to be called on first use
|
|
70
75
|
} else {
|
|
71
76
|
this.connectionSettings = cloneDeep(config.connection || {});
|
|
77
|
+
if (config.connection && config.connection.password) {
|
|
78
|
+
setHiddenProperty(this.connectionSettings, config.connection);
|
|
79
|
+
}
|
|
72
80
|
this.connectionConfigExpirationChecker = null;
|
|
73
81
|
}
|
|
74
82
|
if (this.driverName && config.connection) {
|
|
@@ -305,6 +313,18 @@ class Client extends EventEmitter {
|
|
|
305
313
|
try {
|
|
306
314
|
const connection = await this.pool.acquire().promise;
|
|
307
315
|
debug('acquired connection from pool: %s', connection.__knexUid);
|
|
316
|
+
if (connection.config) {
|
|
317
|
+
if (connection.config.password) {
|
|
318
|
+
setHiddenProperty(connection.config);
|
|
319
|
+
}
|
|
320
|
+
if (
|
|
321
|
+
connection.config.authentication &&
|
|
322
|
+
connection.config.authentication.options &&
|
|
323
|
+
connection.config.authentication.options.password
|
|
324
|
+
) {
|
|
325
|
+
setHiddenProperty(connection.config.authentication.options);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
308
328
|
return connection;
|
|
309
329
|
} catch (error) {
|
|
310
330
|
let convertedError = error;
|
|
@@ -9,7 +9,12 @@ class Client_BetterSQLite3 extends Client_SQLite3 {
|
|
|
9
9
|
|
|
10
10
|
// Get a raw connection from the database, returning a promise with the connection object.
|
|
11
11
|
async acquireRawConnection() {
|
|
12
|
-
|
|
12
|
+
const options = this.connectionSettings.options || {};
|
|
13
|
+
|
|
14
|
+
return new this.driver(this.connectionSettings.filename, {
|
|
15
|
+
nativeBinding: options.nativeBinding,
|
|
16
|
+
readonly: !!options.readonly,
|
|
17
|
+
});
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
// Used to explicitly close a connection, called internally by the pool when
|
package/lib/dialects/index.js
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDialectByNameOrAlias = void 0;
|
|
4
|
-
const { resolveClientNameWithAliases } = require('../util/helpers');
|
|
5
|
-
const dbNameToDialectLoader = Object.freeze({
|
|
6
|
-
'better-sqlite3': () => require('./better-sqlite3'),
|
|
7
|
-
cockroachdb: () => require('./cockroachdb'),
|
|
8
|
-
mssql: () => require('./mssql'),
|
|
9
|
-
mysql: () => require('./mysql'),
|
|
10
|
-
mysql2: () => require('./mysql2'),
|
|
11
|
-
oracle: () => require('./oracle'),
|
|
12
|
-
oracledb: () => require('./oracledb'),
|
|
13
|
-
pgnative: () => require('./pgnative'),
|
|
14
|
-
postgres: () => require('./postgres'),
|
|
15
|
-
redshift: () => require('./redshift'),
|
|
16
|
-
sqlite3: () => require('./sqlite3'),
|
|
17
|
-
});
|
|
18
|
-
/**
|
|
19
|
-
* Gets the Dialect object with the given client name or throw an
|
|
20
|
-
* error if not found.
|
|
21
|
-
*
|
|
22
|
-
* NOTE: This is a replacement for prior practice of doing dynamic
|
|
23
|
-
* string construction for imports of Dialect objects.
|
|
24
|
-
*/
|
|
25
|
-
function getDialectByNameOrAlias(clientName) {
|
|
26
|
-
const resolvedClientName = resolveClientNameWithAliases(clientName);
|
|
27
|
-
const dialectLoader = dbNameToDialectLoader[resolvedClientName];
|
|
28
|
-
if (!dialectLoader) {
|
|
29
|
-
throw new Error(`Invalid clientName given: ${clientName}`);
|
|
30
|
-
}
|
|
31
|
-
return dialectLoader();
|
|
32
|
-
}
|
|
33
|
-
exports.getDialectByNameOrAlias = getDialectByNameOrAlias;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDialectByNameOrAlias = void 0;
|
|
4
|
+
const { resolveClientNameWithAliases } = require('../util/helpers');
|
|
5
|
+
const dbNameToDialectLoader = Object.freeze({
|
|
6
|
+
'better-sqlite3': () => require('./better-sqlite3'),
|
|
7
|
+
cockroachdb: () => require('./cockroachdb'),
|
|
8
|
+
mssql: () => require('./mssql'),
|
|
9
|
+
mysql: () => require('./mysql'),
|
|
10
|
+
mysql2: () => require('./mysql2'),
|
|
11
|
+
oracle: () => require('./oracle'),
|
|
12
|
+
oracledb: () => require('./oracledb'),
|
|
13
|
+
pgnative: () => require('./pgnative'),
|
|
14
|
+
postgres: () => require('./postgres'),
|
|
15
|
+
redshift: () => require('./redshift'),
|
|
16
|
+
sqlite3: () => require('./sqlite3'),
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* Gets the Dialect object with the given client name or throw an
|
|
20
|
+
* error if not found.
|
|
21
|
+
*
|
|
22
|
+
* NOTE: This is a replacement for prior practice of doing dynamic
|
|
23
|
+
* string construction for imports of Dialect objects.
|
|
24
|
+
*/
|
|
25
|
+
function getDialectByNameOrAlias(clientName) {
|
|
26
|
+
const resolvedClientName = resolveClientNameWithAliases(clientName);
|
|
27
|
+
const dialectLoader = dbNameToDialectLoader[resolvedClientName];
|
|
28
|
+
if (!dialectLoader) {
|
|
29
|
+
throw new Error(`Invalid clientName given: ${clientName}`);
|
|
30
|
+
}
|
|
31
|
+
return dialectLoader();
|
|
32
|
+
}
|
|
33
|
+
exports.getDialectByNameOrAlias = getDialectByNameOrAlias;
|
|
34
34
|
//# sourceMappingURL=index.js.map
|
|
@@ -12,6 +12,7 @@ const TableCompiler = require('./schema/mssql-tablecompiler');
|
|
|
12
12
|
const ViewCompiler = require('./schema/mssql-viewcompiler');
|
|
13
13
|
const ColumnCompiler = require('./schema/mssql-columncompiler');
|
|
14
14
|
const QueryBuilder = require('../../query/querybuilder');
|
|
15
|
+
const { setHiddenProperty } = require('../../util/security');
|
|
15
16
|
|
|
16
17
|
const debug = require('debug')('knex:mssql');
|
|
17
18
|
|
|
@@ -66,6 +67,10 @@ class Client_MSSQL extends Client {
|
|
|
66
67
|
},
|
|
67
68
|
};
|
|
68
69
|
|
|
70
|
+
if (cfg.authentication.options.password) {
|
|
71
|
+
setHiddenProperty(cfg.authentication.options);
|
|
72
|
+
}
|
|
73
|
+
|
|
69
74
|
// tedious always connect via tcp when port is specified
|
|
70
75
|
if (cfg.options.instanceName) delete cfg.options.port;
|
|
71
76
|
|
|
@@ -14,6 +14,26 @@ class Client_MySQL2 extends Client_MySQL {
|
|
|
14
14
|
_driver() {
|
|
15
15
|
return require('mysql2');
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
initializeDriver() {
|
|
19
|
+
try {
|
|
20
|
+
this.driver = this._driver();
|
|
21
|
+
} catch (e) {
|
|
22
|
+
let message = `Knex: run\n$ npm install ${this.driverName}`;
|
|
23
|
+
|
|
24
|
+
const nodeMajorVersion = process.version.replace(/^v/, '').split('.')[0];
|
|
25
|
+
if (nodeMajorVersion <= 12) {
|
|
26
|
+
message += `@3.2.0`;
|
|
27
|
+
this.logger.error(
|
|
28
|
+
'Mysql2 version 3.2.0 is the latest version to support Node.js 12 or lower.'
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
message += ` --save`;
|
|
32
|
+
this.logger.error(`${message}\n${e.message}\n${e.stack}`);
|
|
33
|
+
throw new Error(`${message}\n${e.message}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
17
37
|
validateConnection(connection) {
|
|
18
38
|
return (
|
|
19
39
|
connection &&
|
|
@@ -254,10 +254,6 @@ class Client_Oracledb extends Client_Oracle {
|
|
|
254
254
|
});
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
|
-
if (connection.isTransaction) {
|
|
258
|
-
return obj;
|
|
259
|
-
}
|
|
260
|
-
await connection.commitAsync();
|
|
261
257
|
if (obj.returningSql) {
|
|
262
258
|
const response = await connection.executeAsync(
|
|
263
259
|
obj.returningSql(),
|
|
@@ -266,6 +262,10 @@ class Client_Oracledb extends Client_Oracle {
|
|
|
266
262
|
);
|
|
267
263
|
obj.response = response.rows;
|
|
268
264
|
}
|
|
265
|
+
if (connection.isTransaction) {
|
|
266
|
+
return obj;
|
|
267
|
+
}
|
|
268
|
+
await connection.commitAsync();
|
|
269
269
|
return obj;
|
|
270
270
|
});
|
|
271
271
|
}
|
|
@@ -287,7 +287,7 @@ class Client_Oracledb extends Client_Oracle {
|
|
|
287
287
|
case 'del':
|
|
288
288
|
case 'update':
|
|
289
289
|
case 'counter':
|
|
290
|
-
if (obj.returning && !isEmpty(obj.returning)) {
|
|
290
|
+
if ((obj.returning && !isEmpty(obj.returning)) || obj.returningSql) {
|
|
291
291
|
return response;
|
|
292
292
|
} else if (obj.rowsAffected !== undefined) {
|
|
293
293
|
return obj.rowsAffected;
|
|
@@ -4,7 +4,7 @@ const { isObject } = require('../../../util/is');
|
|
|
4
4
|
class ColumnCompiler_Oracledb extends ColumnCompiler_Oracle {
|
|
5
5
|
constructor() {
|
|
6
6
|
super(...arguments);
|
|
7
|
-
this.modifiers = ['defaultTo', 'nullable', 'comment'];
|
|
7
|
+
this.modifiers = ['defaultTo', 'nullable', 'comment', 'checkJson'];
|
|
8
8
|
this._addCheckModifiers();
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -38,14 +38,20 @@ class ColumnCompiler_Oracledb extends ColumnCompiler_Oracle {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
json() {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
// implicitly add the check for json
|
|
42
|
+
this.columnBuilder._modifiers.checkJson = [
|
|
43
|
+
this.formatter.columnize(this.getColumnName()),
|
|
44
|
+
];
|
|
45
|
+
return 'varchar2(4000)';
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
jsonb() {
|
|
47
49
|
return this.json();
|
|
48
50
|
}
|
|
51
|
+
|
|
52
|
+
checkJson(column) {
|
|
53
|
+
return `check (${column} is json)`;
|
|
54
|
+
}
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
ColumnCompiler_Oracledb.prototype.time = 'timestamp with local time zone';
|
|
@@ -2,10 +2,17 @@ const Transaction = require('../../../execution/transaction');
|
|
|
2
2
|
|
|
3
3
|
class Transaction_PG extends Transaction {
|
|
4
4
|
begin(conn) {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const trxMode = [
|
|
6
|
+
this.isolationLevel ? `ISOLATION LEVEL ${this.isolationLevel}` : '',
|
|
7
|
+
this.readOnly ? 'READ ONLY' : '',
|
|
8
|
+
]
|
|
9
|
+
.join(' ')
|
|
10
|
+
.trim();
|
|
11
|
+
|
|
12
|
+
if (trxMode.length === 0) {
|
|
13
|
+
return this.query(conn, 'BEGIN;');
|
|
7
14
|
}
|
|
8
|
-
return this.query(conn,
|
|
15
|
+
return this.query(conn, `BEGIN TRANSACTION ${trxMode};`);
|
|
9
16
|
}
|
|
10
17
|
}
|
|
11
18
|
|
|
@@ -80,6 +80,14 @@ class Client_PG extends Client {
|
|
|
80
80
|
_acquireOnlyConnection() {
|
|
81
81
|
const connection = new this.driver.Client(this.connectionSettings);
|
|
82
82
|
|
|
83
|
+
connection.on('error', (err) => {
|
|
84
|
+
connection.__knex__disposed = err;
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
connection.on('end', (err) => {
|
|
88
|
+
connection.__knex__disposed = err || 'Connection ended unexpectedly';
|
|
89
|
+
});
|
|
90
|
+
|
|
83
91
|
return connection.connect().then(() => connection);
|
|
84
92
|
}
|
|
85
93
|
|
|
@@ -90,14 +98,6 @@ class Client_PG extends Client {
|
|
|
90
98
|
|
|
91
99
|
return this._acquireOnlyConnection()
|
|
92
100
|
.then(function (connection) {
|
|
93
|
-
connection.on('error', (err) => {
|
|
94
|
-
connection.__knex__disposed = err;
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
connection.on('end', (err) => {
|
|
98
|
-
connection.__knex__disposed = err || 'Connection ended unexpectedly';
|
|
99
|
-
});
|
|
100
|
-
|
|
101
101
|
if (!client.version) {
|
|
102
102
|
return client.checkVersion(connection).then(function (version) {
|
|
103
103
|
client.version = version;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
const QueryBuilder = require('../../../query/querybuilder.js');
|
|
2
2
|
|
|
3
3
|
module.exports = class QueryBuilder_PostgreSQL extends QueryBuilder {
|
|
4
|
+
updateFrom(name) {
|
|
5
|
+
this._single.updateFrom = name;
|
|
6
|
+
return this;
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
using(tables) {
|
|
5
10
|
this._single.using = tables;
|
|
6
11
|
return this;
|
|
@@ -50,12 +50,13 @@ class QueryCompiler_PG extends QueryCompiler {
|
|
|
50
50
|
const withSQL = this.with();
|
|
51
51
|
const updateData = this._prepUpdate(this.single.update);
|
|
52
52
|
const wheres = this.where();
|
|
53
|
-
const { returning } = this.single;
|
|
53
|
+
const { returning, updateFrom } = this.single;
|
|
54
54
|
return {
|
|
55
55
|
sql:
|
|
56
56
|
withSQL +
|
|
57
57
|
`update ${this.single.only ? 'only ' : ''}${this.tableName} ` +
|
|
58
58
|
`set ${updateData.join(', ')}` +
|
|
59
|
+
this._updateFrom(updateFrom) +
|
|
59
60
|
(wheres ? ` ${wheres}` : '') +
|
|
60
61
|
this._returning(returning),
|
|
61
62
|
returning,
|
|
@@ -141,6 +142,10 @@ class QueryCompiler_PG extends QueryCompiler {
|
|
|
141
142
|
return value ? ` returning ${this.formatter.columnize(value)}` : '';
|
|
142
143
|
}
|
|
143
144
|
|
|
145
|
+
_updateFrom(name) {
|
|
146
|
+
return name ? ` from ${this.formatter.wrap(name)}` : '';
|
|
147
|
+
}
|
|
148
|
+
|
|
144
149
|
_ignore(columns) {
|
|
145
150
|
if (columns === true) {
|
|
146
151
|
return ' on conflict do nothing';
|
|
@@ -120,7 +120,9 @@ class SchemaCompiler_PG extends SchemaCompiler {
|
|
|
120
120
|
|
|
121
121
|
refreshMaterializedView(viewName, concurrently = false) {
|
|
122
122
|
this.pushQuery({
|
|
123
|
-
sql: `refresh materialized view${
|
|
123
|
+
sql: `refresh materialized view${
|
|
124
|
+
concurrently ? ' concurrently' : ''
|
|
125
|
+
} ${this.formatter.wrap(viewName)}`,
|
|
124
126
|
});
|
|
125
127
|
}
|
|
126
128
|
|
|
@@ -235,12 +235,13 @@ class TableCompiler_PG extends TableCompiler {
|
|
|
235
235
|
: this._indexCommand('index', this.tableNameRaw, columns);
|
|
236
236
|
|
|
237
237
|
let predicate;
|
|
238
|
+
let storageEngineIndexType;
|
|
238
239
|
let indexType;
|
|
239
240
|
|
|
240
241
|
if (isString(options)) {
|
|
241
|
-
|
|
242
|
+
storageEngineIndexType = options;
|
|
242
243
|
} else if (isObject(options)) {
|
|
243
|
-
({ indexType, predicate } = options);
|
|
244
|
+
({ indexType, storageEngineIndexType, predicate } = options);
|
|
244
245
|
}
|
|
245
246
|
|
|
246
247
|
const predicateQuery = predicate
|
|
@@ -248,8 +249,12 @@ class TableCompiler_PG extends TableCompiler {
|
|
|
248
249
|
: '';
|
|
249
250
|
|
|
250
251
|
this.pushQuery(
|
|
251
|
-
`create
|
|
252
|
-
|
|
252
|
+
`create${
|
|
253
|
+
typeof indexType === 'string' && indexType.toLowerCase() === 'unique'
|
|
254
|
+
? ' unique'
|
|
255
|
+
: ''
|
|
256
|
+
} index ${indexName} on ${this.tableName()}${
|
|
257
|
+
(storageEngineIndexType && ` using ${storageEngineIndexType}`) || ''
|
|
253
258
|
}` +
|
|
254
259
|
' (' +
|
|
255
260
|
this.formatter.columnize(columns) +
|
|
@@ -2,10 +2,17 @@ const Transaction = require('../../execution/transaction');
|
|
|
2
2
|
|
|
3
3
|
module.exports = class Redshift_Transaction extends Transaction {
|
|
4
4
|
begin(conn) {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const trxMode = [
|
|
6
|
+
this.isolationLevel ? `ISOLATION LEVEL ${this.isolationLevel}` : '',
|
|
7
|
+
this.readOnly ? 'READ ONLY' : '',
|
|
8
|
+
]
|
|
9
|
+
.join(' ')
|
|
10
|
+
.trim();
|
|
11
|
+
|
|
12
|
+
if (trxMode.length === 0) {
|
|
13
|
+
return this.query(conn, 'BEGIN;');
|
|
7
14
|
}
|
|
8
|
-
return this.query(conn,
|
|
15
|
+
return this.query(conn, `BEGIN ${trxMode};`);
|
|
9
16
|
}
|
|
10
17
|
|
|
11
18
|
savepoint(conn) {
|
|
@@ -11,6 +11,13 @@ class Transaction_Sqlite extends Transaction {
|
|
|
11
11
|
'sqlite3 only supports serializable transactions, ignoring the isolation level param'
|
|
12
12
|
);
|
|
13
13
|
}
|
|
14
|
+
// SQLite infers read vs write transactions from the statement operation
|
|
15
|
+
// https://www.sqlite.org/lang_transaction.html#read_transactions_versus_write_transactions
|
|
16
|
+
if (this.readOnly) {
|
|
17
|
+
this.client.logger.warn(
|
|
18
|
+
'sqlite3 implicitly handles read vs write transactions'
|
|
19
|
+
);
|
|
20
|
+
}
|
|
14
21
|
return this.query(conn, 'BEGIN;');
|
|
15
22
|
}
|
|
16
23
|
}
|
|
@@ -15,7 +15,7 @@ function renameTable(tableName, alteredName) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
function getTableSql(tableName) {
|
|
18
|
-
return `SELECT type, sql FROM sqlite_master WHERE (type='table' OR (type='index' AND sql IS NOT NULL)) AND tbl_name='${tableName}'`;
|
|
18
|
+
return `SELECT type, sql FROM sqlite_master WHERE (type='table' OR (type='index' AND sql IS NOT NULL)) AND lower(tbl_name)='${tableName.toLowerCase()}'`;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
function isForeignCheckEnabled() {
|
package/lib/execution/runner.js
CHANGED
|
@@ -72,6 +72,24 @@ class Runner {
|
|
|
72
72
|
this.client.releaseConnection(this.connection);
|
|
73
73
|
});
|
|
74
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
|
+
|
|
75
93
|
const connectionAcquirePromise = this.ensureConnection(
|
|
76
94
|
ensureConnectionStreamCallback,
|
|
77
95
|
{
|