@mikro-orm/knex 6.0.0-dev.50 → 6.0.0-dev.52
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/AbstractSqlDriver.js +8 -5
- package/AbstractSqlPlatform.js +9 -5
- package/MonkeyPatchable.d.ts +1 -0
- package/MonkeyPatchable.js +3 -0
- package/index.mjs +3 -1
- package/package.json +2 -2
- package/query/ObjectCriteriaNode.js +7 -3
- package/query/QueryBuilder.d.ts +6 -0
- package/query/QueryBuilder.js +49 -11
- package/query/QueryBuilderHelper.d.ts +0 -2
- package/query/QueryBuilderHelper.js +42 -56
package/AbstractSqlDriver.js
CHANGED
|
@@ -638,11 +638,11 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
638
638
|
const aliased = qb.ref(tableAlias ? `${tableAlias}__${prop.fieldNames[0]}` : prop.fieldNames[0]).toString();
|
|
639
639
|
if (prop.customType?.convertToJSValueSQL && tableAlias) {
|
|
640
640
|
const prefixed = qb.ref(prop.fieldNames[0]).withSchema(tableAlias).toString();
|
|
641
|
-
return [prop.customType.convertToJSValueSQL(prefixed, this.platform)
|
|
641
|
+
return [(0, core_1.raw)(`${prop.customType.convertToJSValueSQL(prefixed, this.platform)} as ${aliased}`)];
|
|
642
642
|
}
|
|
643
643
|
if (prop.formula) {
|
|
644
644
|
const alias = qb.ref(tableAlias ?? qb.alias).toString();
|
|
645
|
-
return [`${prop.formula(alias)} as ${aliased}`];
|
|
645
|
+
return [(0, core_1.raw)(`${prop.formula(alias)} as ${aliased}`)];
|
|
646
646
|
}
|
|
647
647
|
if (tableAlias) {
|
|
648
648
|
return prop.fieldNames.map(fieldName => qb.ref(fieldName).withSchema(tableAlias).as(`${tableAlias}__${fieldName}`));
|
|
@@ -739,7 +739,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
739
739
|
const meta = (0, core_1.helper)(entity).__meta;
|
|
740
740
|
const qb = this.createQueryBuilder(entity.constructor.name, options.ctx).unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES).withSchema(options.schema ?? meta.schema);
|
|
741
741
|
const cond = core_1.Utils.getPrimaryKeyCond(entity, meta.primaryKeys);
|
|
742
|
-
qb.select('1').where(cond).setLockMode(options.lockMode, options.lockTableAliases);
|
|
742
|
+
qb.select((0, core_1.raw)('1')).where(cond).setLockMode(options.lockMode, options.lockTableAliases);
|
|
743
743
|
await this.rethrow(qb.execute());
|
|
744
744
|
}
|
|
745
745
|
buildJoinedPropsOrderBy(entityName, qb, meta, populate, parentPath) {
|
|
@@ -805,6 +805,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
805
805
|
const requiresSQLConversion = meta.props.some(p => p.customType?.convertToJSValueSQL);
|
|
806
806
|
const hasExplicitFields = !!fields;
|
|
807
807
|
const ret = [];
|
|
808
|
+
let addFormulas = false;
|
|
808
809
|
if (joinedProps.length > 0) {
|
|
809
810
|
ret.push(...this.getFieldsForJoinedLoad(qb, meta, fields, populate));
|
|
810
811
|
}
|
|
@@ -830,17 +831,19 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
830
831
|
else if (lazyProps.filter(p => !p.formula).length > 0) {
|
|
831
832
|
const props = meta.props.filter(prop => this.platform.shouldHaveColumn(prop, populate, false));
|
|
832
833
|
ret.push(...core_1.Utils.flatten(props.filter(p => !lazyProps.includes(p)).map(p => p.fieldNames)));
|
|
834
|
+
addFormulas = true;
|
|
833
835
|
}
|
|
834
836
|
else if (hasLazyFormulas || requiresSQLConversion) {
|
|
835
837
|
ret.push('*');
|
|
838
|
+
addFormulas = true;
|
|
836
839
|
}
|
|
837
|
-
if (ret.length > 0 && !hasExplicitFields) {
|
|
840
|
+
if (ret.length > 0 && !hasExplicitFields && addFormulas) {
|
|
838
841
|
meta.props
|
|
839
842
|
.filter(prop => prop.formula && !lazyProps.includes(prop))
|
|
840
843
|
.forEach(prop => {
|
|
841
844
|
const alias = qb.ref(qb.alias).toString();
|
|
842
845
|
const aliased = qb.ref(prop.fieldNames[0]).toString();
|
|
843
|
-
ret.push(`${prop.formula(alias)} as ${aliased}`);
|
|
846
|
+
ret.push((0, core_1.raw)(`${prop.formula(alias)} as ${aliased}`));
|
|
844
847
|
});
|
|
845
848
|
meta.props
|
|
846
849
|
.filter(prop => prop.customType?.convertToDatabaseValueSQL || prop.customType?.convertToJSValueSQL)
|
package/AbstractSqlPlatform.js
CHANGED
|
@@ -48,22 +48,26 @@ class AbstractSqlPlatform extends core_1.Platform {
|
|
|
48
48
|
let j = 0;
|
|
49
49
|
let pos = 0;
|
|
50
50
|
let ret = '';
|
|
51
|
+
if (sql[0] === '?' && sql[1] !== '?') {
|
|
52
|
+
ret += this.quoteValue(params[j++]);
|
|
53
|
+
pos = 1;
|
|
54
|
+
}
|
|
51
55
|
while (pos < sql.length) {
|
|
52
56
|
const idx = sql.indexOf('?', pos + 1);
|
|
53
57
|
if (idx === -1) {
|
|
54
58
|
ret += sql.substring(pos, sql.length);
|
|
55
59
|
break;
|
|
56
60
|
}
|
|
57
|
-
if (sql.
|
|
58
|
-
ret += sql.
|
|
61
|
+
if (sql.substring(idx - 1, idx + 1) === '\\?') {
|
|
62
|
+
ret += sql.substring(pos, idx - 1) + '?';
|
|
59
63
|
pos = idx + 1;
|
|
60
64
|
}
|
|
61
|
-
else if (sql.
|
|
62
|
-
ret += sql.
|
|
65
|
+
else if (sql.substring(idx, idx + 2) === '??') {
|
|
66
|
+
ret += sql.substring(pos, idx) + this.quoteIdentifier(params[j++]);
|
|
63
67
|
pos = idx + 2;
|
|
64
68
|
}
|
|
65
69
|
else {
|
|
66
|
-
ret += sql.
|
|
70
|
+
ret += sql.substring(pos, idx) + this.quoteValue(params[j++]);
|
|
67
71
|
pos = idx + 1;
|
|
68
72
|
}
|
|
69
73
|
}
|
package/MonkeyPatchable.d.ts
CHANGED
package/MonkeyPatchable.js
CHANGED
|
@@ -13,6 +13,8 @@ const mysql_1 = __importDefault(require("knex/lib/dialects/mysql"));
|
|
|
13
13
|
// @ts-ignore
|
|
14
14
|
const mysql_columncompiler_1 = __importDefault(require("knex/lib/dialects/mysql/schema/mysql-columncompiler"));
|
|
15
15
|
// @ts-ignore
|
|
16
|
+
const mysql_querycompiler_1 = __importDefault(require("knex/lib/dialects/mysql/query/mysql-querycompiler"));
|
|
17
|
+
// @ts-ignore
|
|
16
18
|
const pg_tablecompiler_1 = __importDefault(require("knex/lib/dialects/postgres/schema/pg-tablecompiler"));
|
|
17
19
|
// @ts-ignore
|
|
18
20
|
const sqlite3_1 = __importDefault(require("knex/lib/dialects/sqlite3"));
|
|
@@ -29,6 +31,7 @@ exports.MonkeyPatchable = {
|
|
|
29
31
|
QueryExecutioner: query_executioner_1.default,
|
|
30
32
|
MySqlDialect: mysql_1.default,
|
|
31
33
|
MySqlColumnCompiler: mysql_columncompiler_1.default,
|
|
34
|
+
MySqlQueryCompiler: mysql_querycompiler_1.default,
|
|
32
35
|
PostgresDialectTableCompiler: pg_tablecompiler_1.default,
|
|
33
36
|
Sqlite3Dialect: sqlite3_1.default,
|
|
34
37
|
Sqlite3DialectTableCompiler: sqlite_tablecompiler_1.default,
|
package/index.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import mod from "./index.js";
|
|
2
2
|
|
|
3
3
|
export default mod;
|
|
4
|
+
export const ALIAS_REPLACEMENT = mod.ALIAS_REPLACEMENT;
|
|
5
|
+
export const ALIAS_REPLACEMENT_RE = mod.ALIAS_REPLACEMENT_RE;
|
|
4
6
|
export const ARRAY_OPERATORS = mod.ARRAY_OPERATORS;
|
|
5
7
|
export const AbstractNamingStrategy = mod.AbstractNamingStrategy;
|
|
6
8
|
export const AbstractSchemaGenerator = mod.AbstractSchemaGenerator;
|
|
@@ -186,7 +188,6 @@ export const compareBuffers = mod.compareBuffers;
|
|
|
186
188
|
export const compareObjects = mod.compareObjects;
|
|
187
189
|
export const defineConfig = mod.defineConfig;
|
|
188
190
|
export const equals = mod.equals;
|
|
189
|
-
export const expr = mod.expr;
|
|
190
191
|
export const helper = mod.helper;
|
|
191
192
|
export const knex = mod.knex;
|
|
192
193
|
export const parseJsonSafe = mod.parseJsonSafe;
|
|
@@ -194,6 +195,7 @@ export const raw = mod.raw;
|
|
|
194
195
|
export const ref = mod.ref;
|
|
195
196
|
export const rel = mod.rel;
|
|
196
197
|
export const serialize = mod.serialize;
|
|
198
|
+
export const sql = mod.sql;
|
|
197
199
|
export const t = mod.t;
|
|
198
200
|
export const types = mod.types;
|
|
199
201
|
export const wrap = mod.wrap;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/knex",
|
|
3
|
-
"version": "6.0.0-dev.
|
|
3
|
+
"version": "6.0.0-dev.52",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
@@ -66,6 +66,6 @@
|
|
|
66
66
|
"@mikro-orm/core": "^5.6.16"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@mikro-orm/core": "~6.0.0-dev.
|
|
69
|
+
"@mikro-orm/core": "~6.0.0-dev.52"
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -21,7 +21,7 @@ class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
|
21
21
|
const childNode = this.payload[field];
|
|
22
22
|
const payload = childNode.process(qb, this.prop ? alias : ownerAlias);
|
|
23
23
|
const operator = core_1.Utils.isOperator(field);
|
|
24
|
-
const
|
|
24
|
+
const isRawField = core_1.RawQueryFragment.isKnownFragment(field);
|
|
25
25
|
// we need to keep the prefixing for formulas otherwise we would lose aliasing context when nesting inside group operators
|
|
26
26
|
const virtual = childNode.prop?.persist === false && !childNode.prop?.formula;
|
|
27
27
|
// if key is missing, we are inside group operator and we need to prefix with alias
|
|
@@ -33,8 +33,12 @@ class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
|
33
33
|
else if (childNode.shouldRename(payload)) {
|
|
34
34
|
o[childNode.renameFieldToPK(qb)] = payload;
|
|
35
35
|
}
|
|
36
|
-
else if (
|
|
37
|
-
|
|
36
|
+
else if (isRawField) {
|
|
37
|
+
const rawField = core_1.RawQueryFragment.getKnownFragment(field);
|
|
38
|
+
o[(0, core_1.raw)(rawField.sql.replaceAll(core_1.ALIAS_REPLACEMENT, alias), rawField.params)] = payload;
|
|
39
|
+
}
|
|
40
|
+
else if (primaryKey || virtual || operator || field.includes('.') || ![enums_1.QueryType.SELECT, enums_1.QueryType.COUNT].includes(qb.type ?? enums_1.QueryType.SELECT)) {
|
|
41
|
+
o[field.replaceAll(core_1.ALIAS_REPLACEMENT, alias)] = payload;
|
|
38
42
|
}
|
|
39
43
|
else {
|
|
40
44
|
o[`${alias}.${field}`] = payload;
|
package/query/QueryBuilder.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ import type { Field } from '../typings';
|
|
|
29
29
|
* ```
|
|
30
30
|
*/
|
|
31
31
|
export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
32
|
+
#private;
|
|
32
33
|
private readonly metadata;
|
|
33
34
|
private readonly driver;
|
|
34
35
|
private readonly context?;
|
|
@@ -139,6 +140,11 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
139
140
|
* Returns the query with parameters as wildcards.
|
|
140
141
|
*/
|
|
141
142
|
getQuery(): string;
|
|
143
|
+
toQuery(): {
|
|
144
|
+
sql: string;
|
|
145
|
+
_sql: Knex.Sql;
|
|
146
|
+
params: readonly unknown[];
|
|
147
|
+
};
|
|
142
148
|
/**
|
|
143
149
|
* Returns the list of all parameters for this query.
|
|
144
150
|
*/
|
package/query/QueryBuilder.js
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
5
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
8
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
11
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
12
|
+
};
|
|
13
|
+
var _QueryBuilder_query;
|
|
2
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
15
|
exports.QueryBuilder = void 0;
|
|
4
16
|
const util_1 = require("util");
|
|
@@ -64,6 +76,7 @@ class QueryBuilder {
|
|
|
64
76
|
this._aliases = {};
|
|
65
77
|
this.platform = this.driver.getPlatform();
|
|
66
78
|
this.knex = this.driver.getConnection(this.connectionType).getKnex();
|
|
79
|
+
_QueryBuilder_query.set(this, void 0);
|
|
67
80
|
if (alias) {
|
|
68
81
|
this.aliasCounter++;
|
|
69
82
|
this._explicitAlias = true;
|
|
@@ -165,9 +178,15 @@ class QueryBuilder {
|
|
|
165
178
|
}
|
|
166
179
|
where(cond, params, operator) {
|
|
167
180
|
this.ensureNotFinalized();
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
181
|
+
const rawField = core_1.RawQueryFragment.getKnownFragment(cond);
|
|
182
|
+
if (rawField) {
|
|
183
|
+
const sql = this.platform.formatQuery(rawField.sql, rawField.params);
|
|
184
|
+
cond = { [(0, core_1.raw)(`(${sql})`)]: core_1.Utils.asArray(params) };
|
|
185
|
+
operator ??= '$and';
|
|
186
|
+
}
|
|
187
|
+
else if (core_1.Utils.isString(cond)) {
|
|
188
|
+
cond = { [(0, core_1.raw)(`(${cond})`, core_1.Utils.asArray(params))]: [] };
|
|
189
|
+
operator ??= '$and';
|
|
171
190
|
}
|
|
172
191
|
else {
|
|
173
192
|
cond = core_1.QueryHelper.processWhere({
|
|
@@ -235,7 +254,7 @@ class QueryBuilder {
|
|
|
235
254
|
having(cond = {}, params) {
|
|
236
255
|
this.ensureNotFinalized();
|
|
237
256
|
if (core_1.Utils.isString(cond)) {
|
|
238
|
-
cond = { [`(${cond})
|
|
257
|
+
cond = { [(0, core_1.raw)(`(${cond})`, params)]: [] };
|
|
239
258
|
}
|
|
240
259
|
this._having = CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, cond).process(this);
|
|
241
260
|
return this;
|
|
@@ -376,19 +395,27 @@ class QueryBuilder {
|
|
|
376
395
|
* Returns the query with parameters as wildcards.
|
|
377
396
|
*/
|
|
378
397
|
getQuery() {
|
|
379
|
-
return this.
|
|
398
|
+
return this.toQuery().sql;
|
|
399
|
+
}
|
|
400
|
+
toQuery() {
|
|
401
|
+
if (__classPrivateFieldGet(this, _QueryBuilder_query, "f")) {
|
|
402
|
+
return __classPrivateFieldGet(this, _QueryBuilder_query, "f");
|
|
403
|
+
}
|
|
404
|
+
const sql = this.getKnexQuery().toSQL();
|
|
405
|
+
const query = sql.toNative();
|
|
406
|
+
return __classPrivateFieldSet(this, _QueryBuilder_query, { sql: query.sql, params: query.bindings ?? [], _sql: sql }, "f");
|
|
380
407
|
}
|
|
381
408
|
/**
|
|
382
409
|
* Returns the list of all parameters for this query.
|
|
383
410
|
*/
|
|
384
411
|
getParams() {
|
|
385
|
-
return this.
|
|
412
|
+
return this.toQuery().params;
|
|
386
413
|
}
|
|
387
414
|
/**
|
|
388
415
|
* Returns raw interpolated query string with all the parameters inlined.
|
|
389
416
|
*/
|
|
390
417
|
getFormattedQuery() {
|
|
391
|
-
const query = this.
|
|
418
|
+
const query = this.toQuery()._sql;
|
|
392
419
|
return this.platform.formatQuery(query.sql, query.bindings);
|
|
393
420
|
}
|
|
394
421
|
/**
|
|
@@ -632,6 +659,12 @@ class QueryBuilder {
|
|
|
632
659
|
prepareFields(fields, type = 'where') {
|
|
633
660
|
const ret = [];
|
|
634
661
|
fields.forEach(field => {
|
|
662
|
+
const rawField = core_1.RawQueryFragment.getKnownFragment(field);
|
|
663
|
+
if (rawField) {
|
|
664
|
+
const sql = this.platform.formatQuery(rawField.sql, rawField.params);
|
|
665
|
+
ret.push(this.knex.raw(sql));
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
635
668
|
if (!core_1.Utils.isString(field)) {
|
|
636
669
|
ret.push(field);
|
|
637
670
|
return;
|
|
@@ -799,8 +832,13 @@ class QueryBuilder {
|
|
|
799
832
|
const aliased = this.knex.ref(prop.fieldNames[0]).toString();
|
|
800
833
|
return `${prop.formula(alias)} as ${aliased}`;
|
|
801
834
|
})
|
|
802
|
-
.filter(field => !this._fields.
|
|
803
|
-
|
|
835
|
+
.filter(field => !this._fields.some(f => {
|
|
836
|
+
if (f instanceof core_1.RawQueryFragment) {
|
|
837
|
+
return f.sql === field && f.params.length === 0;
|
|
838
|
+
}
|
|
839
|
+
return f === field;
|
|
840
|
+
}))
|
|
841
|
+
.forEach(field => this._fields.push((0, core_1.raw)(field)));
|
|
804
842
|
}
|
|
805
843
|
this.processPopulateWhere();
|
|
806
844
|
core_1.QueryHelper.processObjectParams(this._data);
|
|
@@ -877,7 +915,7 @@ class QueryBuilder {
|
|
|
877
915
|
if (!prop?.persist && !prop?.formula) {
|
|
878
916
|
addToSelect.push(fieldName);
|
|
879
917
|
}
|
|
880
|
-
orderBy.push({ [`min(${this.ref(fieldName)}${type})`]: direction });
|
|
918
|
+
orderBy.push({ [(0, core_1.raw)(`min(${this.ref(fieldName)}${type})`)]: direction });
|
|
881
919
|
}
|
|
882
920
|
}
|
|
883
921
|
subQuery.orderBy(orderBy);
|
|
@@ -969,7 +1007,7 @@ class QueryBuilder {
|
|
|
969
1007
|
}
|
|
970
1008
|
}
|
|
971
1009
|
/* istanbul ignore next */
|
|
972
|
-
[util_1.inspect.custom](depth) {
|
|
1010
|
+
[(_QueryBuilder_query = new WeakMap(), util_1.inspect.custom)](depth) {
|
|
973
1011
|
const object = { ...this };
|
|
974
1012
|
const hidden = ['metadata', 'driver', 'context', 'platform', 'knex', 'type'];
|
|
975
1013
|
Object.keys(object).filter(k => k.startsWith('_')).forEach(k => delete object[k]);
|
|
@@ -43,7 +43,6 @@ export declare class QueryBuilderHelper {
|
|
|
43
43
|
}[], qb: Knex.QueryBuilder): void;
|
|
44
44
|
appendQueryCondition(type: QueryType, cond: any, qb: Knex.QueryBuilder, operator?: '$and' | '$or', method?: 'where' | 'having'): void;
|
|
45
45
|
private appendQuerySubCondition;
|
|
46
|
-
private processCustomExpression;
|
|
47
46
|
private processObjectSubCondition;
|
|
48
47
|
private getOperatorReplacement;
|
|
49
48
|
getQueryOrder(type: QueryType, orderBy: FlatQueryOrderMap | FlatQueryOrderMap[], populate: Dictionary<string>): string;
|
|
@@ -52,7 +51,6 @@ export declare class QueryBuilderHelper {
|
|
|
52
51
|
splitField<T>(field: EntityKey<T>, greedyAlias?: boolean): [string, EntityKey<T>];
|
|
53
52
|
getLockSQL(qb: Knex.QueryBuilder, lockMode: LockMode, lockTables?: string[]): void;
|
|
54
53
|
updateVersionProperty(qb: Knex.QueryBuilder, data: Dictionary): void;
|
|
55
|
-
static isCustomExpression(field: string, hasAlias?: boolean): boolean;
|
|
56
54
|
private prefix;
|
|
57
55
|
private appendGroupCondition;
|
|
58
56
|
private isPrefixed;
|
|
@@ -20,7 +20,7 @@ class QueryBuilderHelper {
|
|
|
20
20
|
}
|
|
21
21
|
mapper(field, type = enums_1.QueryType.SELECT, value, alias) {
|
|
22
22
|
if (core_1.Utils.isRawSql(field)) {
|
|
23
|
-
return this.
|
|
23
|
+
return this.knex.raw(field.sql, field.params);
|
|
24
24
|
}
|
|
25
25
|
if (typeof field !== 'string') {
|
|
26
26
|
return field;
|
|
@@ -52,10 +52,13 @@ class QueryBuilderHelper {
|
|
|
52
52
|
}
|
|
53
53
|
return this.knex.raw('(' + parts.map(part => this.knex.ref(part)).join(', ') + ')');
|
|
54
54
|
}
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
const rawField = core_1.RawQueryFragment.getKnownFragment(field);
|
|
56
|
+
if (rawField) {
|
|
57
|
+
return this.knex.raw(rawField.sql, rawField.params);
|
|
58
|
+
}
|
|
57
59
|
const [a, f] = this.splitField(field);
|
|
58
60
|
const prop = this.getProperty(f, a);
|
|
61
|
+
let ret = field;
|
|
59
62
|
// embeddable nested path instead of a regular property with table alias, reset alias
|
|
60
63
|
if (prop?.name === a && prop.embeddedProps[f]) {
|
|
61
64
|
return this.alias + '.' + prop.fieldNames[0];
|
|
@@ -79,16 +82,12 @@ class QueryBuilderHelper {
|
|
|
79
82
|
return this.knex.raw(`${valueSQL} as ${this.platform.quoteIdentifier(alias ?? prop.fieldNames[0])}`);
|
|
80
83
|
}
|
|
81
84
|
// do not wrap custom expressions
|
|
82
|
-
if (!
|
|
85
|
+
if (!rawField) {
|
|
83
86
|
ret = this.prefix(field);
|
|
84
87
|
}
|
|
85
88
|
if (alias) {
|
|
86
89
|
ret += ' as ' + alias;
|
|
87
90
|
}
|
|
88
|
-
if (customExpression) {
|
|
89
|
-
const bindings = core_1.Utils.asArray(value).slice(0, ret.match(/\?/g)?.length ?? 0);
|
|
90
|
-
return this.knex.raw(ret, bindings);
|
|
91
|
-
}
|
|
92
91
|
if (!isTableNameAliasRequired || this.isPrefixed(ret) || noPrefix) {
|
|
93
92
|
return ret;
|
|
94
93
|
}
|
|
@@ -227,20 +226,14 @@ class QueryBuilderHelper {
|
|
|
227
226
|
if (operator === '$exists') {
|
|
228
227
|
value = null;
|
|
229
228
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
const { sql, bindings } = k.toSQL().toNative();
|
|
238
|
-
if (params2.length > 0) {
|
|
239
|
-
params.push(...bindings);
|
|
240
|
-
params.push(...params2);
|
|
241
|
-
return sql + ' = ?';
|
|
229
|
+
const rawField = core_1.RawQueryFragment.getKnownFragment(key);
|
|
230
|
+
if (rawField) {
|
|
231
|
+
let sql = rawField.sql;
|
|
232
|
+
params.push(...rawField.params);
|
|
233
|
+
params.push(...core_1.Utils.asArray(value));
|
|
234
|
+
if (core_1.Utils.asArray(value).length > 0) {
|
|
235
|
+
sql += ' = ?';
|
|
242
236
|
}
|
|
243
|
-
params.push(...bindings);
|
|
244
237
|
return sql;
|
|
245
238
|
}
|
|
246
239
|
const sql = this.mapper(key);
|
|
@@ -351,28 +344,20 @@ class QueryBuilderHelper {
|
|
|
351
344
|
if (core_1.Utils.isPlainObject(cond[key]) || cond[key] instanceof RegExp) {
|
|
352
345
|
return this.processObjectSubCondition(cond, key, qb, method, m, type);
|
|
353
346
|
}
|
|
354
|
-
if (QueryBuilderHelper.isCustomExpression(key)) {
|
|
355
|
-
return this.processCustomExpression(qb, m, key, cond, type);
|
|
356
|
-
}
|
|
357
347
|
const op = cond[key] === null ? 'is' : '=';
|
|
348
|
+
const raw = core_1.RawQueryFragment.getKnownFragment(key);
|
|
349
|
+
if (raw) {
|
|
350
|
+
const value = core_1.Utils.asArray(cond[key]);
|
|
351
|
+
if (value.length > 0) {
|
|
352
|
+
return void qb[m](this.knex.raw(raw.sql, raw.params), op, value[0]);
|
|
353
|
+
}
|
|
354
|
+
return void qb[m](this.knex.raw(raw.sql, raw.params));
|
|
355
|
+
}
|
|
358
356
|
if (this.subQueries[key]) {
|
|
359
357
|
return void qb[m](this.knex.raw(`(${this.subQueries[key]})`), op, cond[key]);
|
|
360
358
|
}
|
|
361
359
|
qb[m](this.mapper(key, type, cond[key], null), op, cond[key]);
|
|
362
360
|
}
|
|
363
|
-
processCustomExpression(clause, m, key, cond, type) {
|
|
364
|
-
// unwind parameters when ? found in field name
|
|
365
|
-
const count = key.concat('?').match(/\?/g).length - 1;
|
|
366
|
-
const value = core_1.Utils.asArray(cond[key]);
|
|
367
|
-
const params1 = value.slice(0, count).map((c) => core_1.Utils.isObject(c) ? JSON.stringify(c) : c);
|
|
368
|
-
const params2 = value.slice(count);
|
|
369
|
-
const k = this.mapper(key, type, params1);
|
|
370
|
-
if (params2.length > 0) {
|
|
371
|
-
const val = params2.length === 1 && params2[0] === null ? null : this.knex.raw('?', params2);
|
|
372
|
-
return void clause[m](k, val);
|
|
373
|
-
}
|
|
374
|
-
clause[m](k);
|
|
375
|
-
}
|
|
376
361
|
processObjectSubCondition(cond, key, qb, method, m, type) {
|
|
377
362
|
// grouped condition for one field
|
|
378
363
|
let value = cond[key];
|
|
@@ -438,19 +423,20 @@ class QueryBuilderHelper {
|
|
|
438
423
|
}
|
|
439
424
|
getQueryOrderFromObject(type, orderBy, populate) {
|
|
440
425
|
const ret = [];
|
|
441
|
-
Object.keys(orderBy).forEach(
|
|
442
|
-
const direction = orderBy[
|
|
426
|
+
Object.keys(orderBy).forEach(key => {
|
|
427
|
+
const direction = orderBy[key];
|
|
443
428
|
const order = core_1.Utils.isNumber(direction) ? core_1.QueryOrderNumeric[direction] : direction;
|
|
444
|
-
|
|
445
|
-
|
|
429
|
+
const raw = core_1.RawQueryFragment.getKnownFragment(key);
|
|
430
|
+
if (raw) {
|
|
431
|
+
ret.push(`${this.platform.formatQuery(raw.sql, raw.params)} ${order.toLowerCase()}`);
|
|
446
432
|
return;
|
|
447
433
|
}
|
|
448
|
-
core_1.Utils.splitPrimaryKeys(
|
|
434
|
+
core_1.Utils.splitPrimaryKeys(key).forEach(f => {
|
|
449
435
|
// eslint-disable-next-line prefer-const
|
|
450
436
|
let [alias, field] = this.splitField(f, true);
|
|
451
437
|
alias = populate[alias] || alias;
|
|
452
438
|
const prop = this.getProperty(field, alias);
|
|
453
|
-
const noPrefix = (prop && prop.persist === false && !prop.formula) ||
|
|
439
|
+
const noPrefix = (prop && prop.persist === false && !prop.formula) || core_1.RawQueryFragment.isKnownFragment(f);
|
|
454
440
|
const column = this.mapper(noPrefix ? field : `${alias}.${field}`, type, undefined, null);
|
|
455
441
|
/* istanbul ignore next */
|
|
456
442
|
const rawColumn = core_1.Utils.isString(column) ? column.split('.').map(e => this.knex.ref(e)).join('.') : column;
|
|
@@ -522,20 +508,20 @@ class QueryBuilderHelper {
|
|
|
522
508
|
}
|
|
523
509
|
qb.update(versionProperty.fieldNames[0], this.knex.raw(sql));
|
|
524
510
|
}
|
|
525
|
-
static isCustomExpression(field, hasAlias = false) {
|
|
526
|
-
// if we do not have alias, we don't consider spaces as custom expressions
|
|
527
|
-
const re = hasAlias ? /[ ?<>=()'"`:]|^\d/ : /[?<>=()'"`:]|^\d/;
|
|
528
|
-
return !!field.match(re);
|
|
529
|
-
}
|
|
530
511
|
prefix(field, always = false, quote = false) {
|
|
531
512
|
let ret;
|
|
532
513
|
if (!this.isPrefixed(field)) {
|
|
533
514
|
const alias = always ? (quote ? this.alias : this.platform.quoteIdentifier(this.alias)) + '.' : '';
|
|
534
515
|
const fieldName = this.fieldName(field, this.alias, always);
|
|
535
|
-
if (
|
|
536
|
-
return fieldName;
|
|
516
|
+
if (fieldName instanceof core_1.RawQueryFragment) {
|
|
517
|
+
return fieldName.sql;
|
|
518
|
+
}
|
|
519
|
+
if (this.isPrefixed(fieldName)) {
|
|
520
|
+
ret = fieldName;
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
ret = alias + fieldName;
|
|
537
524
|
}
|
|
538
|
-
ret = alias + fieldName;
|
|
539
525
|
}
|
|
540
526
|
else {
|
|
541
527
|
const [a, ...rest] = field.split('.');
|
|
@@ -573,15 +559,15 @@ class QueryBuilderHelper {
|
|
|
573
559
|
}
|
|
574
560
|
if (prop.fieldNameRaw) {
|
|
575
561
|
if (!always) {
|
|
576
|
-
return prop.fieldNameRaw
|
|
577
|
-
.replace(
|
|
578
|
-
.replace(this.platform.quoteIdentifier('') + '.', '');
|
|
562
|
+
return (0, core_1.raw)(prop.fieldNameRaw
|
|
563
|
+
.replace(new RegExp(core_1.ALIAS_REPLACEMENT_RE + '\\.?', 'g'), '')
|
|
564
|
+
.replace(this.platform.quoteIdentifier('') + '.', ''));
|
|
579
565
|
}
|
|
580
566
|
if (alias) {
|
|
581
|
-
return prop.fieldNameRaw.replace(
|
|
567
|
+
return (0, core_1.raw)(prop.fieldNameRaw.replace(new RegExp(core_1.ALIAS_REPLACEMENT_RE, 'g'), alias));
|
|
582
568
|
}
|
|
583
569
|
/* istanbul ignore next */
|
|
584
|
-
return prop.fieldNameRaw;
|
|
570
|
+
return (0, core_1.raw)(prop.fieldNameRaw);
|
|
585
571
|
}
|
|
586
572
|
/* istanbul ignore next */
|
|
587
573
|
return prop.fieldNames?.[0] ?? field;
|