knex 3.2.3 → 3.2.4
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 +2447 -2441
- package/CONTRIBUTING.md +190 -190
- package/LICENSE +22 -22
- package/README.md +156 -156
- package/UPGRADING.md +245 -245
- package/bin/cli.js +516 -516
- package/bin/knexfile-runtime-error.js +27 -27
- package/bin/utils/cli-config-utils.js +217 -217
- package/bin/utils/constants.js +7 -7
- package/bin/utils/migrationsLister.js +37 -37
- package/knex.js +23 -23
- package/knex.mjs +11 -11
- package/lib/builder-interface-augmenter.js +120 -120
- package/lib/client.js +585 -585
- package/lib/constants.js +61 -61
- package/lib/dialects/better-sqlite3/index.js +101 -101
- package/lib/dialects/cockroachdb/crdb-columncompiler.js +14 -14
- package/lib/dialects/cockroachdb/crdb-querybuilder.js +11 -11
- package/lib/dialects/cockroachdb/crdb-querycompiler.js +122 -122
- package/lib/dialects/cockroachdb/crdb-tablecompiler.js +46 -46
- package/lib/dialects/cockroachdb/crdb-viewcompiler.js +15 -15
- package/lib/dialects/cockroachdb/index.js +86 -86
- package/lib/dialects/index.js +34 -34
- package/lib/dialects/mssql/index.js +498 -498
- package/lib/dialects/mssql/mssql-formatter.js +34 -34
- package/lib/dialects/mssql/query/mssql-querycompiler.js +601 -601
- package/lib/dialects/mssql/schema/mssql-columncompiler.js +185 -185
- package/lib/dialects/mssql/schema/mssql-compiler.js +91 -91
- package/lib/dialects/mssql/schema/mssql-tablecompiler.js +393 -393
- package/lib/dialects/mssql/schema/mssql-viewcompiler.js +55 -55
- package/lib/dialects/mssql/transaction.js +176 -176
- package/lib/dialects/mysql/index.js +317 -317
- package/lib/dialects/mysql/query/mysql-querybuilder.js +14 -14
- package/lib/dialects/mysql/query/mysql-querycompiler.js +292 -292
- package/lib/dialects/mysql/schema/mysql-columncompiler.js +193 -193
- package/lib/dialects/mysql/schema/mysql-compiler.js +60 -60
- package/lib/dialects/mysql/schema/mysql-tablecompiler.js +426 -426
- package/lib/dialects/mysql/schema/mysql-viewbuilder.js +21 -21
- package/lib/dialects/mysql/schema/mysql-viewcompiler.js +15 -15
- package/lib/dialects/mysql/transaction.js +46 -46
- package/lib/dialects/mysql2/index.js +53 -53
- package/lib/dialects/mysql2/transaction.js +44 -44
- package/lib/dialects/oracle/DEAD_CODE.md +5 -5
- package/lib/dialects/oracle/index.js +92 -92
- package/lib/dialects/oracle/query/oracle-querycompiler.js +343 -343
- package/lib/dialects/oracle/schema/internal/incrementUtils.js +22 -22
- package/lib/dialects/oracle/schema/internal/trigger.js +155 -155
- package/lib/dialects/oracle/schema/oracle-columnbuilder.js +17 -17
- package/lib/dialects/oracle/schema/oracle-columncompiler.js +126 -126
- package/lib/dialects/oracle/schema/oracle-compiler.js +124 -124
- package/lib/dialects/oracle/schema/oracle-tablecompiler.js +210 -210
- package/lib/dialects/oracle/utils.js +107 -107
- package/lib/dialects/oracledb/index.js +381 -381
- package/lib/dialects/oracledb/query/oracledb-querycompiler.js +481 -481
- package/lib/dialects/oracledb/schema/oracledb-columncompiler.js +61 -61
- package/lib/dialects/oracledb/schema/oracledb-tablecompiler.js +19 -19
- package/lib/dialects/oracledb/schema/oracledb-viewbuilder.js +13 -13
- package/lib/dialects/oracledb/schema/oracledb-viewcompiler.js +19 -19
- package/lib/dialects/oracledb/transaction.js +98 -98
- package/lib/dialects/oracledb/utils.js +208 -208
- package/lib/dialects/pgnative/index.js +60 -60
- package/lib/dialects/postgres/execution/pg-transaction.js +19 -19
- package/lib/dialects/postgres/index.js +373 -373
- package/lib/dialects/postgres/query/pg-querybuilder.js +43 -43
- package/lib/dialects/postgres/query/pg-querycompiler.js +400 -400
- package/lib/dialects/postgres/schema/pg-columncompiler.js +162 -162
- package/lib/dialects/postgres/schema/pg-compiler.js +138 -138
- package/lib/dialects/postgres/schema/pg-tablecompiler.js +331 -331
- package/lib/dialects/postgres/schema/pg-viewbuilder.js +21 -21
- package/lib/dialects/postgres/schema/pg-viewcompiler.js +35 -35
- package/lib/dialects/redshift/index.js +86 -86
- package/lib/dialects/redshift/query/redshift-querycompiler.js +163 -163
- package/lib/dialects/redshift/schema/redshift-columnbuilder.js +22 -22
- package/lib/dialects/redshift/schema/redshift-columncompiler.js +67 -67
- package/lib/dialects/redshift/schema/redshift-compiler.js +14 -14
- package/lib/dialects/redshift/schema/redshift-tablecompiler.js +134 -134
- package/lib/dialects/redshift/schema/redshift-viewcompiler.js +11 -11
- package/lib/dialects/redshift/transaction.js +32 -32
- package/lib/dialects/sqlite3/execution/sqlite-transaction.js +172 -172
- package/lib/dialects/sqlite3/index.js +263 -263
- package/lib/dialects/sqlite3/query/sqlite-querybuilder.js +33 -33
- package/lib/dialects/sqlite3/query/sqlite-querycompiler.js +341 -341
- package/lib/dialects/sqlite3/schema/ddl.js +380 -380
- package/lib/dialects/sqlite3/schema/internal/compiler.js +327 -327
- package/lib/dialects/sqlite3/schema/internal/parser-combinator.js +161 -161
- package/lib/dialects/sqlite3/schema/internal/parser.js +638 -638
- package/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js +41 -41
- package/lib/dialects/sqlite3/schema/internal/tokenizer.js +38 -38
- package/lib/dialects/sqlite3/schema/internal/utils.js +12 -12
- package/lib/dialects/sqlite3/schema/sqlite-columncompiler.js +50 -50
- package/lib/dialects/sqlite3/schema/sqlite-compiler.js +80 -80
- package/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js +364 -364
- package/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js +40 -40
- package/lib/execution/batch-insert.js +51 -51
- package/lib/execution/internal/delay.js +6 -6
- package/lib/execution/internal/ensure-connection-callback.js +41 -41
- package/lib/execution/internal/query-executioner.js +62 -62
- package/lib/execution/runner.js +325 -325
- package/lib/execution/transaction.js +417 -417
- package/lib/formatter/formatterUtils.js +42 -42
- package/lib/formatter/rawFormatter.js +84 -84
- package/lib/formatter/wrappingFormatter.js +253 -253
- package/lib/formatter.js +25 -25
- package/lib/index.js +3 -3
- package/lib/knex-builder/FunctionHelper.js +80 -80
- package/lib/knex-builder/Knex.js +59 -59
- package/lib/knex-builder/internal/config-resolver.js +57 -57
- package/lib/knex-builder/internal/parse-connection.js +87 -87
- package/lib/knex-builder/make-knex.js +345 -345
- package/lib/logger.js +76 -76
- package/lib/migrations/common/MigrationsLoader.js +36 -36
- package/lib/migrations/migrate/MigrationGenerator.js +84 -84
- package/lib/migrations/migrate/Migrator.js +632 -632
- package/lib/migrations/migrate/migrate-stub.js +17 -17
- package/lib/migrations/migrate/migration-list-resolver.js +33 -33
- package/lib/migrations/migrate/migrator-configuration-merger.js +58 -58
- package/lib/migrations/migrate/sources/fs-migrations.js +74 -74
- package/lib/migrations/migrate/stub/cjs.stub +15 -15
- package/lib/migrations/migrate/stub/coffee.stub +13 -13
- package/lib/migrations/migrate/stub/eg.stub +14 -14
- package/lib/migrations/migrate/stub/js-schema.stub +22 -22
- package/lib/migrations/migrate/stub/js.stub +22 -22
- package/lib/migrations/migrate/stub/knexfile-coffee.stub +34 -34
- package/lib/migrations/migrate/stub/knexfile-eg.stub +43 -43
- package/lib/migrations/migrate/stub/knexfile-js.stub +47 -47
- package/lib/migrations/migrate/stub/knexfile-ls.stub +35 -35
- package/lib/migrations/migrate/stub/knexfile-ts.stub +47 -47
- package/lib/migrations/migrate/stub/ls.stub +14 -14
- package/lib/migrations/migrate/stub/mjs.stub +23 -23
- package/lib/migrations/migrate/stub/ts-schema.stub +21 -21
- package/lib/migrations/migrate/stub/ts.stub +21 -21
- package/lib/migrations/migrate/table-creator.js +77 -77
- package/lib/migrations/migrate/table-resolver.js +27 -27
- package/lib/migrations/seed/Seeder.js +137 -137
- package/lib/migrations/seed/seed-stub.js +13 -13
- package/lib/migrations/seed/seeder-configuration-merger.js +60 -60
- package/lib/migrations/seed/sources/fs-seeds.js +65 -65
- package/lib/migrations/seed/stub/coffee.stub +9 -9
- package/lib/migrations/seed/stub/eg.stub +11 -11
- package/lib/migrations/seed/stub/js.stub +13 -13
- package/lib/migrations/seed/stub/ls.stub +11 -11
- package/lib/migrations/seed/stub/mjs.stub +12 -12
- package/lib/migrations/seed/stub/ts.stub +13 -13
- package/lib/migrations/util/fs.js +86 -86
- package/lib/migrations/util/import-file.js +12 -12
- package/lib/migrations/util/is-module-type.js +9 -9
- package/lib/migrations/util/template.js +52 -52
- package/lib/migrations/util/timestamp.js +14 -14
- package/lib/query/analytic.js +52 -52
- package/lib/query/constants.js +15 -15
- package/lib/query/joinclause.js +270 -270
- package/lib/query/method-constants.js +136 -136
- package/lib/query/querybuilder.js +1793 -1793
- package/lib/query/querycompiler.js +1634 -1634
- package/lib/raw.js +139 -139
- package/lib/ref.js +39 -39
- package/lib/schema/builder.js +115 -115
- package/lib/schema/columnbuilder.js +146 -146
- package/lib/schema/columncompiler.js +307 -307
- package/lib/schema/compiler.js +187 -187
- package/lib/schema/internal/helpers.js +55 -55
- package/lib/schema/tablebuilder.js +379 -379
- package/lib/schema/tablecompiler.js +450 -450
- package/lib/schema/viewbuilder.js +92 -92
- package/lib/schema/viewcompiler.js +138 -138
- package/lib/util/finally-mixin.js +13 -13
- package/lib/util/helpers.js +95 -95
- package/lib/util/is.js +32 -32
- package/lib/util/nanoid.js +40 -40
- package/lib/util/noop.js +1 -1
- package/lib/util/save-async-stack.js +14 -14
- package/lib/util/security.js +32 -32
- package/lib/util/string.js +190 -190
- package/lib/util/timeout.js +29 -29
- package/package.json +294 -293
- package/scripts/act-testing/act.sh +19 -19
- package/scripts/act-testing/merged-no-label.json +11 -11
- package/scripts/act-testing/merged-patch-labeled.json +12 -12
- package/scripts/act-testing/merged-skip-labeled.json +12 -12
- package/scripts/act-testing/not-merged-patch-labeled.json +12 -12
- package/scripts/build-for-release.sh +121 -121
- package/scripts/build.js +125 -125
- package/scripts/clean.js +31 -31
- package/scripts/docker-compose.yml +150 -150
- package/scripts/format-changelog.js +55 -55
- package/scripts/next-release-howto.md +24 -24
- package/scripts/oracledb-install-driver-libs.sh +82 -82
- package/scripts/release.sh +36 -36
- package/scripts/runkit-example.js +35 -35
- package/scripts/stress-test/README.txt +18 -18
- package/scripts/stress-test/docker-compose.yml +55 -55
- package/scripts/stress-test/knex-stress-test.js +212 -212
- package/scripts/stress-test/mysql2-random-hanging-every-now-and-then.js +149 -149
- package/scripts/stress-test/mysql2-sudden-exit-without-error.js +101 -101
- package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +188 -188
- package/types/index.d.mts +11 -0
- package/types/index.d.ts +3321 -3321
- package/types/result.d.ts +27 -27
- package/types/tables.d.ts +4 -4
|
@@ -1,253 +1,253 @@
|
|
|
1
|
-
const transform = require('lodash/transform');
|
|
2
|
-
const QueryBuilder = require('../query/querybuilder');
|
|
3
|
-
const { compileCallback, wrapAsIdentifier } = require('./formatterUtils');
|
|
4
|
-
|
|
5
|
-
// Valid values for the `order by` clause generation.
|
|
6
|
-
const orderBys = ['asc', 'desc'];
|
|
7
|
-
|
|
8
|
-
// Turn this into a lookup map
|
|
9
|
-
const operators = transform(
|
|
10
|
-
[
|
|
11
|
-
'=',
|
|
12
|
-
'<',
|
|
13
|
-
'>',
|
|
14
|
-
'<=',
|
|
15
|
-
'<=>',
|
|
16
|
-
'>=',
|
|
17
|
-
'<>',
|
|
18
|
-
'!=',
|
|
19
|
-
'like',
|
|
20
|
-
'not like',
|
|
21
|
-
'between',
|
|
22
|
-
'not between',
|
|
23
|
-
'ilike',
|
|
24
|
-
'not ilike',
|
|
25
|
-
'exists',
|
|
26
|
-
'not exist',
|
|
27
|
-
'rlike',
|
|
28
|
-
'not rlike',
|
|
29
|
-
'regexp',
|
|
30
|
-
'not regexp',
|
|
31
|
-
'match',
|
|
32
|
-
'similar to',
|
|
33
|
-
'not similar to',
|
|
34
|
-
'&',
|
|
35
|
-
'|',
|
|
36
|
-
'^',
|
|
37
|
-
'<<',
|
|
38
|
-
'>>',
|
|
39
|
-
'~',
|
|
40
|
-
'~=',
|
|
41
|
-
'~*',
|
|
42
|
-
'!~',
|
|
43
|
-
'!~*',
|
|
44
|
-
'#',
|
|
45
|
-
'&&',
|
|
46
|
-
'@>',
|
|
47
|
-
'<@',
|
|
48
|
-
'||',
|
|
49
|
-
'&<',
|
|
50
|
-
'&>',
|
|
51
|
-
'-|-',
|
|
52
|
-
'@@',
|
|
53
|
-
'!!',
|
|
54
|
-
['?', '\\?'],
|
|
55
|
-
['?|', '\\?|'],
|
|
56
|
-
['?&', '\\?&'],
|
|
57
|
-
],
|
|
58
|
-
(result, key) => {
|
|
59
|
-
if (Array.isArray(key)) {
|
|
60
|
-
result[key[0]] = key[1];
|
|
61
|
-
} else {
|
|
62
|
-
result[key] = key;
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
{}
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
// Accepts a string or array of columns to wrap as appropriate. Column can be raw
|
|
69
|
-
function columnize(target, builder, client, bindingHolder) {
|
|
70
|
-
const columns = Array.isArray(target) ? target : [target];
|
|
71
|
-
let str = '',
|
|
72
|
-
i = -1;
|
|
73
|
-
while (++i < columns.length) {
|
|
74
|
-
if (i > 0) str += ', ';
|
|
75
|
-
str += wrap(columns[i], undefined, builder, client, bindingHolder);
|
|
76
|
-
}
|
|
77
|
-
return str;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Puts the appropriate wrapper around a value depending on the database
|
|
81
|
-
// engine, unless it's a knex.raw value, in which case it's left alone.
|
|
82
|
-
function wrap(value, isParameter, builder, client, bindingHolder) {
|
|
83
|
-
const raw = unwrapRaw(value, isParameter, builder, client, bindingHolder);
|
|
84
|
-
if (raw) return raw;
|
|
85
|
-
switch (typeof value) {
|
|
86
|
-
case 'function':
|
|
87
|
-
return outputQuery(
|
|
88
|
-
compileCallback(value, undefined, client, bindingHolder),
|
|
89
|
-
true,
|
|
90
|
-
builder,
|
|
91
|
-
client
|
|
92
|
-
);
|
|
93
|
-
case 'object':
|
|
94
|
-
return parseObject(value, builder, client, bindingHolder);
|
|
95
|
-
case 'number':
|
|
96
|
-
return value;
|
|
97
|
-
default:
|
|
98
|
-
return wrapString(value + '', builder, client);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function unwrapRaw(value, isParameter, builder, client, bindingsHolder) {
|
|
103
|
-
let query;
|
|
104
|
-
if (value instanceof QueryBuilder) {
|
|
105
|
-
query = client.queryCompiler(value).toSQL();
|
|
106
|
-
if (query.bindings) {
|
|
107
|
-
bindingsHolder.bindings.push(...query.bindings);
|
|
108
|
-
}
|
|
109
|
-
return outputQuery(query, isParameter, builder, client);
|
|
110
|
-
}
|
|
111
|
-
if (value && value.isRawInstance) {
|
|
112
|
-
value.client = client;
|
|
113
|
-
if (builder._queryContext) {
|
|
114
|
-
value.queryContext = () => {
|
|
115
|
-
return builder._queryContext;
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
query = value.toSQL();
|
|
120
|
-
if (query.bindings) {
|
|
121
|
-
bindingsHolder.bindings.push(...query.bindings);
|
|
122
|
-
}
|
|
123
|
-
return query.sql;
|
|
124
|
-
}
|
|
125
|
-
if (isParameter) {
|
|
126
|
-
bindingsHolder.bindings.push(value);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function operator(value, builder, client, bindingsHolder) {
|
|
131
|
-
const raw = unwrapRaw(value, undefined, builder, client, bindingsHolder);
|
|
132
|
-
if (raw) return raw;
|
|
133
|
-
const operator = operators[(value || '').toLowerCase()];
|
|
134
|
-
if (!operator) {
|
|
135
|
-
throw new TypeError(`The operator "${value}" is not permitted`);
|
|
136
|
-
}
|
|
137
|
-
return operator;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Coerce to string to prevent strange errors when it's not a string.
|
|
141
|
-
function wrapString(value, builder, client) {
|
|
142
|
-
const asIndex = value.toLowerCase().indexOf(' as ');
|
|
143
|
-
if (asIndex !== -1) {
|
|
144
|
-
const first = value.slice(0, asIndex);
|
|
145
|
-
const second = value.slice(asIndex + 4);
|
|
146
|
-
return client.alias(
|
|
147
|
-
wrapString(first, builder, client),
|
|
148
|
-
wrapAsIdentifier(second, builder, client)
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
const wrapped = [];
|
|
152
|
-
let i = -1;
|
|
153
|
-
const segments = value.split('.');
|
|
154
|
-
while (++i < segments.length) {
|
|
155
|
-
value = segments[i];
|
|
156
|
-
if (i === 0 && segments.length > 1) {
|
|
157
|
-
wrapped.push(wrapString((value || '').trim(), builder, client));
|
|
158
|
-
} else {
|
|
159
|
-
wrapped.push(wrapAsIdentifier(value, builder, client));
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
return wrapped.join('.');
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Key-value notation for alias
|
|
166
|
-
function parseObject(obj, builder, client, formatter) {
|
|
167
|
-
const ret = [];
|
|
168
|
-
for (const alias in obj) {
|
|
169
|
-
const queryOrIdentifier = obj[alias];
|
|
170
|
-
// Avoids double aliasing for subqueries
|
|
171
|
-
if (typeof queryOrIdentifier === 'function') {
|
|
172
|
-
const compiled = compileCallback(
|
|
173
|
-
queryOrIdentifier,
|
|
174
|
-
undefined,
|
|
175
|
-
client,
|
|
176
|
-
formatter
|
|
177
|
-
);
|
|
178
|
-
compiled.as = alias; // enforces the object's alias
|
|
179
|
-
ret.push(outputQuery(compiled, true, builder, client));
|
|
180
|
-
} else if (queryOrIdentifier instanceof QueryBuilder) {
|
|
181
|
-
ret.push(
|
|
182
|
-
client.alias(
|
|
183
|
-
`(${wrap(queryOrIdentifier, undefined, builder, client, formatter)})`,
|
|
184
|
-
wrapAsIdentifier(alias, builder, client)
|
|
185
|
-
)
|
|
186
|
-
);
|
|
187
|
-
} else {
|
|
188
|
-
ret.push(
|
|
189
|
-
client.alias(
|
|
190
|
-
wrap(queryOrIdentifier, undefined, builder, client, formatter),
|
|
191
|
-
wrapAsIdentifier(alias, builder, client)
|
|
192
|
-
)
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return ret.join(', ');
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Ensures the query is aliased if necessary.
|
|
200
|
-
function outputQuery(compiled, isParameter, builder, client) {
|
|
201
|
-
let sql = compiled.sql || '';
|
|
202
|
-
if (sql) {
|
|
203
|
-
if (
|
|
204
|
-
(compiled.method === 'select' || compiled.method === 'first') &&
|
|
205
|
-
(isParameter || compiled.as)
|
|
206
|
-
) {
|
|
207
|
-
sql = `(${sql})`;
|
|
208
|
-
if (compiled.as)
|
|
209
|
-
return client.alias(sql, wrapString(compiled.as, builder, client));
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
return sql;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Creates SQL for a parameter, which might be passed to where() or .with() or
|
|
217
|
-
* pretty much anywhere in API.
|
|
218
|
-
*
|
|
219
|
-
* @param value
|
|
220
|
-
* @param method Optional at least 'select' or 'update' are valid
|
|
221
|
-
* @param builder
|
|
222
|
-
* @param client
|
|
223
|
-
* @param bindingHolder
|
|
224
|
-
*/
|
|
225
|
-
function rawOrFn(value, method, builder, client, bindingHolder) {
|
|
226
|
-
if (typeof value === 'function') {
|
|
227
|
-
return outputQuery(
|
|
228
|
-
compileCallback(value, method, client, bindingHolder),
|
|
229
|
-
undefined,
|
|
230
|
-
builder,
|
|
231
|
-
client
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
return unwrapRaw(value, undefined, builder, client, bindingHolder) || '';
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Specify the direction of the ordering.
|
|
238
|
-
function direction(value, builder, client, bindingsHolder) {
|
|
239
|
-
const raw = unwrapRaw(value, undefined, builder, client, bindingsHolder);
|
|
240
|
-
if (raw) return raw;
|
|
241
|
-
return orderBys.indexOf((value || '').toLowerCase()) !== -1 ? value : 'asc';
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
module.exports = {
|
|
245
|
-
columnize,
|
|
246
|
-
direction,
|
|
247
|
-
operator,
|
|
248
|
-
outputQuery,
|
|
249
|
-
rawOrFn,
|
|
250
|
-
unwrapRaw,
|
|
251
|
-
wrap,
|
|
252
|
-
wrapString,
|
|
253
|
-
};
|
|
1
|
+
const transform = require('lodash/transform');
|
|
2
|
+
const QueryBuilder = require('../query/querybuilder');
|
|
3
|
+
const { compileCallback, wrapAsIdentifier } = require('./formatterUtils');
|
|
4
|
+
|
|
5
|
+
// Valid values for the `order by` clause generation.
|
|
6
|
+
const orderBys = ['asc', 'desc'];
|
|
7
|
+
|
|
8
|
+
// Turn this into a lookup map
|
|
9
|
+
const operators = transform(
|
|
10
|
+
[
|
|
11
|
+
'=',
|
|
12
|
+
'<',
|
|
13
|
+
'>',
|
|
14
|
+
'<=',
|
|
15
|
+
'<=>',
|
|
16
|
+
'>=',
|
|
17
|
+
'<>',
|
|
18
|
+
'!=',
|
|
19
|
+
'like',
|
|
20
|
+
'not like',
|
|
21
|
+
'between',
|
|
22
|
+
'not between',
|
|
23
|
+
'ilike',
|
|
24
|
+
'not ilike',
|
|
25
|
+
'exists',
|
|
26
|
+
'not exist',
|
|
27
|
+
'rlike',
|
|
28
|
+
'not rlike',
|
|
29
|
+
'regexp',
|
|
30
|
+
'not regexp',
|
|
31
|
+
'match',
|
|
32
|
+
'similar to',
|
|
33
|
+
'not similar to',
|
|
34
|
+
'&',
|
|
35
|
+
'|',
|
|
36
|
+
'^',
|
|
37
|
+
'<<',
|
|
38
|
+
'>>',
|
|
39
|
+
'~',
|
|
40
|
+
'~=',
|
|
41
|
+
'~*',
|
|
42
|
+
'!~',
|
|
43
|
+
'!~*',
|
|
44
|
+
'#',
|
|
45
|
+
'&&',
|
|
46
|
+
'@>',
|
|
47
|
+
'<@',
|
|
48
|
+
'||',
|
|
49
|
+
'&<',
|
|
50
|
+
'&>',
|
|
51
|
+
'-|-',
|
|
52
|
+
'@@',
|
|
53
|
+
'!!',
|
|
54
|
+
['?', '\\?'],
|
|
55
|
+
['?|', '\\?|'],
|
|
56
|
+
['?&', '\\?&'],
|
|
57
|
+
],
|
|
58
|
+
(result, key) => {
|
|
59
|
+
if (Array.isArray(key)) {
|
|
60
|
+
result[key[0]] = key[1];
|
|
61
|
+
} else {
|
|
62
|
+
result[key] = key;
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{}
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
// Accepts a string or array of columns to wrap as appropriate. Column can be raw
|
|
69
|
+
function columnize(target, builder, client, bindingHolder) {
|
|
70
|
+
const columns = Array.isArray(target) ? target : [target];
|
|
71
|
+
let str = '',
|
|
72
|
+
i = -1;
|
|
73
|
+
while (++i < columns.length) {
|
|
74
|
+
if (i > 0) str += ', ';
|
|
75
|
+
str += wrap(columns[i], undefined, builder, client, bindingHolder);
|
|
76
|
+
}
|
|
77
|
+
return str;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Puts the appropriate wrapper around a value depending on the database
|
|
81
|
+
// engine, unless it's a knex.raw value, in which case it's left alone.
|
|
82
|
+
function wrap(value, isParameter, builder, client, bindingHolder) {
|
|
83
|
+
const raw = unwrapRaw(value, isParameter, builder, client, bindingHolder);
|
|
84
|
+
if (raw) return raw;
|
|
85
|
+
switch (typeof value) {
|
|
86
|
+
case 'function':
|
|
87
|
+
return outputQuery(
|
|
88
|
+
compileCallback(value, undefined, client, bindingHolder),
|
|
89
|
+
true,
|
|
90
|
+
builder,
|
|
91
|
+
client
|
|
92
|
+
);
|
|
93
|
+
case 'object':
|
|
94
|
+
return parseObject(value, builder, client, bindingHolder);
|
|
95
|
+
case 'number':
|
|
96
|
+
return value;
|
|
97
|
+
default:
|
|
98
|
+
return wrapString(value + '', builder, client);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function unwrapRaw(value, isParameter, builder, client, bindingsHolder) {
|
|
103
|
+
let query;
|
|
104
|
+
if (value instanceof QueryBuilder) {
|
|
105
|
+
query = client.queryCompiler(value).toSQL();
|
|
106
|
+
if (query.bindings) {
|
|
107
|
+
bindingsHolder.bindings.push(...query.bindings);
|
|
108
|
+
}
|
|
109
|
+
return outputQuery(query, isParameter, builder, client);
|
|
110
|
+
}
|
|
111
|
+
if (value && value.isRawInstance) {
|
|
112
|
+
value.client = client;
|
|
113
|
+
if (builder._queryContext) {
|
|
114
|
+
value.queryContext = () => {
|
|
115
|
+
return builder._queryContext;
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
query = value.toSQL();
|
|
120
|
+
if (query.bindings) {
|
|
121
|
+
bindingsHolder.bindings.push(...query.bindings);
|
|
122
|
+
}
|
|
123
|
+
return query.sql;
|
|
124
|
+
}
|
|
125
|
+
if (isParameter) {
|
|
126
|
+
bindingsHolder.bindings.push(value);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function operator(value, builder, client, bindingsHolder) {
|
|
131
|
+
const raw = unwrapRaw(value, undefined, builder, client, bindingsHolder);
|
|
132
|
+
if (raw) return raw;
|
|
133
|
+
const operator = operators[(value || '').toLowerCase()];
|
|
134
|
+
if (!operator) {
|
|
135
|
+
throw new TypeError(`The operator "${value}" is not permitted`);
|
|
136
|
+
}
|
|
137
|
+
return operator;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Coerce to string to prevent strange errors when it's not a string.
|
|
141
|
+
function wrapString(value, builder, client) {
|
|
142
|
+
const asIndex = value.toLowerCase().indexOf(' as ');
|
|
143
|
+
if (asIndex !== -1) {
|
|
144
|
+
const first = value.slice(0, asIndex);
|
|
145
|
+
const second = value.slice(asIndex + 4);
|
|
146
|
+
return client.alias(
|
|
147
|
+
wrapString(first, builder, client),
|
|
148
|
+
wrapAsIdentifier(second, builder, client)
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
const wrapped = [];
|
|
152
|
+
let i = -1;
|
|
153
|
+
const segments = value.split('.');
|
|
154
|
+
while (++i < segments.length) {
|
|
155
|
+
value = segments[i];
|
|
156
|
+
if (i === 0 && segments.length > 1) {
|
|
157
|
+
wrapped.push(wrapString((value || '').trim(), builder, client));
|
|
158
|
+
} else {
|
|
159
|
+
wrapped.push(wrapAsIdentifier(value, builder, client));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return wrapped.join('.');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Key-value notation for alias
|
|
166
|
+
function parseObject(obj, builder, client, formatter) {
|
|
167
|
+
const ret = [];
|
|
168
|
+
for (const alias in obj) {
|
|
169
|
+
const queryOrIdentifier = obj[alias];
|
|
170
|
+
// Avoids double aliasing for subqueries
|
|
171
|
+
if (typeof queryOrIdentifier === 'function') {
|
|
172
|
+
const compiled = compileCallback(
|
|
173
|
+
queryOrIdentifier,
|
|
174
|
+
undefined,
|
|
175
|
+
client,
|
|
176
|
+
formatter
|
|
177
|
+
);
|
|
178
|
+
compiled.as = alias; // enforces the object's alias
|
|
179
|
+
ret.push(outputQuery(compiled, true, builder, client));
|
|
180
|
+
} else if (queryOrIdentifier instanceof QueryBuilder) {
|
|
181
|
+
ret.push(
|
|
182
|
+
client.alias(
|
|
183
|
+
`(${wrap(queryOrIdentifier, undefined, builder, client, formatter)})`,
|
|
184
|
+
wrapAsIdentifier(alias, builder, client)
|
|
185
|
+
)
|
|
186
|
+
);
|
|
187
|
+
} else {
|
|
188
|
+
ret.push(
|
|
189
|
+
client.alias(
|
|
190
|
+
wrap(queryOrIdentifier, undefined, builder, client, formatter),
|
|
191
|
+
wrapAsIdentifier(alias, builder, client)
|
|
192
|
+
)
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return ret.join(', ');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Ensures the query is aliased if necessary.
|
|
200
|
+
function outputQuery(compiled, isParameter, builder, client) {
|
|
201
|
+
let sql = compiled.sql || '';
|
|
202
|
+
if (sql) {
|
|
203
|
+
if (
|
|
204
|
+
(compiled.method === 'select' || compiled.method === 'first') &&
|
|
205
|
+
(isParameter || compiled.as)
|
|
206
|
+
) {
|
|
207
|
+
sql = `(${sql})`;
|
|
208
|
+
if (compiled.as)
|
|
209
|
+
return client.alias(sql, wrapString(compiled.as, builder, client));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return sql;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Creates SQL for a parameter, which might be passed to where() or .with() or
|
|
217
|
+
* pretty much anywhere in API.
|
|
218
|
+
*
|
|
219
|
+
* @param value
|
|
220
|
+
* @param method Optional at least 'select' or 'update' are valid
|
|
221
|
+
* @param builder
|
|
222
|
+
* @param client
|
|
223
|
+
* @param bindingHolder
|
|
224
|
+
*/
|
|
225
|
+
function rawOrFn(value, method, builder, client, bindingHolder) {
|
|
226
|
+
if (typeof value === 'function') {
|
|
227
|
+
return outputQuery(
|
|
228
|
+
compileCallback(value, method, client, bindingHolder),
|
|
229
|
+
undefined,
|
|
230
|
+
builder,
|
|
231
|
+
client
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
return unwrapRaw(value, undefined, builder, client, bindingHolder) || '';
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Specify the direction of the ordering.
|
|
238
|
+
function direction(value, builder, client, bindingsHolder) {
|
|
239
|
+
const raw = unwrapRaw(value, undefined, builder, client, bindingsHolder);
|
|
240
|
+
if (raw) return raw;
|
|
241
|
+
return orderBys.indexOf((value || '').toLowerCase()) !== -1 ? value : 'asc';
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
module.exports = {
|
|
245
|
+
columnize,
|
|
246
|
+
direction,
|
|
247
|
+
operator,
|
|
248
|
+
outputQuery,
|
|
249
|
+
rawOrFn,
|
|
250
|
+
unwrapRaw,
|
|
251
|
+
wrap,
|
|
252
|
+
wrapString,
|
|
253
|
+
};
|
package/lib/formatter.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
const {
|
|
2
|
-
columnize: columnize_,
|
|
3
|
-
wrap: wrap_,
|
|
4
|
-
} = require('./formatter/wrappingFormatter');
|
|
5
|
-
|
|
6
|
-
class Formatter {
|
|
7
|
-
constructor(client, builder) {
|
|
8
|
-
this.client = client;
|
|
9
|
-
this.builder = builder;
|
|
10
|
-
this.bindings = [];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Accepts a string or array of columns to wrap as appropriate.
|
|
14
|
-
columnize(target) {
|
|
15
|
-
return columnize_(target, this.builder, this.client, this);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Puts the appropriate wrapper around a value depending on the database
|
|
19
|
-
// engine, unless it's a knex.raw value, in which case it's left alone.
|
|
20
|
-
wrap(value, isParameter) {
|
|
21
|
-
return wrap_(value, isParameter, this.builder, this.client, this);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
module.exports = Formatter;
|
|
1
|
+
const {
|
|
2
|
+
columnize: columnize_,
|
|
3
|
+
wrap: wrap_,
|
|
4
|
+
} = require('./formatter/wrappingFormatter');
|
|
5
|
+
|
|
6
|
+
class Formatter {
|
|
7
|
+
constructor(client, builder) {
|
|
8
|
+
this.client = client;
|
|
9
|
+
this.builder = builder;
|
|
10
|
+
this.bindings = [];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Accepts a string or array of columns to wrap as appropriate.
|
|
14
|
+
columnize(target) {
|
|
15
|
+
return columnize_(target, this.builder, this.client, this);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Puts the appropriate wrapper around a value depending on the database
|
|
19
|
+
// engine, unless it's a knex.raw value, in which case it's left alone.
|
|
20
|
+
wrap(value, isParameter) {
|
|
21
|
+
return wrap_(value, isParameter, this.builder, this.client, this);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = Formatter;
|
package/lib/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
const Knex = require('./knex-builder/Knex');
|
|
2
|
-
|
|
3
|
-
module.exports = Knex;
|
|
1
|
+
const Knex = require('./knex-builder/Knex');
|
|
2
|
+
|
|
3
|
+
module.exports = Knex;
|