knex 1.0.1 → 1.0.2
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 +24 -0
- package/UPGRADING.md +1 -1
- package/lib/dialects/better-sqlite3/index.js +1 -1
- package/lib/dialects/cockroachdb/crdb-querycompiler.js +5 -0
- package/lib/dialects/mssql/schema/mssql-compiler.js +3 -4
- package/lib/dialects/mysql/query/mysql-querycompiler.js +2 -0
- package/lib/dialects/mysql/schema/mysql-tablecompiler.js +5 -2
- package/lib/dialects/oracledb/query/oracledb-querycompiler.js +1 -16
- package/lib/dialects/postgres/query/pg-querybuilder.js +30 -0
- package/lib/dialects/postgres/query/pg-querycompiler.js +6 -4
- package/lib/dialects/postgres/schema/pg-tablecompiler.js +26 -17
- package/lib/dialects/sqlite3/index.js +5 -0
- package/lib/dialects/sqlite3/query/sqlite-querybuilder.js +33 -0
- package/lib/dialects/sqlite3/query/sqlite-querycompiler.js +2 -4
- package/lib/knex-builder/FunctionHelper.js +31 -16
- package/lib/migrations/migrate/Migrator.js +2 -1
- package/lib/query/querybuilder.js +62 -48
- package/lib/query/querycompiler.js +44 -5
- package/lib/schema/columnbuilder.js +6 -1
- package/lib/schema/tablecompiler.js +4 -4
- package/package.json +11 -14
- package/types/index.d.ts +10 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Master (Unreleased)
|
|
2
2
|
|
|
3
|
+
# 1.0.2 - 02 February, 2022
|
|
4
|
+
|
|
5
|
+
### New features:
|
|
6
|
+
|
|
7
|
+
- Support of MATERIALIZED and NOT MATERIALIZED with WITH/CTE #4940
|
|
8
|
+
- Add raw support in onConflict clause #4960
|
|
9
|
+
- Alter nullable constraint when alterNullable is set to true #4730
|
|
10
|
+
- Add alterType parameter for alter function #4967
|
|
11
|
+
- Support string json in json values #4988
|
|
12
|
+
- MySQL: add with clause #4508
|
|
13
|
+
|
|
14
|
+
### Bug fixes:
|
|
15
|
+
|
|
16
|
+
- Fix error message for missing migration files #4937
|
|
17
|
+
- Move deferrable to after on update/on delete #4976
|
|
18
|
+
- Do not use sys.tables to find if a table exists #2328
|
|
19
|
+
- PostgreSQL: Fix Order nulls #4989
|
|
20
|
+
- MySQL: Fix collation when renaming column #2666
|
|
21
|
+
- SQLite: Same boolean handling in better-sqlite3 as in sqlite3 #4982
|
|
22
|
+
|
|
23
|
+
### Typings:
|
|
24
|
+
|
|
25
|
+
- WhereILike - fix typo #4941
|
|
26
|
+
|
|
3
27
|
# 1.0.1 - 16 January, 2022
|
|
4
28
|
|
|
5
29
|
### Bug fixes:
|
package/UPGRADING.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
### Upgrading to version 1.0.0+
|
|
4
4
|
|
|
5
5
|
* Node.js older than 12 is no longer supported, make sure to update your environment;
|
|
6
|
-
* If you are using `sqlite3` driver, please replace it with `@vscode/sqlite3`;
|
|
6
|
+
* If you are using `sqlite3` driver dependency, please replace it with `@vscode/sqlite3` in your `package.json`;
|
|
7
7
|
* `RETURNING` operations now always return an object with column names;
|
|
8
8
|
* Migrator now returns list of migrations as objects.
|
|
9
9
|
|
|
@@ -28,6 +28,11 @@ class QueryCompiler_CRDB extends QueryCompiler_PG {
|
|
|
28
28
|
return body === '' ? '' : sql + body;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
_groupOrder(item, type) {
|
|
32
|
+
// CockroachDB don't support PostgreSQL order nulls first/last syntax, we take the generic one.
|
|
33
|
+
return this._basicGroupOrder(item, type);
|
|
34
|
+
}
|
|
35
|
+
|
|
31
36
|
whereJsonPath(statement) {
|
|
32
37
|
let castValue = '';
|
|
33
38
|
if (parseInt(statement.value)) {
|
|
@@ -45,14 +45,13 @@ class SchemaCompiler_MSSQL extends SchemaCompiler {
|
|
|
45
45
|
// Check whether a table exists on the query.
|
|
46
46
|
hasTable(tableName) {
|
|
47
47
|
const formattedTable = this.client.parameter(
|
|
48
|
-
|
|
48
|
+
prefixedTableName(this.schema, tableName),
|
|
49
49
|
this.builder,
|
|
50
50
|
this.bindingsHolder
|
|
51
51
|
);
|
|
52
|
-
|
|
53
52
|
const sql =
|
|
54
|
-
`
|
|
55
|
-
`
|
|
53
|
+
`SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES ` +
|
|
54
|
+
`WHERE TABLE_NAME = ${formattedTable}`;
|
|
56
55
|
this.pushQuery({ sql, output: (resp) => resp.length > 0 });
|
|
57
56
|
}
|
|
58
57
|
|
|
@@ -80,12 +80,14 @@ class QueryCompiler_MySQL extends QueryCompiler {
|
|
|
80
80
|
|
|
81
81
|
// Update method, including joins, wheres, order & limits.
|
|
82
82
|
update() {
|
|
83
|
+
const withSQL = this.with();
|
|
83
84
|
const join = this.join();
|
|
84
85
|
const updates = this._prepUpdate(this.single.update);
|
|
85
86
|
const where = this.where();
|
|
86
87
|
const order = this.order();
|
|
87
88
|
const limit = this.limit();
|
|
88
89
|
return (
|
|
90
|
+
withSQL +
|
|
89
91
|
`update ${this.tableName}` +
|
|
90
92
|
(join ? ` ${join}` : '') +
|
|
91
93
|
' set ' +
|
|
@@ -73,7 +73,7 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
73
73
|
|
|
74
74
|
this.pushQuery({
|
|
75
75
|
sql:
|
|
76
|
-
`show fields from ${table} where field = ` +
|
|
76
|
+
`show full fields from ${table} where field = ` +
|
|
77
77
|
this.client.parameter(from, this.tableBuilder, this.bindingsHolder),
|
|
78
78
|
output(resp) {
|
|
79
79
|
const column = resp[0];
|
|
@@ -101,7 +101,10 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
101
101
|
if (column.Default !== void 0 && column.Default !== null) {
|
|
102
102
|
sql += ` DEFAULT '${column.Default}'`;
|
|
103
103
|
}
|
|
104
|
-
|
|
104
|
+
if (column.Collation !== void 0 && column.Collation !== null) {
|
|
105
|
+
sql += ` COLLATE '${column.Collation}'`;
|
|
106
|
+
}
|
|
107
|
+
// Add back the auto increment if the column it, fix issue #2767
|
|
105
108
|
if (column.Extra == 'auto_increment') {
|
|
106
109
|
sql += ` AUTO_INCREMENT`;
|
|
107
110
|
}
|
|
@@ -8,9 +8,7 @@ const BlobHelper = require('../utils').BlobHelper;
|
|
|
8
8
|
const { isString } = require('../../../util/is');
|
|
9
9
|
const {
|
|
10
10
|
columnize: columnize_,
|
|
11
|
-
direction: direction_,
|
|
12
11
|
} = require('../../../formatter/wrappingFormatter');
|
|
13
|
-
const Raw = require('../../../raw');
|
|
14
12
|
|
|
15
13
|
class Oracledb_Compiler extends Oracle_Compiler {
|
|
16
14
|
// Compiles an "insert" query, allowing for multiple
|
|
@@ -318,20 +316,7 @@ class Oracledb_Compiler extends Oracle_Compiler {
|
|
|
318
316
|
}
|
|
319
317
|
|
|
320
318
|
_groupOrder(item, type) {
|
|
321
|
-
|
|
322
|
-
const direction =
|
|
323
|
-
type === 'order' && item.type !== 'orderByRaw'
|
|
324
|
-
? ` ${direction_(
|
|
325
|
-
item.direction,
|
|
326
|
-
this.builder,
|
|
327
|
-
this.client,
|
|
328
|
-
this.bindingsHolder
|
|
329
|
-
)}`
|
|
330
|
-
: '';
|
|
331
|
-
if (item.nulls && !(item.value instanceof Raw)) {
|
|
332
|
-
return `${column}${direction ? direction : ''} nulls ${item.nulls}`;
|
|
333
|
-
}
|
|
334
|
-
return column + direction;
|
|
319
|
+
return super._groupOrderNulls(item, type);
|
|
335
320
|
}
|
|
336
321
|
|
|
337
322
|
update() {
|
|
@@ -5,4 +5,34 @@ module.exports = class QueryBuilder_PostgreSQL extends QueryBuilder {
|
|
|
5
5
|
this._single.using = tables;
|
|
6
6
|
return this;
|
|
7
7
|
}
|
|
8
|
+
|
|
9
|
+
withMaterialized(alias, statementOrColumnList, nothingOrStatement) {
|
|
10
|
+
this._validateWithArgs(
|
|
11
|
+
alias,
|
|
12
|
+
statementOrColumnList,
|
|
13
|
+
nothingOrStatement,
|
|
14
|
+
'with'
|
|
15
|
+
);
|
|
16
|
+
return this.withWrapped(
|
|
17
|
+
alias,
|
|
18
|
+
statementOrColumnList,
|
|
19
|
+
nothingOrStatement,
|
|
20
|
+
true
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
withNotMaterialized(alias, statementOrColumnList, nothingOrStatement) {
|
|
25
|
+
this._validateWithArgs(
|
|
26
|
+
alias,
|
|
27
|
+
statementOrColumnList,
|
|
28
|
+
nothingOrStatement,
|
|
29
|
+
'with'
|
|
30
|
+
);
|
|
31
|
+
return this.withWrapped(
|
|
32
|
+
alias,
|
|
33
|
+
statementOrColumnList,
|
|
34
|
+
nothingOrStatement,
|
|
35
|
+
false
|
|
36
|
+
);
|
|
37
|
+
}
|
|
8
38
|
};
|
|
@@ -145,13 +145,11 @@ class QueryCompiler_PG extends QueryCompiler {
|
|
|
145
145
|
if (columns === true) {
|
|
146
146
|
return ' on conflict do nothing';
|
|
147
147
|
}
|
|
148
|
-
return ` on conflict
|
|
148
|
+
return ` on conflict ${this._onConflictClause(columns)} do nothing`;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
_merge(updates, columns, insert) {
|
|
152
|
-
let sql = ` on conflict
|
|
153
|
-
columns
|
|
154
|
-
)}) do update set `;
|
|
152
|
+
let sql = ` on conflict ${this._onConflictClause(columns)} do update set `;
|
|
155
153
|
if (updates && Array.isArray(updates)) {
|
|
156
154
|
sql += updates
|
|
157
155
|
.map((column) =>
|
|
@@ -219,6 +217,10 @@ class QueryCompiler_PG extends QueryCompiler {
|
|
|
219
217
|
return lockMode + (tables.length ? ' of ' + this._tableNames(tables) : '');
|
|
220
218
|
}
|
|
221
219
|
|
|
220
|
+
_groupOrder(item, type) {
|
|
221
|
+
return super._groupOrderNulls(item, type);
|
|
222
|
+
}
|
|
223
|
+
|
|
222
224
|
forUpdate() {
|
|
223
225
|
return this._lockingClause('for update');
|
|
224
226
|
}
|
|
@@ -91,21 +91,28 @@ class TableCompiler_PG extends TableCompiler {
|
|
|
91
91
|
|
|
92
92
|
// To alter enum columns they must be cast to text first
|
|
93
93
|
const isEnum = col.type === 'enu';
|
|
94
|
-
|
|
95
94
|
this.pushQuery({
|
|
96
95
|
sql: `alter table ${quotedTableName} alter column ${colName} drop default`,
|
|
97
96
|
bindings: [],
|
|
98
97
|
});
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
98
|
+
|
|
99
|
+
const alterNullable = col.columnBuilder.alterNullable;
|
|
100
|
+
if (alterNullable) {
|
|
101
|
+
this.pushQuery({
|
|
102
|
+
sql: `alter table ${quotedTableName} alter column ${colName} drop not null`,
|
|
103
|
+
bindings: [],
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const alterType = col.columnBuilder.alterType;
|
|
108
|
+
if (alterType) {
|
|
109
|
+
this.pushQuery({
|
|
110
|
+
sql: `alter table ${quotedTableName} alter column ${colName} type ${type} using (${colName}${
|
|
111
|
+
isEnum ? '::text::' : '::'
|
|
112
|
+
}${type})`,
|
|
113
|
+
bindings: [],
|
|
114
|
+
});
|
|
115
|
+
}
|
|
109
116
|
|
|
110
117
|
const defaultTo = col.modified['defaultTo'];
|
|
111
118
|
if (defaultTo) {
|
|
@@ -116,12 +123,14 @@ class TableCompiler_PG extends TableCompiler {
|
|
|
116
123
|
});
|
|
117
124
|
}
|
|
118
125
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
126
|
+
if (alterNullable) {
|
|
127
|
+
const nullable = col.modified['nullable'];
|
|
128
|
+
if (nullable && nullable[0] === false) {
|
|
129
|
+
this.pushQuery({
|
|
130
|
+
sql: `alter table ${quotedTableName} alter column ${colName} set not null`,
|
|
131
|
+
bindings: [],
|
|
132
|
+
});
|
|
133
|
+
}
|
|
125
134
|
}
|
|
126
135
|
}
|
|
127
136
|
|
|
@@ -15,6 +15,7 @@ const TableCompiler = require('./schema/sqlite-tablecompiler');
|
|
|
15
15
|
const ViewCompiler = require('./schema/sqlite-viewcompiler');
|
|
16
16
|
const SQLite3_DDL = require('./schema/ddl');
|
|
17
17
|
const Formatter = require('../../formatter');
|
|
18
|
+
const QueryBuilder = require('./query/sqlite-querybuilder');
|
|
18
19
|
|
|
19
20
|
class Client_SQLite3 extends Client {
|
|
20
21
|
constructor(config) {
|
|
@@ -44,6 +45,10 @@ class Client_SQLite3 extends Client {
|
|
|
44
45
|
return new SqliteQueryCompiler(this, builder, formatter);
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
queryBuilder() {
|
|
49
|
+
return new QueryBuilder(this);
|
|
50
|
+
}
|
|
51
|
+
|
|
47
52
|
viewCompiler(builder, formatter) {
|
|
48
53
|
return new ViewCompiler(this, builder, formatter);
|
|
49
54
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const QueryBuilder = require('../../../query/querybuilder.js');
|
|
2
|
+
|
|
3
|
+
module.exports = class QueryBuilder_SQLite3 extends QueryBuilder {
|
|
4
|
+
withMaterialized(alias, statementOrColumnList, nothingOrStatement) {
|
|
5
|
+
this._validateWithArgs(
|
|
6
|
+
alias,
|
|
7
|
+
statementOrColumnList,
|
|
8
|
+
nothingOrStatement,
|
|
9
|
+
'with'
|
|
10
|
+
);
|
|
11
|
+
return this.withWrapped(
|
|
12
|
+
alias,
|
|
13
|
+
statementOrColumnList,
|
|
14
|
+
nothingOrStatement,
|
|
15
|
+
true
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
withNotMaterialized(alias, statementOrColumnList, nothingOrStatement) {
|
|
20
|
+
this._validateWithArgs(
|
|
21
|
+
alias,
|
|
22
|
+
statementOrColumnList,
|
|
23
|
+
nothingOrStatement,
|
|
24
|
+
'with'
|
|
25
|
+
);
|
|
26
|
+
return this.withWrapped(
|
|
27
|
+
alias,
|
|
28
|
+
statementOrColumnList,
|
|
29
|
+
nothingOrStatement,
|
|
30
|
+
false
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
@@ -153,13 +153,11 @@ class QueryCompiler_SQLite3 extends QueryCompiler {
|
|
|
153
153
|
if (columns === true) {
|
|
154
154
|
return ' on conflict do nothing';
|
|
155
155
|
}
|
|
156
|
-
return ` on conflict
|
|
156
|
+
return ` on conflict ${this._onConflictClause(columns)} do nothing`;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
_merge(updates, columns, insert) {
|
|
160
|
-
let sql = ` on conflict
|
|
161
|
-
columns
|
|
162
|
-
)}) do update set `;
|
|
160
|
+
let sql = ` on conflict ${this._onConflictClause(columns)} do update set `;
|
|
163
161
|
if (updates && Array.isArray(updates)) {
|
|
164
162
|
sql += updates
|
|
165
163
|
.map((column) =>
|
|
@@ -14,25 +14,40 @@ class FunctionHelper {
|
|
|
14
14
|
return this.client.raw('CURRENT_TIMESTAMP');
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
uuidToBin(uuid) {
|
|
17
|
+
uuidToBin(uuid, ordered = true) {
|
|
18
18
|
const buf = Buffer.from(uuid.replace(/-/g, ''), 'hex');
|
|
19
|
-
return
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
return ordered
|
|
20
|
+
? Buffer.concat([
|
|
21
|
+
buf.slice(6, 8),
|
|
22
|
+
buf.slice(4, 6),
|
|
23
|
+
buf.slice(0, 4),
|
|
24
|
+
buf.slice(8, 16),
|
|
25
|
+
])
|
|
26
|
+
: Buffer.concat([
|
|
27
|
+
buf.slice(0, 4),
|
|
28
|
+
buf.slice(4, 6),
|
|
29
|
+
buf.slice(6, 8),
|
|
30
|
+
buf.slice(8, 16),
|
|
31
|
+
]);
|
|
25
32
|
}
|
|
26
33
|
|
|
27
|
-
binToUuid(bin) {
|
|
28
|
-
const buf =
|
|
29
|
-
return
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
binToUuid(bin, ordered = true) {
|
|
35
|
+
const buf = Buffer.from(bin, 'hex');
|
|
36
|
+
return ordered
|
|
37
|
+
? [
|
|
38
|
+
buf.toString('hex', 4, 8),
|
|
39
|
+
buf.toString('hex', 2, 4),
|
|
40
|
+
buf.toString('hex', 0, 2),
|
|
41
|
+
buf.toString('hex', 8, 10),
|
|
42
|
+
buf.toString('hex', 10, 16),
|
|
43
|
+
].join('-')
|
|
44
|
+
: [
|
|
45
|
+
buf.toString('hex', 0, 4),
|
|
46
|
+
buf.toString('hex', 4, 6),
|
|
47
|
+
buf.toString('hex', 6, 8),
|
|
48
|
+
buf.toString('hex', 8, 10),
|
|
49
|
+
buf.toString('hex', 10, 16),
|
|
50
|
+
].join('-');
|
|
36
51
|
}
|
|
37
52
|
}
|
|
38
53
|
|
|
@@ -562,8 +562,9 @@ function validateMigrationList(migrationSource, migrations) {
|
|
|
562
562
|
const [all, completed] = migrations;
|
|
563
563
|
const diff = getMissingMigrations(migrationSource, completed, all);
|
|
564
564
|
if (!isEmpty(diff)) {
|
|
565
|
+
const names = diff.map((d) => d.name);
|
|
565
566
|
throw new Error(
|
|
566
|
-
`The migration directory is corrupt, the following files are missing: ${
|
|
567
|
+
`The migration directory is corrupt, the following files are missing: ${names.join(
|
|
567
568
|
', '
|
|
568
569
|
)}`
|
|
569
570
|
);
|
|
@@ -118,25 +118,82 @@ class Builder extends EventEmitter {
|
|
|
118
118
|
|
|
119
119
|
// With
|
|
120
120
|
// ------
|
|
121
|
+
isValidStatementArg(statement) {
|
|
122
|
+
return (
|
|
123
|
+
typeof statement === 'function' ||
|
|
124
|
+
statement instanceof Builder ||
|
|
125
|
+
(statement && statement.isRawInstance)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
_validateWithArgs(alias, statementOrColumnList, nothingOrStatement, method) {
|
|
130
|
+
const [query, columnList] =
|
|
131
|
+
typeof nothingOrStatement === 'undefined'
|
|
132
|
+
? [statementOrColumnList, undefined]
|
|
133
|
+
: [nothingOrStatement, statementOrColumnList];
|
|
134
|
+
if (typeof alias !== 'string') {
|
|
135
|
+
throw new Error(`${method}() first argument must be a string`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (this.isValidStatementArg(query) && typeof columnList === 'undefined') {
|
|
139
|
+
// Validated as two-arg variant (alias, statement).
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Attempt to interpret as three-arg variant (alias, columnList, statement).
|
|
144
|
+
const isNonEmptyNameList =
|
|
145
|
+
Array.isArray(columnList) &&
|
|
146
|
+
columnList.length > 0 &&
|
|
147
|
+
columnList.every((it) => typeof it === 'string');
|
|
148
|
+
if (!isNonEmptyNameList) {
|
|
149
|
+
throw new Error(
|
|
150
|
+
`${method}() second argument must be a statement or non-empty column name list.`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (this.isValidStatementArg(query)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
throw new Error(
|
|
158
|
+
`${method}() third argument must be a function / QueryBuilder or a raw when its second argument is a column name list`
|
|
159
|
+
);
|
|
160
|
+
}
|
|
121
161
|
|
|
122
162
|
with(alias, statementOrColumnList, nothingOrStatement) {
|
|
123
|
-
|
|
163
|
+
this._validateWithArgs(
|
|
164
|
+
alias,
|
|
165
|
+
statementOrColumnList,
|
|
166
|
+
nothingOrStatement,
|
|
167
|
+
'with'
|
|
168
|
+
);
|
|
124
169
|
return this.withWrapped(alias, statementOrColumnList, nothingOrStatement);
|
|
125
170
|
}
|
|
126
171
|
|
|
172
|
+
withMaterialized(alias, statementOrColumnList, nothingOrStatement) {
|
|
173
|
+
throw new Error('With materialized is not supported by this dialect');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
withNotMaterialized(alias, statementOrColumnList, nothingOrStatement) {
|
|
177
|
+
throw new Error('With materialized is not supported by this dialect');
|
|
178
|
+
}
|
|
179
|
+
|
|
127
180
|
// Helper for compiling any advanced `with` queries.
|
|
128
|
-
withWrapped(alias, statementOrColumnList, nothingOrStatement) {
|
|
181
|
+
withWrapped(alias, statementOrColumnList, nothingOrStatement, materialized) {
|
|
129
182
|
const [query, columnList] =
|
|
130
183
|
typeof nothingOrStatement === 'undefined'
|
|
131
184
|
? [statementOrColumnList, undefined]
|
|
132
185
|
: [nothingOrStatement, statementOrColumnList];
|
|
133
|
-
|
|
186
|
+
const statement = {
|
|
134
187
|
grouping: 'with',
|
|
135
188
|
type: 'withWrapped',
|
|
136
189
|
alias: alias,
|
|
137
190
|
columnList,
|
|
138
191
|
value: query,
|
|
139
|
-
}
|
|
192
|
+
};
|
|
193
|
+
if (materialized !== undefined) {
|
|
194
|
+
statement.materialized = materialized;
|
|
195
|
+
}
|
|
196
|
+
this._statements.push(statement);
|
|
140
197
|
return this;
|
|
141
198
|
}
|
|
142
199
|
|
|
@@ -144,7 +201,7 @@ class Builder extends EventEmitter {
|
|
|
144
201
|
// ------
|
|
145
202
|
|
|
146
203
|
withRecursive(alias, statementOrColumnList, nothingOrStatement) {
|
|
147
|
-
|
|
204
|
+
this._validateWithArgs(
|
|
148
205
|
alias,
|
|
149
206
|
statementOrColumnList,
|
|
150
207
|
nothingOrStatement,
|
|
@@ -1656,49 +1713,6 @@ class Builder extends EventEmitter {
|
|
|
1656
1713
|
}
|
|
1657
1714
|
}
|
|
1658
1715
|
|
|
1659
|
-
const isValidStatementArg = (statement) =>
|
|
1660
|
-
typeof statement === 'function' ||
|
|
1661
|
-
statement instanceof Builder ||
|
|
1662
|
-
(statement && statement.isRawInstance);
|
|
1663
|
-
|
|
1664
|
-
const validateWithArgs = function (
|
|
1665
|
-
alias,
|
|
1666
|
-
statementOrColumnList,
|
|
1667
|
-
nothingOrStatement,
|
|
1668
|
-
method
|
|
1669
|
-
) {
|
|
1670
|
-
const [query, columnList] =
|
|
1671
|
-
typeof nothingOrStatement === 'undefined'
|
|
1672
|
-
? [statementOrColumnList, undefined]
|
|
1673
|
-
: [nothingOrStatement, statementOrColumnList];
|
|
1674
|
-
if (typeof alias !== 'string') {
|
|
1675
|
-
throw new Error(`${method}() first argument must be a string`);
|
|
1676
|
-
}
|
|
1677
|
-
|
|
1678
|
-
if (isValidStatementArg(query) && typeof columnList === 'undefined') {
|
|
1679
|
-
// Validated as two-arg variant (alias, statement).
|
|
1680
|
-
return;
|
|
1681
|
-
}
|
|
1682
|
-
|
|
1683
|
-
// Attempt to interpret as three-arg variant (alias, columnList, statement).
|
|
1684
|
-
const isNonEmptyNameList =
|
|
1685
|
-
Array.isArray(columnList) &&
|
|
1686
|
-
columnList.length > 0 &&
|
|
1687
|
-
columnList.every((it) => typeof it === 'string');
|
|
1688
|
-
if (!isNonEmptyNameList) {
|
|
1689
|
-
throw new Error(
|
|
1690
|
-
`${method}() second argument must be a statement or non-empty column name list.`
|
|
1691
|
-
);
|
|
1692
|
-
}
|
|
1693
|
-
|
|
1694
|
-
if (isValidStatementArg(query)) {
|
|
1695
|
-
return;
|
|
1696
|
-
}
|
|
1697
|
-
throw new Error(
|
|
1698
|
-
`${method}() third argument must be a function / QueryBuilder or a raw when its second argument is a column name list`
|
|
1699
|
-
);
|
|
1700
|
-
};
|
|
1701
|
-
|
|
1702
1716
|
Builder.prototype.select = Builder.prototype.columns;
|
|
1703
1717
|
Builder.prototype.column = Builder.prototype.columns;
|
|
1704
1718
|
Builder.prototype.andWhereNot = Builder.prototype.whereNot;
|
|
@@ -149,6 +149,12 @@ class QueryCompiler {
|
|
|
149
149
|
return body === '' ? '' : sql + body;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
_onConflictClause(columns) {
|
|
153
|
+
return columns instanceof Raw
|
|
154
|
+
? this.formatter.wrap(columns)
|
|
155
|
+
: `(${this.formatter.columnize(columns)})`;
|
|
156
|
+
}
|
|
157
|
+
|
|
152
158
|
_buildInsertValues(insertData) {
|
|
153
159
|
let sql = '';
|
|
154
160
|
let i = -1;
|
|
@@ -1070,10 +1076,14 @@ class QueryCompiler {
|
|
|
1070
1076
|
}
|
|
1071
1077
|
|
|
1072
1078
|
_jsonWrapValue(jsonValue) {
|
|
1073
|
-
if (this.builder._isJsonObject(jsonValue)) {
|
|
1074
|
-
|
|
1079
|
+
if (!this.builder._isJsonObject(jsonValue)) {
|
|
1080
|
+
try {
|
|
1081
|
+
return JSON.stringify(JSON.parse(jsonValue.replace(/\n|\t/g, '')));
|
|
1082
|
+
} catch (e) {
|
|
1083
|
+
return jsonValue;
|
|
1084
|
+
}
|
|
1075
1085
|
}
|
|
1076
|
-
return jsonValue;
|
|
1086
|
+
return JSON.stringify(jsonValue);
|
|
1077
1087
|
}
|
|
1078
1088
|
|
|
1079
1089
|
_jsonValueClause(statement) {
|
|
@@ -1170,6 +1180,12 @@ class QueryCompiler {
|
|
|
1170
1180
|
) +
|
|
1171
1181
|
')'
|
|
1172
1182
|
: '';
|
|
1183
|
+
const materialized =
|
|
1184
|
+
statement.materialized === undefined
|
|
1185
|
+
? ''
|
|
1186
|
+
: statement.materialized
|
|
1187
|
+
? 'materialized '
|
|
1188
|
+
: 'not materialized ';
|
|
1173
1189
|
return (
|
|
1174
1190
|
(val &&
|
|
1175
1191
|
columnize_(
|
|
@@ -1179,7 +1195,9 @@ class QueryCompiler {
|
|
|
1179
1195
|
this.bindingsHolder
|
|
1180
1196
|
) +
|
|
1181
1197
|
columnList +
|
|
1182
|
-
' as
|
|
1198
|
+
' as ' +
|
|
1199
|
+
materialized +
|
|
1200
|
+
'(' +
|
|
1183
1201
|
val +
|
|
1184
1202
|
')') ||
|
|
1185
1203
|
''
|
|
@@ -1325,7 +1343,7 @@ class QueryCompiler {
|
|
|
1325
1343
|
return groupOrder;
|
|
1326
1344
|
}
|
|
1327
1345
|
|
|
1328
|
-
|
|
1346
|
+
_basicGroupOrder(item, type) {
|
|
1329
1347
|
const column = this._formatGroupsItemValue(item.value, item.nulls);
|
|
1330
1348
|
const direction =
|
|
1331
1349
|
type === 'order' && item.type !== 'orderByRaw'
|
|
@@ -1339,6 +1357,27 @@ class QueryCompiler {
|
|
|
1339
1357
|
return column + direction;
|
|
1340
1358
|
}
|
|
1341
1359
|
|
|
1360
|
+
_groupOrder(item, type) {
|
|
1361
|
+
return this._basicGroupOrder(item, type);
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
_groupOrderNulls(item, type) {
|
|
1365
|
+
const column = this._formatGroupsItemValue(item.value);
|
|
1366
|
+
const direction =
|
|
1367
|
+
type === 'order' && item.type !== 'orderByRaw'
|
|
1368
|
+
? ` ${direction_(
|
|
1369
|
+
item.direction,
|
|
1370
|
+
this.builder,
|
|
1371
|
+
this.client,
|
|
1372
|
+
this.bindingsHolder
|
|
1373
|
+
)}`
|
|
1374
|
+
: '';
|
|
1375
|
+
if (item.nulls && !(item.value instanceof Raw)) {
|
|
1376
|
+
return `${column}${direction ? direction : ''} nulls ${item.nulls}`;
|
|
1377
|
+
}
|
|
1378
|
+
return column + direction;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1342
1381
|
// Compiles the `order by` statements.
|
|
1343
1382
|
_groupsOrders(type) {
|
|
1344
1383
|
const items = this.grouped[type];
|
|
@@ -110,8 +110,13 @@ AlterMethods.alterType = function (type) {
|
|
|
110
110
|
};
|
|
111
111
|
|
|
112
112
|
// Set column method to alter (default is add).
|
|
113
|
-
AlterMethods.alter = function (
|
|
113
|
+
AlterMethods.alter = function ({
|
|
114
|
+
alterNullable = true,
|
|
115
|
+
alterType = true,
|
|
116
|
+
} = {}) {
|
|
114
117
|
this._method = 'alter';
|
|
118
|
+
this.alterNullable = alterNullable;
|
|
119
|
+
this.alterType = alterType;
|
|
115
120
|
|
|
116
121
|
return this;
|
|
117
122
|
};
|
|
@@ -127,9 +127,9 @@ class TableCompiler {
|
|
|
127
127
|
' (' +
|
|
128
128
|
references +
|
|
129
129
|
')' +
|
|
130
|
-
deferrable +
|
|
131
130
|
onUpdate +
|
|
132
|
-
onDelete
|
|
131
|
+
onDelete +
|
|
132
|
+
deferrable
|
|
133
133
|
);
|
|
134
134
|
} else {
|
|
135
135
|
this.pushQuery(
|
|
@@ -144,9 +144,9 @@ class TableCompiler {
|
|
|
144
144
|
' (' +
|
|
145
145
|
references +
|
|
146
146
|
')' +
|
|
147
|
-
deferrable +
|
|
148
147
|
onUpdate +
|
|
149
|
-
onDelete
|
|
148
|
+
onDelete +
|
|
149
|
+
deferrable
|
|
150
150
|
);
|
|
151
151
|
}
|
|
152
152
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knex",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
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",
|
|
@@ -84,9 +84,6 @@
|
|
|
84
84
|
"pg-native": {
|
|
85
85
|
"optional": true
|
|
86
86
|
},
|
|
87
|
-
"sqlite3": {
|
|
88
|
-
"optional": true
|
|
89
|
-
},
|
|
90
87
|
"@vscode/sqlite3": {
|
|
91
88
|
"optional": true
|
|
92
89
|
},
|
|
@@ -101,24 +98,24 @@
|
|
|
101
98
|
]
|
|
102
99
|
},
|
|
103
100
|
"devDependencies": {
|
|
104
|
-
"@types/node": "^16.11.
|
|
101
|
+
"@types/node": "^16.11.22",
|
|
105
102
|
"@vscode/sqlite3": "^5.0.7",
|
|
106
|
-
"better-sqlite3": "^7.
|
|
107
|
-
"chai": "^4.3.
|
|
103
|
+
"better-sqlite3": "^7.5.0",
|
|
104
|
+
"chai": "^4.3.6",
|
|
108
105
|
"chai-as-promised": "^7.1.1",
|
|
109
106
|
"chai-subset-in-order": "^3.1.0",
|
|
110
107
|
"cli-testlab": "^2.2.0",
|
|
111
108
|
"coveralls": "^3.1.1",
|
|
112
109
|
"cross-env": "^7.0.3",
|
|
113
110
|
"dtslint": "4.2.1",
|
|
114
|
-
"eslint": "^8.
|
|
111
|
+
"eslint": "^8.8.0",
|
|
115
112
|
"eslint-config-prettier": "^8.3.0",
|
|
116
|
-
"eslint-plugin-import": "^2.25.
|
|
113
|
+
"eslint-plugin-import": "^2.25.4",
|
|
117
114
|
"husky": "^4.3.8",
|
|
118
115
|
"jake": "^8.1.1",
|
|
119
116
|
"JSONStream": "^1.3.5",
|
|
120
117
|
"lint-staged": "^11.1.2",
|
|
121
|
-
"mocha": "^9.
|
|
118
|
+
"mocha": "^9.2.0",
|
|
122
119
|
"mock-fs": "^5.1.2",
|
|
123
120
|
"mysql": "^2.18.1",
|
|
124
121
|
"mysql2": "^2.3.3",
|
|
@@ -128,16 +125,16 @@
|
|
|
128
125
|
"pg-query-stream": "^4.2.1",
|
|
129
126
|
"prettier": "2.4.1",
|
|
130
127
|
"rimraf": "^3.0.2",
|
|
131
|
-
"sinon": "^
|
|
128
|
+
"sinon": "^13.0.1",
|
|
132
129
|
"sinon-chai": "^3.7.0",
|
|
133
130
|
"source-map-support": "^0.5.21",
|
|
134
131
|
"tap-spec": "^5.0.0",
|
|
135
|
-
"tape": "^5.
|
|
136
|
-
"tedious": "^12.
|
|
132
|
+
"tape": "^5.5.0",
|
|
133
|
+
"tedious": "^12.3.0",
|
|
137
134
|
"toxiproxy-node-client": "^2.0.6",
|
|
138
135
|
"ts-node": "^10.4.0",
|
|
139
136
|
"tsd": "^0.19.1",
|
|
140
|
-
"typescript": "4.5.
|
|
137
|
+
"typescript": "4.5.5"
|
|
141
138
|
},
|
|
142
139
|
"buildDependencies": [
|
|
143
140
|
"rimraf"
|
package/types/index.d.ts
CHANGED
|
@@ -520,6 +520,8 @@ export declare namespace Knex {
|
|
|
520
520
|
|
|
521
521
|
// Withs
|
|
522
522
|
with: With<TRecord, TResult>;
|
|
523
|
+
withMaterialized: With<TRecord, TResult>;
|
|
524
|
+
withNotMaterialized: With<TRecord, TResult>;
|
|
523
525
|
withRecursive: With<TRecord, TResult>;
|
|
524
526
|
withRaw: WithRaw<TRecord, TResult>;
|
|
525
527
|
withSchema: WithSchema<TRecord, TResult>;
|
|
@@ -546,7 +548,7 @@ export declare namespace Knex {
|
|
|
546
548
|
whereNotIn: WhereIn<TRecord, TResult>;
|
|
547
549
|
orWhereNotIn: WhereIn<TRecord, TResult>;
|
|
548
550
|
whereLike: Where<TRecord, TResult>;
|
|
549
|
-
|
|
551
|
+
whereILike: Where<TRecord, TResult>;
|
|
550
552
|
whereNull: WhereNull<TRecord, TResult>;
|
|
551
553
|
orWhereNull: WhereNull<TRecord, TResult>;
|
|
552
554
|
whereNotNull: WhereNull<TRecord, TResult>;
|
|
@@ -977,6 +979,10 @@ export declare namespace Knex {
|
|
|
977
979
|
columns: string[]
|
|
978
980
|
): OnConflictQueryBuilder<TRecord, TResult>;
|
|
979
981
|
|
|
982
|
+
onConflict(
|
|
983
|
+
raw: Raw
|
|
984
|
+
): OnConflictQueryBuilder<TRecord, TResult>;
|
|
985
|
+
|
|
980
986
|
onConflict(): OnConflictQueryBuilder<TRecord, TResult>;
|
|
981
987
|
|
|
982
988
|
del(
|
|
@@ -2204,7 +2210,7 @@ export declare namespace Knex {
|
|
|
2204
2210
|
notNullable(): ColumnBuilder;
|
|
2205
2211
|
nullable(): ColumnBuilder;
|
|
2206
2212
|
comment(value: string): ColumnBuilder;
|
|
2207
|
-
alter(): ColumnBuilder;
|
|
2213
|
+
alter(options: Readonly<{alterNullable?: boolean, alterType?: boolean}>): ColumnBuilder;
|
|
2208
2214
|
queryContext(context: any): ColumnBuilder;
|
|
2209
2215
|
after(columnName: string): ColumnBuilder;
|
|
2210
2216
|
first(): ColumnBuilder;
|
|
@@ -2717,6 +2723,8 @@ export declare namespace Knex {
|
|
|
2717
2723
|
|
|
2718
2724
|
interface FunctionHelper {
|
|
2719
2725
|
now(precision?: number): Raw;
|
|
2726
|
+
uuidToBin(uuid: string, ordered?: boolean): Buffer;
|
|
2727
|
+
binToUuid(bin: Buffer, ordered?: boolean): string;
|
|
2720
2728
|
}
|
|
2721
2729
|
|
|
2722
2730
|
interface EnumOptions {
|