knex 3.0.1 → 3.1.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 +23 -1
- package/lib/dialects/mysql/index.js +5 -0
- package/lib/dialects/mysql/query/mysql-querybuilder.js +14 -0
- package/lib/dialects/mysql/query/mysql-querycompiler.js +18 -0
- package/lib/dialects/mysql/schema/mysql-tablecompiler.js +24 -0
- package/lib/dialects/oracle/schema/internal/incrementUtils.js +3 -1
- package/lib/dialects/oracle/schema/internal/trigger.js +38 -18
- package/lib/dialects/oracle/schema/oracle-compiler.js +4 -2
- package/lib/dialects/oracle/schema/oracle-tablecompiler.js +9 -2
- package/lib/dialects/oracle/utils.js +41 -22
- package/lib/dialects/oracledb/index.js +70 -16
- package/lib/dialects/postgres/index.js +4 -1
- package/lib/execution/transaction.js +4 -0
- package/lib/migrations/migrate/stub/ts.stub +1 -1
- package/lib/query/querybuilder.js +1 -1
- package/lib/schema/tablecompiler.js +6 -0
- package/package.json +11 -10
- package/types/index.d.ts +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
# Master (Unreleased)
|
|
2
2
|
|
|
3
|
-
# 3.
|
|
3
|
+
# 3.1.0 - 8 December, 2023
|
|
4
|
+
|
|
5
|
+
### Bug fixes
|
|
6
|
+
|
|
7
|
+
- andWhereNotJsonObject calling wrong function (#5683)
|
|
8
|
+
- PostgreSQL: fix error when setting query_timeout (#5673)
|
|
9
|
+
- MySQL: Missing comments on delete, update and insert (#5738)
|
|
10
|
+
- MySQL: Fixed issue with bigincrements not working with composite primary key - #5341 (#5343)
|
|
11
|
+
|
|
12
|
+
### Types
|
|
13
|
+
|
|
14
|
+
- Add type definitions for orHavingNull and orHavingNotNull (#5669)
|
|
15
|
+
- Import knex as type in TS migration template (#5741)
|
|
16
|
+
- Fix conditional constraint error (#5747)
|
|
17
|
+
- PostgreSQL: Fix typing to reflect pg typing change (#5647)
|
|
18
|
+
|
|
19
|
+
### New features
|
|
20
|
+
|
|
21
|
+
- Add transactor.parentTransaction (#5567)
|
|
22
|
+
- MySQL: Added implementation for upsert (#5743)
|
|
23
|
+
- Oracle: Support Object Names Greater than 30 Characters for Oracle DB Versions 12.2 and Greater (#5197)
|
|
24
|
+
|
|
25
|
+
# 3.0.1 - 6 October, 2023
|
|
4
26
|
|
|
5
27
|
- Build fix
|
|
6
28
|
|
|
@@ -6,6 +6,7 @@ const { promisify } = require('util');
|
|
|
6
6
|
const Client = require('../../client');
|
|
7
7
|
|
|
8
8
|
const Transaction = require('./transaction');
|
|
9
|
+
const QueryBuilder = require('./query/mysql-querybuilder');
|
|
9
10
|
const QueryCompiler = require('./query/mysql-querycompiler');
|
|
10
11
|
const SchemaCompiler = require('./schema/mysql-compiler');
|
|
11
12
|
const TableCompiler = require('./schema/mysql-tablecompiler');
|
|
@@ -23,6 +24,10 @@ class Client_MySQL extends Client {
|
|
|
23
24
|
return require('mysql');
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
queryBuilder() {
|
|
28
|
+
return new QueryBuilder(this);
|
|
29
|
+
}
|
|
30
|
+
|
|
26
31
|
queryCompiler(builder, formatter) {
|
|
27
32
|
return new QueryCompiler(this, builder, formatter);
|
|
28
33
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const QueryBuilder = require('../../../query/querybuilder');
|
|
2
|
+
const isEmpty = require('lodash/isEmpty');
|
|
3
|
+
|
|
4
|
+
module.exports = class QueryBuilder_MySQL extends QueryBuilder {
|
|
5
|
+
upsert(values, returning, options) {
|
|
6
|
+
this._method = 'upsert';
|
|
7
|
+
if (!isEmpty(returning)) {
|
|
8
|
+
this.returning(returning, options);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
this._single.upsert = values;
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -27,12 +27,21 @@ class QueryCompiler_MySQL extends QueryCompiler {
|
|
|
27
27
|
|
|
28
28
|
this._emptyInsertValue = '() values ()';
|
|
29
29
|
}
|
|
30
|
+
// Compiles an `delete` allowing comments
|
|
31
|
+
del() {
|
|
32
|
+
const sql = super.del();
|
|
33
|
+
if (sql === '') return sql;
|
|
34
|
+
const comments = this.comments();
|
|
35
|
+
return (comments === '' ? '' : comments + ' ') + sql;
|
|
36
|
+
}
|
|
30
37
|
|
|
31
38
|
// Compiles an `insert` query, allowing for multiple
|
|
32
39
|
// inserts using a single query statement.
|
|
33
40
|
insert() {
|
|
34
41
|
let sql = super.insert();
|
|
35
42
|
if (sql === '') return sql;
|
|
43
|
+
const comments = this.comments();
|
|
44
|
+
sql = (comments === '' ? '' : comments + ' ') + sql;
|
|
36
45
|
|
|
37
46
|
const { ignore, merge, insert } = this.single;
|
|
38
47
|
if (ignore) sql = sql.replace('insert into', 'insert ignore into');
|
|
@@ -49,6 +58,13 @@ class QueryCompiler_MySQL extends QueryCompiler {
|
|
|
49
58
|
return sql;
|
|
50
59
|
}
|
|
51
60
|
|
|
61
|
+
upsert() {
|
|
62
|
+
const upsertValues = this.single.upsert || [];
|
|
63
|
+
const sql = this.with() + `replace into ${this.tableName} `;
|
|
64
|
+
const body = this._insertBody(upsertValues);
|
|
65
|
+
return body === '' ? '' : sql + body;
|
|
66
|
+
}
|
|
67
|
+
|
|
52
68
|
// Compiles merge for onConflict, allowing for different merge strategies
|
|
53
69
|
_merge(updates, insert) {
|
|
54
70
|
const sql = ' on duplicate key update ';
|
|
@@ -86,6 +102,7 @@ class QueryCompiler_MySQL extends QueryCompiler {
|
|
|
86
102
|
|
|
87
103
|
// Update method, including joins, wheres, order & limits.
|
|
88
104
|
update() {
|
|
105
|
+
const comments = this.comments();
|
|
89
106
|
const withSQL = this.with();
|
|
90
107
|
const join = this.join();
|
|
91
108
|
const updates = this._prepUpdate(this.single.update);
|
|
@@ -93,6 +110,7 @@ class QueryCompiler_MySQL extends QueryCompiler {
|
|
|
93
110
|
const order = this.order();
|
|
94
111
|
const limit = this.limit();
|
|
95
112
|
return (
|
|
113
|
+
(comments === '' ? '' : comments + ' ') +
|
|
96
114
|
withSQL +
|
|
97
115
|
`update ${this.tableName}` +
|
|
98
116
|
(join ? ` ${join}` : '') +
|
|
@@ -160,6 +160,14 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
160
160
|
}
|
|
161
161
|
});
|
|
162
162
|
}
|
|
163
|
+
const bigIncrementsCols = this._getBigIncrementsColumnNames();
|
|
164
|
+
if (bigIncrementsCols.length) {
|
|
165
|
+
bigIncrementsCols.forEach((c) => {
|
|
166
|
+
if (!columns.includes(c)) {
|
|
167
|
+
columns.unshift(c);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
163
171
|
}
|
|
164
172
|
|
|
165
173
|
return `,${constraintName} primary key (${this.formatter.columnize(
|
|
@@ -292,6 +300,7 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
292
300
|
|
|
293
301
|
const primaryCols = columns;
|
|
294
302
|
let incrementsCols = [];
|
|
303
|
+
let bigIncrementsCols = [];
|
|
295
304
|
if (this.grouped.columns) {
|
|
296
305
|
incrementsCols = this._getIncrementsColumnNames();
|
|
297
306
|
if (incrementsCols) {
|
|
@@ -301,6 +310,14 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
301
310
|
}
|
|
302
311
|
});
|
|
303
312
|
}
|
|
313
|
+
bigIncrementsCols = this._getBigIncrementsColumnNames();
|
|
314
|
+
if (bigIncrementsCols) {
|
|
315
|
+
bigIncrementsCols.forEach((c) => {
|
|
316
|
+
if (!primaryCols.includes(c)) {
|
|
317
|
+
primaryCols.unshift(c);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
304
321
|
}
|
|
305
322
|
if (this.method !== 'create' && this.method !== 'createIfNot') {
|
|
306
323
|
this.pushQuery(
|
|
@@ -316,6 +333,13 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
316
333
|
)} int unsigned not null auto_increment`
|
|
317
334
|
);
|
|
318
335
|
}
|
|
336
|
+
if (bigIncrementsCols.length) {
|
|
337
|
+
this.pushQuery(
|
|
338
|
+
`alter table ${this.tableName()} modify column ${this.formatter.columnize(
|
|
339
|
+
bigIncrementsCols
|
|
340
|
+
)} bigint unsigned not null auto_increment`
|
|
341
|
+
);
|
|
342
|
+
}
|
|
319
343
|
}
|
|
320
344
|
|
|
321
345
|
unique(columns, indexName) {
|
|
@@ -2,11 +2,13 @@ const Trigger = require('./trigger');
|
|
|
2
2
|
|
|
3
3
|
// helper function for pushAdditional in increments() and bigincrements()
|
|
4
4
|
function createAutoIncrementTriggerAndSequence(columnCompiler) {
|
|
5
|
+
const trigger = new Trigger(columnCompiler.client.version);
|
|
6
|
+
|
|
5
7
|
// TODO Add warning that sequence etc is created
|
|
6
8
|
columnCompiler.pushAdditional(function () {
|
|
7
9
|
const tableName = this.tableCompiler.tableNameRaw;
|
|
8
10
|
const schemaName = this.tableCompiler.schemaNameRaw;
|
|
9
|
-
const createTriggerSQL =
|
|
11
|
+
const createTriggerSQL = trigger.createAutoIncrementTrigger(
|
|
10
12
|
this.client.logger,
|
|
11
13
|
tableName,
|
|
12
14
|
schemaName
|
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
const
|
|
1
|
+
const { NameHelper } = require('../../utils');
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
class Trigger {
|
|
4
|
+
constructor(oracleVersion) {
|
|
5
|
+
this.nameHelper = new NameHelper(oracleVersion);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
renameColumnTrigger(logger, tableName, columnName, to) {
|
|
9
|
+
const triggerName = this.nameHelper.generateCombinedName(
|
|
6
10
|
logger,
|
|
7
11
|
'autoinc_trg',
|
|
8
12
|
tableName
|
|
9
13
|
);
|
|
10
|
-
const sequenceName =
|
|
14
|
+
const sequenceName = this.nameHelper.generateCombinedName(
|
|
15
|
+
logger,
|
|
16
|
+
'seq',
|
|
17
|
+
tableName
|
|
18
|
+
);
|
|
11
19
|
return (
|
|
12
20
|
`DECLARE ` +
|
|
13
21
|
`PK_NAME VARCHAR(200); ` +
|
|
@@ -41,19 +49,19 @@ const trigger = {
|
|
|
41
49
|
` end if;` +
|
|
42
50
|
`END;`
|
|
43
51
|
);
|
|
44
|
-
}
|
|
52
|
+
}
|
|
45
53
|
|
|
46
|
-
createAutoIncrementTrigger
|
|
54
|
+
createAutoIncrementTrigger(logger, tableName, schemaName) {
|
|
47
55
|
const tableQuoted = `"${tableName}"`;
|
|
48
56
|
const tableUnquoted = tableName;
|
|
49
57
|
const schemaQuoted = schemaName ? `"${schemaName}".` : '';
|
|
50
58
|
const constraintOwner = schemaName ? `'${schemaName}'` : 'cols.owner';
|
|
51
|
-
const triggerName =
|
|
59
|
+
const triggerName = this.nameHelper.generateCombinedName(
|
|
52
60
|
logger,
|
|
53
61
|
'autoinc_trg',
|
|
54
62
|
tableName
|
|
55
63
|
);
|
|
56
|
-
const sequenceNameUnquoted =
|
|
64
|
+
const sequenceNameUnquoted = this.nameHelper.generateCombinedName(
|
|
57
65
|
logger,
|
|
58
66
|
'seq',
|
|
59
67
|
tableName
|
|
@@ -86,17 +94,29 @@ const trigger = {
|
|
|
86
94
|
` end;'); ` +
|
|
87
95
|
`END;`
|
|
88
96
|
);
|
|
89
|
-
}
|
|
97
|
+
}
|
|
90
98
|
|
|
91
|
-
renameTableAndAutoIncrementTrigger
|
|
92
|
-
const triggerName =
|
|
99
|
+
renameTableAndAutoIncrementTrigger(logger, tableName, to) {
|
|
100
|
+
const triggerName = this.nameHelper.generateCombinedName(
|
|
93
101
|
logger,
|
|
94
102
|
'autoinc_trg',
|
|
95
103
|
tableName
|
|
96
104
|
);
|
|
97
|
-
const sequenceName =
|
|
98
|
-
|
|
99
|
-
|
|
105
|
+
const sequenceName = this.nameHelper.generateCombinedName(
|
|
106
|
+
logger,
|
|
107
|
+
'seq',
|
|
108
|
+
tableName
|
|
109
|
+
);
|
|
110
|
+
const toTriggerName = this.nameHelper.generateCombinedName(
|
|
111
|
+
logger,
|
|
112
|
+
'autoinc_trg',
|
|
113
|
+
to
|
|
114
|
+
);
|
|
115
|
+
const toSequenceName = this.nameHelper.generateCombinedName(
|
|
116
|
+
logger,
|
|
117
|
+
'seq',
|
|
118
|
+
to
|
|
119
|
+
);
|
|
100
120
|
return (
|
|
101
121
|
`DECLARE ` +
|
|
102
122
|
`PK_NAME VARCHAR(200); ` +
|
|
@@ -129,7 +149,7 @@ const trigger = {
|
|
|
129
149
|
` end if;` +
|
|
130
150
|
`END;`
|
|
131
151
|
);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
134
154
|
|
|
135
|
-
module.exports =
|
|
155
|
+
module.exports = Trigger;
|
|
@@ -11,7 +11,8 @@ class SchemaCompiler_Oracle extends SchemaCompiler {
|
|
|
11
11
|
|
|
12
12
|
// Rename a table on the schema.
|
|
13
13
|
renameTable(tableName, to) {
|
|
14
|
-
const
|
|
14
|
+
const trigger = new Trigger(this.client.version);
|
|
15
|
+
const renameTable = trigger.renameTableAndAutoIncrementTrigger(
|
|
15
16
|
this.client.logger,
|
|
16
17
|
tableName,
|
|
17
18
|
to
|
|
@@ -60,7 +61,8 @@ class SchemaCompiler_Oracle extends SchemaCompiler {
|
|
|
60
61
|
|
|
61
62
|
_dropRelatedSequenceIfExists(tableName) {
|
|
62
63
|
// removing the sequence that was possibly generated by increments() column
|
|
63
|
-
const
|
|
64
|
+
const nameHelper = new utils.NameHelper(this.client.version);
|
|
65
|
+
const sequenceName = nameHelper.generateCombinedName(
|
|
64
66
|
this.client.logger,
|
|
65
67
|
'seq',
|
|
66
68
|
tableName
|
|
@@ -39,8 +39,9 @@ class TableCompiler_Oracle extends TableCompiler {
|
|
|
39
39
|
renameColumn(from, to) {
|
|
40
40
|
// Remove quotes around tableName
|
|
41
41
|
const tableName = this.tableName().slice(1, -1);
|
|
42
|
+
const trigger = new Trigger(this.client.version);
|
|
42
43
|
return this.pushQuery(
|
|
43
|
-
|
|
44
|
+
trigger.renameColumnTrigger(this.client.logger, tableName, from, to)
|
|
44
45
|
);
|
|
45
46
|
}
|
|
46
47
|
|
|
@@ -86,8 +87,14 @@ class TableCompiler_Oracle extends TableCompiler {
|
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
_indexCommand(type, tableName, columns) {
|
|
90
|
+
const nameHelper = new utils.NameHelper(this.client.version);
|
|
89
91
|
return this.formatter.wrap(
|
|
90
|
-
|
|
92
|
+
nameHelper.generateCombinedName(
|
|
93
|
+
this.client.logger,
|
|
94
|
+
type,
|
|
95
|
+
tableName,
|
|
96
|
+
columns
|
|
97
|
+
)
|
|
91
98
|
);
|
|
92
99
|
}
|
|
93
100
|
|
|
@@ -1,25 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
class NameHelper {
|
|
2
|
+
constructor(oracleVersion) {
|
|
3
|
+
this.oracleVersion = oracleVersion;
|
|
4
|
+
|
|
5
|
+
// In oracle versions prior to 12.2, the maximum length for a database
|
|
6
|
+
// object name was 30 characters. 12.2 extended this to 128.
|
|
7
|
+
const versionParts = oracleVersion
|
|
8
|
+
.split('.')
|
|
9
|
+
.map((versionPart) => parseInt(versionPart));
|
|
10
|
+
if (
|
|
11
|
+
versionParts[0] > 12 ||
|
|
12
|
+
(versionParts[0] === 12 && versionParts[1] >= 2)
|
|
13
|
+
) {
|
|
14
|
+
this.limit = 128;
|
|
15
|
+
} else {
|
|
16
|
+
this.limit = 30;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
generateCombinedName(logger, postfix, name, subNames) {
|
|
21
|
+
const crypto = require('crypto');
|
|
22
|
+
if (!Array.isArray(subNames)) subNames = subNames ? [subNames] : [];
|
|
23
|
+
const table = name.replace(/\.|-/g, '_');
|
|
24
|
+
const subNamesPart = subNames.join('_');
|
|
25
|
+
let result = `${table}_${
|
|
26
|
+
subNamesPart.length ? subNamesPart + '_' : ''
|
|
27
|
+
}${postfix}`.toLowerCase();
|
|
28
|
+
if (result.length > this.limit) {
|
|
29
|
+
logger.warn(
|
|
30
|
+
`Automatically generated name "${result}" exceeds ${this.limit} character ` +
|
|
31
|
+
`limit for Oracle Database ${this.oracleVersion}. Using base64 encoded sha1 of that name instead.`
|
|
32
|
+
);
|
|
33
|
+
// generates the sha1 of the name and encode it with base64
|
|
34
|
+
result = crypto
|
|
35
|
+
.createHash('sha1')
|
|
36
|
+
.update(result)
|
|
37
|
+
.digest('base64')
|
|
38
|
+
.replace('=', '');
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
21
41
|
}
|
|
22
|
-
return result;
|
|
23
42
|
}
|
|
24
43
|
|
|
25
44
|
function wrapSqlWithCatch(sql, errorNumberToCatch) {
|
|
@@ -80,7 +99,7 @@ function isConnectionError(err) {
|
|
|
80
99
|
}
|
|
81
100
|
|
|
82
101
|
module.exports = {
|
|
83
|
-
|
|
102
|
+
NameHelper,
|
|
84
103
|
isConnectionError,
|
|
85
104
|
wrapSqlWithCatch,
|
|
86
105
|
ReturningHelper,
|
|
@@ -25,6 +25,13 @@ const { compileCallback } = require('../../formatter/formatterUtils');
|
|
|
25
25
|
class Client_Oracledb extends Client_Oracle {
|
|
26
26
|
constructor(config) {
|
|
27
27
|
super(config);
|
|
28
|
+
|
|
29
|
+
if (this.version) {
|
|
30
|
+
// Normalize version format; null bad format
|
|
31
|
+
// to trigger fallback to auto-detect.
|
|
32
|
+
this.version = parseVersion(this.version);
|
|
33
|
+
}
|
|
34
|
+
|
|
28
35
|
if (this.driver) {
|
|
29
36
|
process.env.UV_THREADPOOL_SIZE = process.env.UV_THREADPOOL_SIZE || 1;
|
|
30
37
|
process.env.UV_THREADPOOL_SIZE =
|
|
@@ -120,43 +127,40 @@ class Client_Oracledb extends Client_Oracle {
|
|
|
120
127
|
// Get a raw connection, called by the `pool` whenever a new
|
|
121
128
|
// connection needs to be added to the pool.
|
|
122
129
|
acquireRawConnection() {
|
|
123
|
-
|
|
124
|
-
const asyncConnection = new Promise(function (resolver, rejecter) {
|
|
130
|
+
return new Promise((resolver, rejecter) => {
|
|
125
131
|
// If external authentication don't have to worry about username/password and
|
|
126
132
|
// if not need to set the username and password
|
|
127
|
-
const oracleDbConfig =
|
|
128
|
-
? { externalAuth:
|
|
133
|
+
const oracleDbConfig = this.connectionSettings.externalAuth
|
|
134
|
+
? { externalAuth: this.connectionSettings.externalAuth }
|
|
129
135
|
: {
|
|
130
|
-
user:
|
|
131
|
-
password:
|
|
136
|
+
user: this.connectionSettings.user,
|
|
137
|
+
password: this.connectionSettings.password,
|
|
132
138
|
};
|
|
133
139
|
|
|
134
140
|
// In the case of external authentication connection string will be given
|
|
135
141
|
oracleDbConfig.connectString = resolveConnectString(
|
|
136
|
-
|
|
142
|
+
this.connectionSettings
|
|
137
143
|
);
|
|
138
144
|
|
|
139
|
-
if (
|
|
140
|
-
oracleDbConfig.prefetchRows =
|
|
141
|
-
client.connectionSettings.prefetchRowCount;
|
|
145
|
+
if (this.connectionSettings.prefetchRowCount) {
|
|
146
|
+
oracleDbConfig.prefetchRows = this.connectionSettings.prefetchRowCount;
|
|
142
147
|
}
|
|
143
148
|
|
|
144
|
-
if (
|
|
145
|
-
oracleDbConfig.stmtCacheSize =
|
|
149
|
+
if (this.connectionSettings.stmtCacheSize !== undefined) {
|
|
150
|
+
oracleDbConfig.stmtCacheSize = this.connectionSettings.stmtCacheSize;
|
|
146
151
|
}
|
|
147
152
|
|
|
148
|
-
|
|
153
|
+
this.driver.fetchAsString = this.fetchAsString;
|
|
149
154
|
|
|
150
|
-
|
|
155
|
+
this.driver.getConnection(oracleDbConfig, (err, connection) => {
|
|
151
156
|
if (err) {
|
|
152
157
|
return rejecter(err);
|
|
153
158
|
}
|
|
154
|
-
monkeyPatchConnection(connection,
|
|
159
|
+
monkeyPatchConnection(connection, this);
|
|
155
160
|
|
|
156
161
|
resolver(connection);
|
|
157
162
|
});
|
|
158
163
|
});
|
|
159
|
-
return asyncConnection;
|
|
160
164
|
}
|
|
161
165
|
|
|
162
166
|
// Used to explicitly close a connection, called internally by the pool
|
|
@@ -165,6 +169,39 @@ class Client_Oracledb extends Client_Oracle {
|
|
|
165
169
|
return connection.release();
|
|
166
170
|
}
|
|
167
171
|
|
|
172
|
+
// Handle oracle version resolution on acquiring connection from pool instead of connection creation.
|
|
173
|
+
// Must do this here since only the client used to create a connection would be updated with version
|
|
174
|
+
// information on creation. Poses a problem when knex instance is cloned since instances share the
|
|
175
|
+
// connection pool while having their own client instances.
|
|
176
|
+
async acquireConnection() {
|
|
177
|
+
const connection = await super.acquireConnection();
|
|
178
|
+
this.checkVersion(connection);
|
|
179
|
+
return connection;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// In Oracle, we need to check the version to dynamically determine
|
|
183
|
+
// certain limits. If user did not specify a version, get it from the connection.
|
|
184
|
+
checkVersion(connection) {
|
|
185
|
+
// Already determined version before?
|
|
186
|
+
if (this.version) {
|
|
187
|
+
return this.version;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const detectedVersion = parseVersion(connection.oracleServerVersionString);
|
|
191
|
+
if (!detectedVersion) {
|
|
192
|
+
// When original version is set to null, user-provided version was invalid and we fell-back to auto-detect.
|
|
193
|
+
// Otherwise, we couldn't auto-detect at all. Set error message accordingly.
|
|
194
|
+
throw new Error(
|
|
195
|
+
this.version === null
|
|
196
|
+
? 'Invalid Oracledb version number format passed to knex. Unable to successfully auto-detect as fallback. Please specify a valid oracledb version.'
|
|
197
|
+
: 'Unable to detect Oracledb version number automatically. Please specify the version in knex configuration.'
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
this.version = detectedVersion;
|
|
202
|
+
return detectedVersion;
|
|
203
|
+
}
|
|
204
|
+
|
|
168
205
|
// Runs the query on the specified connection, providing the bindings
|
|
169
206
|
// and any other necessary prep work.
|
|
170
207
|
_query(connection, obj) {
|
|
@@ -300,12 +337,29 @@ class Client_Oracledb extends Client_Oracle {
|
|
|
300
337
|
}
|
|
301
338
|
|
|
302
339
|
processPassedConnection(connection) {
|
|
340
|
+
this.checkVersion(connection);
|
|
303
341
|
monkeyPatchConnection(connection, this);
|
|
304
342
|
}
|
|
305
343
|
}
|
|
306
344
|
|
|
307
345
|
Client_Oracledb.prototype.driverName = 'oracledb';
|
|
308
346
|
|
|
347
|
+
function parseVersion(versionString) {
|
|
348
|
+
try {
|
|
349
|
+
// We only care about first two version components at most
|
|
350
|
+
const versionParts = versionString.split('.').slice(0, 2);
|
|
351
|
+
// Strip off any character suffixes in version number (ex. 12c => 12, 12.2c => 12.2)
|
|
352
|
+
versionParts.forEach((versionPart, idx) => {
|
|
353
|
+
versionParts[idx] = versionPart.replace(/\D$/, '');
|
|
354
|
+
});
|
|
355
|
+
const version = versionParts.join('.');
|
|
356
|
+
return version.match(/^\d+\.?\d*$/) ? version : null;
|
|
357
|
+
} catch (err) {
|
|
358
|
+
// Non-string versionString passed in.
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
309
363
|
function resolveConnectString(connectionSettings) {
|
|
310
364
|
if (connectionSettings.connectString) {
|
|
311
365
|
return connectionSettings.connectString;
|
|
@@ -194,7 +194,10 @@ class Client_PG extends Client {
|
|
|
194
194
|
|
|
195
195
|
return new Promise(function (resolver, rejecter) {
|
|
196
196
|
const queryStream = connection.query(
|
|
197
|
-
new PGQueryStream(sql, obj.bindings, options)
|
|
197
|
+
new PGQueryStream(sql, obj.bindings, options),
|
|
198
|
+
(err) => {
|
|
199
|
+
rejecter(err);
|
|
200
|
+
}
|
|
198
201
|
);
|
|
199
202
|
|
|
200
203
|
queryStream.on('error', function (error) {
|
|
@@ -219,6 +219,10 @@ class Transaction extends EventEmitter {
|
|
|
219
219
|
return makeTransactor(this, connection, trxClient);
|
|
220
220
|
})
|
|
221
221
|
.then((transactor) => {
|
|
222
|
+
this.transactor = transactor;
|
|
223
|
+
if (this.outerTx) {
|
|
224
|
+
transactor.parentTransaction = this.outerTx.transactor;
|
|
225
|
+
}
|
|
222
226
|
transactor.executionPromise = executionPromise;
|
|
223
227
|
|
|
224
228
|
// If we've returned a "thenable" from the transaction container, assume
|
|
@@ -1730,7 +1730,7 @@ Builder.prototype.andWhereRaw = Builder.prototype.whereRaw;
|
|
|
1730
1730
|
Builder.prototype.andWhereBetween = Builder.prototype.whereBetween;
|
|
1731
1731
|
Builder.prototype.andWhereNotBetween = Builder.prototype.whereNotBetween;
|
|
1732
1732
|
Builder.prototype.andWhereJsonObject = Builder.prototype.whereJsonObject;
|
|
1733
|
-
Builder.prototype.andWhereNotJsonObject = Builder.prototype.
|
|
1733
|
+
Builder.prototype.andWhereNotJsonObject = Builder.prototype.whereNotJsonObject;
|
|
1734
1734
|
Builder.prototype.andWhereJsonPath = Builder.prototype.whereJsonPath;
|
|
1735
1735
|
Builder.prototype.andWhereLike = Builder.prototype.whereLike;
|
|
1736
1736
|
Builder.prototype.andWhereILike = Builder.prototype.whereILike;
|
|
@@ -418,6 +418,12 @@ class TableCompiler {
|
|
|
418
418
|
.filter((c) => c.builder._type === 'increments')
|
|
419
419
|
.map((c) => c.builder._args[0]);
|
|
420
420
|
}
|
|
421
|
+
|
|
422
|
+
_getBigIncrementsColumnNames() {
|
|
423
|
+
return this.grouped.columns
|
|
424
|
+
.filter((c) => c.builder._type === 'bigincrements')
|
|
425
|
+
.map((c) => c.builder._args[0]);
|
|
426
|
+
}
|
|
421
427
|
}
|
|
422
428
|
|
|
423
429
|
TableCompiler.prototype.pushQuery = pushQuery;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knex",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "A batteries-included SQL query & schema builder for PostgresSQL, MySQL, CockroachDB, MSSQL and SQLite3",
|
|
5
5
|
"main": "knex",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
"debug:test": "mocha --inspect-brk --exit -t 0 test/all-tests-suite.js",
|
|
18
18
|
"debug:tape": "node --inspect-brk test/tape/index.js",
|
|
19
19
|
"coveralls": "nyc report --reporter=lcov",
|
|
20
|
-
"lint": "eslint --cache
|
|
21
|
-
"lint:fix": "eslint --cache --fix
|
|
22
|
-
"lint:types": "tsd
|
|
20
|
+
"lint": "eslint --cache .",
|
|
21
|
+
"lint:fix": "eslint --cache --fix .",
|
|
22
|
+
"lint:types": "tsd",
|
|
23
|
+
"lint:types:legacy": "dtslint types",
|
|
23
24
|
"lint:everything": "npm run lint && npm run lint:types",
|
|
24
25
|
"lint:fix:everything": "npm run lint:fix && npm run lint:types",
|
|
25
26
|
"test:unit": "npm run test:unit-only && npm run test:cli",
|
|
@@ -70,7 +71,7 @@
|
|
|
70
71
|
"getopts": "2.3.0",
|
|
71
72
|
"interpret": "^2.2.0",
|
|
72
73
|
"lodash": "^4.17.21",
|
|
73
|
-
"pg-connection-string": "2.6.
|
|
74
|
+
"pg-connection-string": "2.6.2",
|
|
74
75
|
"rechoir": "^0.8.0",
|
|
75
76
|
"resolve-from": "^5.0.0",
|
|
76
77
|
"tarn": "^3.0.2",
|
|
@@ -106,7 +107,7 @@
|
|
|
106
107
|
"devDependencies": {
|
|
107
108
|
"@tsconfig/recommended": "^1.0.1",
|
|
108
109
|
"@types/node": "^20.4.0",
|
|
109
|
-
"better-sqlite3": "^
|
|
110
|
+
"better-sqlite3": "^9.1.1",
|
|
110
111
|
"chai": "^4.3.6",
|
|
111
112
|
"chai-as-promised": "^7.1.1",
|
|
112
113
|
"chai-subset-in-order": "^3.1.0",
|
|
@@ -114,9 +115,9 @@
|
|
|
114
115
|
"coveralls": "^3.1.1",
|
|
115
116
|
"cross-env": "^7.0.3",
|
|
116
117
|
"dtslint": "4.2.1",
|
|
117
|
-
"eslint": "^8.
|
|
118
|
+
"eslint": "^8.54.0",
|
|
118
119
|
"eslint-config-prettier": "^8.6.0",
|
|
119
|
-
"eslint-plugin-import": "^2.
|
|
120
|
+
"eslint-plugin-import": "^2.29.0",
|
|
120
121
|
"eslint-plugin-mocha-no-only": "^1.1.1",
|
|
121
122
|
"eslint-plugin-prettier": "^4.2.1",
|
|
122
123
|
"husky": "^8.0.1",
|
|
@@ -132,14 +133,14 @@
|
|
|
132
133
|
"pg": "^8.8.0",
|
|
133
134
|
"pg-query-stream": "^4.2.4",
|
|
134
135
|
"prettier": "2.8.7",
|
|
135
|
-
"rimraf": "^
|
|
136
|
+
"rimraf": "^5.0.5",
|
|
136
137
|
"sinon": "^15.0.1",
|
|
137
138
|
"sinon-chai": "^3.7.0",
|
|
138
139
|
"source-map-support": "^0.5.21",
|
|
139
140
|
"sqlite3": "^5.0.11",
|
|
140
141
|
"tap-spec": "^5.0.0",
|
|
141
142
|
"tape": "^5.6.0",
|
|
142
|
-
"tedious": "^
|
|
143
|
+
"tedious": "^16.6.1",
|
|
143
144
|
"toxiproxy-node-client": "^2.0.6",
|
|
144
145
|
"ts-node": "^10.9.1",
|
|
145
146
|
"tsd": "^0.28.1",
|
package/types/index.d.ts
CHANGED
|
@@ -561,7 +561,7 @@ declare namespace Knex {
|
|
|
561
561
|
type ResolveTableType<
|
|
562
562
|
TCompositeTableType,
|
|
563
563
|
TScope extends TableInterfaceScope = 'base'
|
|
564
|
-
> = TCompositeTableType extends CompositeTableType<
|
|
564
|
+
> = TCompositeTableType extends CompositeTableType<{}>
|
|
565
565
|
? TCompositeTableType[TScope]
|
|
566
566
|
: TCompositeTableType;
|
|
567
567
|
|
|
@@ -734,6 +734,8 @@ declare namespace Knex {
|
|
|
734
734
|
orHavingNotIn: HavingRange<TRecord, TResult>;
|
|
735
735
|
havingNull: HavingNull<TRecord, TResult>;
|
|
736
736
|
havingNotNull: HavingNull<TRecord, TResult>;
|
|
737
|
+
orHavingNull: HavingNull<TRecord, TResult>;
|
|
738
|
+
orHavingNotNull: HavingNull<TRecord, TResult>;
|
|
737
739
|
|
|
738
740
|
// Clear
|
|
739
741
|
clearSelect(): QueryBuilder<
|
|
@@ -2321,6 +2323,7 @@ declare namespace Knex {
|
|
|
2321
2323
|
interface Transaction<TRecord extends {} = any, TResult = any[]>
|
|
2322
2324
|
extends Knex<TRecord, TResult> {
|
|
2323
2325
|
executionPromise: Promise<TResult>;
|
|
2326
|
+
parentTransaction?: Transaction;
|
|
2324
2327
|
isCompleted: () => boolean;
|
|
2325
2328
|
|
|
2326
2329
|
query<TRecord extends {} = any, TResult = void>(
|
|
@@ -3043,7 +3046,7 @@ declare namespace Knex {
|
|
|
3043
3046
|
host?: string;
|
|
3044
3047
|
connectionString?: string;
|
|
3045
3048
|
keepAlive?: boolean;
|
|
3046
|
-
stream?: stream.Duplex;
|
|
3049
|
+
stream?: () => stream.Duplex | stream.Duplex | undefined;
|
|
3047
3050
|
statement_timeout?: false | number;
|
|
3048
3051
|
parseInputDatesAsUTC?: boolean;
|
|
3049
3052
|
ssl?: boolean | ConnectionOptions;
|