@mikro-orm/knex 6.0.0-dev.5 → 6.0.0-dev.50
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/AbstractSqlConnection.d.ts +3 -0
- package/AbstractSqlConnection.js +16 -8
- package/AbstractSqlDriver.d.ts +11 -11
- package/AbstractSqlDriver.js +100 -40
- package/AbstractSqlPlatform.d.ts +2 -4
- package/AbstractSqlPlatform.js +6 -16
- package/README.md +63 -106
- package/SqlEntityManager.d.ts +0 -4
- package/SqlEntityManager.js +1 -9
- package/SqlEntityRepository.d.ts +0 -1
- package/SqlEntityRepository.js +0 -1
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/index.mjs +173 -0
- package/package.json +5 -39
- package/query/ArrayCriteriaNode.d.ts +3 -3
- package/query/CriteriaNode.d.ts +8 -8
- package/query/CriteriaNode.js +8 -8
- package/query/CriteriaNodeFactory.d.ts +6 -6
- package/query/CriteriaNodeFactory.js +11 -11
- package/query/ObjectCriteriaNode.d.ts +3 -3
- package/query/ObjectCriteriaNode.js +5 -5
- package/query/QueryBuilder.d.ts +11 -4
- package/query/QueryBuilder.js +141 -36
- package/query/QueryBuilderHelper.d.ts +3 -3
- package/query/QueryBuilderHelper.js +47 -19
- package/query/ScalarCriteriaNode.d.ts +3 -2
- package/query/ScalarCriteriaNode.js +9 -6
- package/schema/DatabaseSchema.js +3 -3
- package/schema/DatabaseTable.d.ts +9 -9
- package/schema/DatabaseTable.js +21 -22
- package/schema/SchemaComparator.d.ts +4 -4
- package/schema/SchemaComparator.js +4 -2
- package/schema/SchemaHelper.d.ts +11 -11
- package/schema/SchemaHelper.js +3 -3
- package/schema/{SchemaGenerator.d.ts → SqlSchemaGenerator.d.ts} +4 -8
- package/schema/{SchemaGenerator.js → SqlSchemaGenerator.js} +17 -24
- package/schema/index.d.ts +1 -1
- package/schema/index.js +1 -1
- package/typings.d.ts +14 -13
package/query/CriteriaNode.d.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { inspect } from 'util';
|
|
3
|
-
import type { EntityProperty, MetadataStorage } from '@mikro-orm/core';
|
|
3
|
+
import type { EntityKey, EntityProperty, MetadataStorage } from '@mikro-orm/core';
|
|
4
4
|
import type { ICriteriaNode, IQueryBuilder } from '../typings';
|
|
5
5
|
/**
|
|
6
6
|
* Helper for working with deeply nested where/orderBy/having criteria. Uses composite pattern to build tree from the payload.
|
|
7
7
|
* Auto-joins relations and converts payload from { books: { publisher: { name: '...' } } } to { 'publisher_alias.name': '...' }
|
|
8
8
|
* @internal
|
|
9
9
|
*/
|
|
10
|
-
export declare class CriteriaNode implements ICriteriaNode {
|
|
10
|
+
export declare class CriteriaNode<T extends object> implements ICriteriaNode<T> {
|
|
11
11
|
protected readonly metadata: MetadataStorage;
|
|
12
12
|
readonly entityName: string;
|
|
13
|
-
readonly parent?: ICriteriaNode | undefined;
|
|
14
|
-
readonly key?:
|
|
13
|
+
readonly parent?: ICriteriaNode<T> | undefined;
|
|
14
|
+
readonly key?: EntityKey<T> | undefined;
|
|
15
15
|
payload: any;
|
|
16
|
-
prop?: EntityProperty
|
|
16
|
+
prop?: EntityProperty<T>;
|
|
17
17
|
index?: number;
|
|
18
|
-
constructor(metadata: MetadataStorage, entityName: string, parent?: ICriteriaNode | undefined, key?:
|
|
19
|
-
process
|
|
18
|
+
constructor(metadata: MetadataStorage, entityName: string, parent?: ICriteriaNode<T> | undefined, key?: EntityKey<T> | undefined, validate?: boolean);
|
|
19
|
+
process(qb: IQueryBuilder<T>, alias?: string): any;
|
|
20
20
|
shouldInline(payload: any): boolean;
|
|
21
|
-
willAutoJoin
|
|
21
|
+
willAutoJoin(qb: IQueryBuilder<T>, alias?: string): boolean;
|
|
22
22
|
shouldRename(payload: any): boolean;
|
|
23
23
|
renameFieldToPK<T>(qb: IQueryBuilder<T>): string;
|
|
24
24
|
getPath(addIndex?: boolean): string;
|
package/query/CriteriaNode.js
CHANGED
|
@@ -40,7 +40,7 @@ class CriteriaNode {
|
|
|
40
40
|
return false;
|
|
41
41
|
}
|
|
42
42
|
shouldRename(payload) {
|
|
43
|
-
const type = this.prop ? this.prop.
|
|
43
|
+
const type = this.prop ? this.prop.kind : null;
|
|
44
44
|
const composite = this.prop?.joinColumns ? this.prop.joinColumns.length > 1 : false;
|
|
45
45
|
const customExpression = CriteriaNode.isCustomExpression(this.key);
|
|
46
46
|
const scalar = payload === null || core_1.Utils.isPrimaryKey(payload) || payload instanceof RegExp || payload instanceof Date || customExpression;
|
|
@@ -49,17 +49,17 @@ class CriteriaNode {
|
|
|
49
49
|
return true;
|
|
50
50
|
}
|
|
51
51
|
switch (type) {
|
|
52
|
-
case core_1.
|
|
53
|
-
case core_1.
|
|
54
|
-
case core_1.
|
|
55
|
-
case core_1.
|
|
52
|
+
case core_1.ReferenceKind.MANY_TO_ONE: return false;
|
|
53
|
+
case core_1.ReferenceKind.ONE_TO_ONE: return !this.prop.owner;
|
|
54
|
+
case core_1.ReferenceKind.ONE_TO_MANY: return scalar || operator;
|
|
55
|
+
case core_1.ReferenceKind.MANY_TO_MANY: return scalar || operator;
|
|
56
56
|
default: return false;
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
renameFieldToPK(qb) {
|
|
60
60
|
const joinAlias = qb.getAliasForJoinPath(this.getPath());
|
|
61
61
|
const alias = joinAlias ?? qb.alias;
|
|
62
|
-
if (this.prop.
|
|
62
|
+
if (this.prop.kind === core_1.ReferenceKind.MANY_TO_MANY) {
|
|
63
63
|
return core_1.Utils.getPrimaryKeyHash(this.prop.inverseJoinColumns.map(col => `${alias}.${col}`));
|
|
64
64
|
}
|
|
65
65
|
// if we found a matching join, we need to use the target table column names, as we use that alias instead of the root
|
|
@@ -70,7 +70,7 @@ class CriteriaNode {
|
|
|
70
70
|
}
|
|
71
71
|
getPath(addIndex = false) {
|
|
72
72
|
// use index on parent only if we are processing to-many relation
|
|
73
|
-
const addParentIndex = this.prop && [core_1.
|
|
73
|
+
const addParentIndex = this.prop && [core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(this.prop.kind);
|
|
74
74
|
const parentPath = this.parent?.getPath(addParentIndex) ?? this.entityName;
|
|
75
75
|
const index = addIndex && this.index != null ? `[${this.index}]` : '';
|
|
76
76
|
// ignore group operators to allow easier mapping (e.g. for orderBy)
|
|
@@ -89,7 +89,7 @@ class CriteriaNode {
|
|
|
89
89
|
const customExpression = CriteriaNode.isCustomExpression(this.key);
|
|
90
90
|
const scalar = this.payload === null || core_1.Utils.isPrimaryKey(this.payload) || this.payload instanceof RegExp || this.payload instanceof Date || customExpression;
|
|
91
91
|
const operator = core_1.Utils.isObject(this.payload) && Object.keys(this.payload).every(k => core_1.Utils.isOperator(k, false));
|
|
92
|
-
return this.prop.
|
|
92
|
+
return this.prop.kind === core_1.ReferenceKind.MANY_TO_MANY && (scalar || operator);
|
|
93
93
|
}
|
|
94
94
|
getPivotPath(path) {
|
|
95
95
|
return `${path}[pivot]`;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { Dictionary, EntityMetadata, MetadataStorage } from '@mikro-orm/core';
|
|
1
|
+
import type { Dictionary, EntityKey, EntityMetadata, MetadataStorage } from '@mikro-orm/core';
|
|
2
2
|
import type { ICriteriaNode } from '../typings';
|
|
3
3
|
/**
|
|
4
4
|
* @internal
|
|
5
5
|
*/
|
|
6
6
|
export declare class CriteriaNodeFactory {
|
|
7
|
-
static createNode(metadata: MetadataStorage, entityName: string, payload: any, parent?: ICriteriaNode
|
|
8
|
-
static createScalarNode(metadata: MetadataStorage, entityName: string, payload: any, parent?: ICriteriaNode
|
|
9
|
-
static createArrayNode(metadata: MetadataStorage, entityName: string, payload: any[], parent?: ICriteriaNode
|
|
10
|
-
static createObjectNode(metadata: MetadataStorage, entityName: string, payload: Dictionary, parent?: ICriteriaNode
|
|
11
|
-
static createObjectItemNode(metadata: MetadataStorage, entityName: string, node: ICriteriaNode
|
|
7
|
+
static createNode<T extends object>(metadata: MetadataStorage, entityName: string, payload: any, parent?: ICriteriaNode<T>, key?: EntityKey<T>): ICriteriaNode<T>;
|
|
8
|
+
static createScalarNode<T extends object>(metadata: MetadataStorage, entityName: string, payload: any, parent?: ICriteriaNode<T>, key?: EntityKey<T>): ICriteriaNode<T>;
|
|
9
|
+
static createArrayNode<T extends object>(metadata: MetadataStorage, entityName: string, payload: any[], parent?: ICriteriaNode<T>, key?: EntityKey<T>): ICriteriaNode<T>;
|
|
10
|
+
static createObjectNode<T extends object>(metadata: MetadataStorage, entityName: string, payload: Dictionary, parent?: ICriteriaNode<T>, key?: EntityKey<T>): ICriteriaNode<T>;
|
|
11
|
+
static createObjectItemNode<T extends object>(metadata: MetadataStorage, entityName: string, node: ICriteriaNode<T>, payload: Dictionary, key: EntityKey<T>, meta?: EntityMetadata<T>): ICriteriaNode<T>;
|
|
12
12
|
}
|
|
@@ -12,7 +12,7 @@ const CriteriaNode_1 = require("./CriteriaNode");
|
|
|
12
12
|
class CriteriaNodeFactory {
|
|
13
13
|
static createNode(metadata, entityName, payload, parent, key) {
|
|
14
14
|
const customExpression = CriteriaNode_1.CriteriaNode.isCustomExpression(key || '');
|
|
15
|
-
const scalar = core_1.Utils.isPrimaryKey(payload) || payload instanceof RegExp || payload instanceof Date || customExpression;
|
|
15
|
+
const scalar = core_1.Utils.isPrimaryKey(payload) || core_1.Utils.isRawSql(payload) || payload instanceof RegExp || payload instanceof Date || customExpression;
|
|
16
16
|
if (Array.isArray(payload) && !scalar) {
|
|
17
17
|
return this.createArrayNode(metadata, entityName, payload, parent, key);
|
|
18
18
|
}
|
|
@@ -37,7 +37,7 @@ class CriteriaNodeFactory {
|
|
|
37
37
|
}
|
|
38
38
|
static createObjectNode(metadata, entityName, payload, parent, key) {
|
|
39
39
|
const meta = metadata.find(entityName);
|
|
40
|
-
if (!parent && Object.keys(payload).every(k => meta?.properties[k]?.
|
|
40
|
+
if (!parent && Object.keys(payload).every(k => meta?.properties[k]?.kind === core_1.ReferenceKind.SCALAR)) {
|
|
41
41
|
return this.createScalarNode(metadata, entityName, payload, parent, key);
|
|
42
42
|
}
|
|
43
43
|
const node = new ObjectCriteriaNode_1.ObjectCriteriaNode(metadata, entityName, parent, key);
|
|
@@ -47,24 +47,24 @@ class CriteriaNodeFactory {
|
|
|
47
47
|
}, {});
|
|
48
48
|
return node;
|
|
49
49
|
}
|
|
50
|
-
static createObjectItemNode(metadata, entityName, node, payload,
|
|
51
|
-
const prop = meta?.properties[
|
|
52
|
-
if (prop?.
|
|
53
|
-
const childEntity = prop && prop.
|
|
54
|
-
return this.createNode(metadata, childEntity, payload[
|
|
50
|
+
static createObjectItemNode(metadata, entityName, node, payload, key, meta) {
|
|
51
|
+
const prop = meta?.properties[key];
|
|
52
|
+
if (prop?.kind !== core_1.ReferenceKind.EMBEDDED) {
|
|
53
|
+
const childEntity = prop && prop.kind !== core_1.ReferenceKind.SCALAR ? prop.type : entityName;
|
|
54
|
+
return this.createNode(metadata, childEntity, payload[key], node, key);
|
|
55
55
|
}
|
|
56
|
-
const operator = Object.keys(payload[
|
|
56
|
+
const operator = Object.keys(payload[key]).some(f => core_1.Utils.isOperator(f));
|
|
57
57
|
if (operator) {
|
|
58
58
|
throw core_1.ValidationError.cannotUseOperatorsInsideEmbeddables(entityName, prop.name, payload);
|
|
59
59
|
}
|
|
60
|
-
const map = Object.keys(payload[
|
|
60
|
+
const map = Object.keys(payload[key]).reduce((oo, k) => {
|
|
61
61
|
if (!prop.embeddedProps[k]) {
|
|
62
62
|
throw core_1.ValidationError.invalidEmbeddableQuery(entityName, k, prop.type);
|
|
63
63
|
}
|
|
64
|
-
oo[prop.embeddedProps[k].name] = payload[
|
|
64
|
+
oo[prop.embeddedProps[k].name] = payload[key][k];
|
|
65
65
|
return oo;
|
|
66
66
|
}, {});
|
|
67
|
-
return this.createNode(metadata, entityName, map, node,
|
|
67
|
+
return this.createNode(metadata, entityName, map, node, key);
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
exports.CriteriaNodeFactory = CriteriaNodeFactory;
|
|
@@ -3,9 +3,9 @@ import type { IQueryBuilder } from '../typings';
|
|
|
3
3
|
/**
|
|
4
4
|
* @internal
|
|
5
5
|
*/
|
|
6
|
-
export declare class ObjectCriteriaNode extends CriteriaNode {
|
|
7
|
-
process
|
|
8
|
-
willAutoJoin
|
|
6
|
+
export declare class ObjectCriteriaNode<T extends object> extends CriteriaNode<T> {
|
|
7
|
+
process(qb: IQueryBuilder<T>, alias?: string): any;
|
|
8
|
+
willAutoJoin(qb: IQueryBuilder<T>, alias?: string): boolean;
|
|
9
9
|
shouldInline(payload: any): boolean;
|
|
10
10
|
private inlineChildPayload;
|
|
11
11
|
private shouldAutoJoin;
|
|
@@ -60,7 +60,7 @@ class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
|
60
60
|
const customExpression = ObjectCriteriaNode.isCustomExpression(this.key);
|
|
61
61
|
const scalar = core_1.Utils.isPrimaryKey(payload) || payload instanceof RegExp || payload instanceof Date || customExpression;
|
|
62
62
|
const operator = core_1.Utils.isObject(payload) && Object.keys(payload).every(k => core_1.Utils.isOperator(k, false));
|
|
63
|
-
return !!this.prop && this.prop.
|
|
63
|
+
return !!this.prop && this.prop.kind !== core_1.ReferenceKind.SCALAR && !scalar && !operator;
|
|
64
64
|
}
|
|
65
65
|
inlineChildPayload(o, payload, field, alias, childAlias) {
|
|
66
66
|
const prop = this.metadata.find(this.entityName).properties[field];
|
|
@@ -104,15 +104,15 @@ class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
|
104
104
|
if (!this.prop || !this.parent) {
|
|
105
105
|
return false;
|
|
106
106
|
}
|
|
107
|
-
const embeddable = this.prop.
|
|
108
|
-
const knownKey = [core_1.
|
|
107
|
+
const embeddable = this.prop.kind === core_1.ReferenceKind.EMBEDDED;
|
|
108
|
+
const knownKey = [core_1.ReferenceKind.SCALAR, core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.EMBEDDED].includes(this.prop.kind) || (this.prop.kind === core_1.ReferenceKind.ONE_TO_ONE && this.prop.owner);
|
|
109
109
|
const operatorKeys = knownKey && Object.keys(this.payload).every(key => core_1.Utils.isOperator(key, false));
|
|
110
110
|
const primaryKeys = knownKey && Object.keys(this.payload).every(key => {
|
|
111
111
|
const meta = this.metadata.find(this.entityName);
|
|
112
112
|
if (!meta.primaryKeys.includes(key)) {
|
|
113
113
|
return false;
|
|
114
114
|
}
|
|
115
|
-
if (!core_1.Utils.isPlainObject(this.payload[key].payload) || ![core_1.
|
|
115
|
+
if (!core_1.Utils.isPlainObject(this.payload[key].payload) || ![core_1.ReferenceKind.ONE_TO_ONE, core_1.ReferenceKind.MANY_TO_ONE].includes(meta.properties[key].kind)) {
|
|
116
116
|
return true;
|
|
117
117
|
}
|
|
118
118
|
return Object.keys(this.payload[key].payload).every(k => meta.properties[key].targetMeta.primaryKeys.includes(k));
|
|
@@ -125,7 +125,7 @@ class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
|
125
125
|
const scalar = core_1.Utils.isPrimaryKey(this.payload) || this.payload instanceof RegExp || this.payload instanceof Date || customExpression;
|
|
126
126
|
const operator = core_1.Utils.isPlainObject(this.payload) && Object.keys(this.payload).every(k => core_1.Utils.isOperator(k, false));
|
|
127
127
|
const field = `${alias}.${this.prop.name}`;
|
|
128
|
-
if (this.prop.
|
|
128
|
+
if (this.prop.kind === core_1.ReferenceKind.MANY_TO_MANY && (scalar || operator)) {
|
|
129
129
|
qb.join(field, nestedAlias, undefined, 'pivotJoin', this.getPath());
|
|
130
130
|
}
|
|
131
131
|
else {
|
package/query/QueryBuilder.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { inspect } from 'util';
|
|
1
3
|
import type { Knex } from 'knex';
|
|
2
4
|
import type { AnyEntity, ConnectionType, Dictionary, EntityData, EntityName, EntityProperty, FlushMode, GroupOperator, MetadataStorage, ObjectQuery, PopulateOptions, QBFilterQuery, QBQueryOrderMap, QueryResult, RequiredEntityData } from '@mikro-orm/core';
|
|
3
5
|
import { LockMode, PopulateHint, QueryFlag } from '@mikro-orm/core';
|
|
4
6
|
import { QueryType } from './enums';
|
|
5
7
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver';
|
|
6
|
-
import { QueryBuilderHelper } from './QueryBuilderHelper';
|
|
7
8
|
import type { Alias } from './QueryBuilderHelper';
|
|
9
|
+
import { QueryBuilderHelper } from './QueryBuilderHelper';
|
|
8
10
|
import type { SqlEntityManager } from '../SqlEntityManager';
|
|
9
11
|
import type { Field } from '../typings';
|
|
10
12
|
/**
|
|
@@ -75,7 +77,7 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
75
77
|
/**
|
|
76
78
|
* @internal
|
|
77
79
|
*/
|
|
78
|
-
constructor(entityName: EntityName<T> | QueryBuilder<T>, metadata: MetadataStorage, driver: AbstractSqlDriver, context?: Knex.Transaction<any, any[]> | undefined, alias?: string, connectionType?: ConnectionType | undefined, em?: SqlEntityManager<AbstractSqlDriver<import("
|
|
80
|
+
constructor(entityName: EntityName<T> | QueryBuilder<T>, metadata: MetadataStorage, driver: AbstractSqlDriver, context?: Knex.Transaction<any, any[]> | undefined, alias?: string, connectionType?: ConnectionType | undefined, em?: SqlEntityManager<AbstractSqlDriver<import("..").AbstractSqlConnection, import("..").AbstractSqlPlatform>> | undefined);
|
|
79
81
|
select(fields: Field<T> | Field<T>[], distinct?: boolean): SelectQueryBuilder<T>;
|
|
80
82
|
addSelect(fields: Field<T> | Field<T>[]): SelectQueryBuilder<T>;
|
|
81
83
|
distinct(): SelectQueryBuilder<T>;
|
|
@@ -90,7 +92,7 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
90
92
|
leftJoin(field: string, alias: string, cond?: QBFilterQuery): this;
|
|
91
93
|
joinAndSelect(field: string, alias: string, cond?: QBFilterQuery, type?: 'leftJoin' | 'innerJoin' | 'pivotJoin', path?: string): SelectQueryBuilder<T>;
|
|
92
94
|
leftJoinAndSelect(field: string, alias: string, cond?: QBFilterQuery): SelectQueryBuilder<T>;
|
|
93
|
-
protected getFieldsForJoinedLoad
|
|
95
|
+
protected getFieldsForJoinedLoad(prop: EntityProperty<T>, alias: string): Field<T>[];
|
|
94
96
|
withSubQuery(subQuery: Knex.QueryBuilder, alias: string): this;
|
|
95
97
|
where(cond: QBFilterQuery<T>, operator?: keyof typeof GroupOperator): this;
|
|
96
98
|
where(cond: string, params?: any[], operator?: keyof typeof GroupOperator): this;
|
|
@@ -114,7 +116,6 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
114
116
|
ref(field: string): Knex.Ref<string, {
|
|
115
117
|
[x: string]: string;
|
|
116
118
|
}>;
|
|
117
|
-
raw<R = Knex.Raw>(sql: string, bindings?: Knex.RawBinding[] | Knex.ValueDict): R;
|
|
118
119
|
limit(limit?: number, offset?: number): this;
|
|
119
120
|
offset(offset?: number): this;
|
|
120
121
|
withSchema(schema?: string): this;
|
|
@@ -179,6 +180,10 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
179
180
|
* Executes count query (without offset and limit), returning total count of results
|
|
180
181
|
*/
|
|
181
182
|
getCount(field?: string | string[], distinct?: boolean): Promise<number>;
|
|
183
|
+
/**
|
|
184
|
+
* Executes the query, returning both array of results and total count query (without offset and limit).
|
|
185
|
+
*/
|
|
186
|
+
getResultAndCount(): Promise<[T[], number]>;
|
|
182
187
|
/**
|
|
183
188
|
* Provides promise-like interface so we can await the QB instance.
|
|
184
189
|
*/
|
|
@@ -195,6 +200,7 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
195
200
|
private init;
|
|
196
201
|
private getQueryBase;
|
|
197
202
|
private finalize;
|
|
203
|
+
private processPopulateWhere;
|
|
198
204
|
private hasToManyJoins;
|
|
199
205
|
private wrapPaginateSubQuery;
|
|
200
206
|
private wrapModifySubQuery;
|
|
@@ -207,6 +213,7 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
207
213
|
private createQueryBuilderHelper;
|
|
208
214
|
private ensureFromClause;
|
|
209
215
|
private ensureNotFinalized;
|
|
216
|
+
[inspect.custom](depth: number): string;
|
|
210
217
|
}
|
|
211
218
|
export interface RunQueryBuilder<T extends object> extends Omit<QueryBuilder<T>, 'getResult' | 'getSingleResult' | 'getResultList' | 'where'> {
|
|
212
219
|
where(cond: QBFilterQuery<T> | string, params?: keyof typeof GroupOperator | any[], operator?: keyof typeof GroupOperator): this;
|
package/query/QueryBuilder.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.QueryBuilder = void 0;
|
|
4
|
+
const util_1 = require("util");
|
|
4
5
|
const core_1 = require("@mikro-orm/core");
|
|
5
6
|
const enums_1 = require("./enums");
|
|
6
7
|
const QueryBuilderHelper_1 = require("./QueryBuilderHelper");
|
|
@@ -115,7 +116,7 @@ class QueryBuilder {
|
|
|
115
116
|
this._fields = this.mainAlias.metadata.primaryKeys;
|
|
116
117
|
}
|
|
117
118
|
else {
|
|
118
|
-
this._fields = [
|
|
119
|
+
this._fields = [(0, core_1.raw)('*')];
|
|
119
120
|
}
|
|
120
121
|
if (distinct) {
|
|
121
122
|
this.flags.add(core_1.QueryFlag.DISTINCT);
|
|
@@ -277,11 +278,6 @@ class QueryBuilder {
|
|
|
277
278
|
ref(field) {
|
|
278
279
|
return this.knex.ref(field);
|
|
279
280
|
}
|
|
280
|
-
raw(sql, bindings = []) {
|
|
281
|
-
const raw = this.knex.raw(sql, bindings);
|
|
282
|
-
raw.__raw = true; // tag it as there is now way to check via `instanceof`
|
|
283
|
-
return raw;
|
|
284
|
-
}
|
|
285
281
|
limit(limit, offset = 0) {
|
|
286
282
|
this.ensureNotFinalized();
|
|
287
283
|
this._limit = limit;
|
|
@@ -360,7 +356,8 @@ class QueryBuilder {
|
|
|
360
356
|
core_1.Utils.runIfNotEmpty(() => {
|
|
361
357
|
const queryOrder = this.helper.getQueryOrder(this.type ?? enums_1.QueryType.SELECT, this._orderBy, this._populateMap);
|
|
362
358
|
if (queryOrder) {
|
|
363
|
-
|
|
359
|
+
qb.orderByRaw(queryOrder);
|
|
360
|
+
return;
|
|
364
361
|
}
|
|
365
362
|
}, this._orderBy);
|
|
366
363
|
core_1.Utils.runIfNotEmpty(() => qb.limit(this._limit), this._limit != null);
|
|
@@ -372,7 +369,7 @@ class QueryBuilder {
|
|
|
372
369
|
if (this.lockMode) {
|
|
373
370
|
this.helper.getLockSQL(qb, this.lockMode, this.lockTables);
|
|
374
371
|
}
|
|
375
|
-
this.helper.finalize(this.type ?? enums_1.QueryType.SELECT, qb, this.mainAlias.metadata);
|
|
372
|
+
this.helper.finalize(this.type ?? enums_1.QueryType.SELECT, qb, this.mainAlias.metadata, this._data);
|
|
376
373
|
return qb;
|
|
377
374
|
}
|
|
378
375
|
/**
|
|
@@ -464,7 +461,27 @@ class QueryBuilder {
|
|
|
464
461
|
if (this._joinedProps.size > 0) {
|
|
465
462
|
res = this.driver.mergeJoinedResult(res, this.mainAlias.metadata);
|
|
466
463
|
}
|
|
467
|
-
|
|
464
|
+
const entities = [];
|
|
465
|
+
function propagatePopulateHint(entity, hint) {
|
|
466
|
+
(0, core_1.helper)(entity).__serializationContext.populate ??= hint;
|
|
467
|
+
hint.forEach(pop => {
|
|
468
|
+
const value = entity[pop.field];
|
|
469
|
+
if (core_1.Utils.isEntity(value, true)) {
|
|
470
|
+
(0, core_1.helper)(value).populated();
|
|
471
|
+
propagatePopulateHint(value, pop.children ?? []);
|
|
472
|
+
}
|
|
473
|
+
else if (core_1.Utils.isCollection(value)) {
|
|
474
|
+
value.populated();
|
|
475
|
+
value.getItems(false).forEach(item => propagatePopulateHint(item, pop.children ?? []));
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
for (const r of res) {
|
|
480
|
+
const entity = this.em.map(this.mainAlias.entityName, r, { schema: this._schema });
|
|
481
|
+
propagatePopulateHint(entity, this._populate);
|
|
482
|
+
entities.push(entity);
|
|
483
|
+
}
|
|
484
|
+
return entities;
|
|
468
485
|
}
|
|
469
486
|
/**
|
|
470
487
|
* Executes the query, returning the first result or null
|
|
@@ -488,11 +505,24 @@ class QueryBuilder {
|
|
|
488
505
|
}
|
|
489
506
|
return res ? +res.count : 0;
|
|
490
507
|
}
|
|
508
|
+
/**
|
|
509
|
+
* Executes the query, returning both array of results and total count query (without offset and limit).
|
|
510
|
+
*/
|
|
511
|
+
async getResultAndCount() {
|
|
512
|
+
return Promise.all([
|
|
513
|
+
this.getResultList(),
|
|
514
|
+
this.getCount(),
|
|
515
|
+
]);
|
|
516
|
+
}
|
|
491
517
|
/**
|
|
492
518
|
* Provides promise-like interface so we can await the QB instance.
|
|
493
519
|
*/
|
|
494
520
|
then(onfulfilled, onrejected) {
|
|
495
|
-
|
|
521
|
+
let type = this.type ?? enums_1.QueryType.SELECT;
|
|
522
|
+
if (this.flags.has(core_1.QueryFlag.UPDATE_SUB_QUERY) || this.flags.has(core_1.QueryFlag.DELETE_SUB_QUERY)) {
|
|
523
|
+
type = enums_1.QueryType.UPDATE;
|
|
524
|
+
}
|
|
525
|
+
switch (type) {
|
|
496
526
|
case enums_1.QueryType.INSERT:
|
|
497
527
|
case enums_1.QueryType.UPDATE:
|
|
498
528
|
case enums_1.QueryType.DELETE:
|
|
@@ -515,7 +545,10 @@ class QueryBuilder {
|
|
|
515
545
|
/* istanbul ignore next */
|
|
516
546
|
alias = meta?.properties[f]?.fieldNames[0] ?? alias;
|
|
517
547
|
}
|
|
518
|
-
|
|
548
|
+
const ret = qb.as(alias);
|
|
549
|
+
// tag the instance, so it is possible to detect it easily
|
|
550
|
+
Object.defineProperty(ret, '__as', { enumerable: false, value: alias });
|
|
551
|
+
return ret;
|
|
519
552
|
}
|
|
520
553
|
clone() {
|
|
521
554
|
const qb = new QueryBuilder(this.mainAlias.entityName, this.metadata, this.driver, this.context, this.mainAlias.aliasName, this.connectionType, this.em);
|
|
@@ -570,11 +603,11 @@ class QueryBuilder {
|
|
|
570
603
|
aliased: !this.type || [enums_1.QueryType.SELECT, enums_1.QueryType.COUNT].includes(this.type),
|
|
571
604
|
});
|
|
572
605
|
let aliasedName = `${fromAlias}.${prop.name}#${alias}`;
|
|
573
|
-
path
|
|
574
|
-
if (prop.
|
|
606
|
+
path ??= `${(Object.values(this._joins).find(j => j.alias === fromAlias)?.path ?? entityName)}.${prop.name}`;
|
|
607
|
+
if (prop.kind === core_1.ReferenceKind.ONE_TO_MANY) {
|
|
575
608
|
this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond);
|
|
576
609
|
}
|
|
577
|
-
else if (prop.
|
|
610
|
+
else if (prop.kind === core_1.ReferenceKind.MANY_TO_MANY) {
|
|
578
611
|
let pivotAlias = alias;
|
|
579
612
|
if (type !== 'pivotJoin') {
|
|
580
613
|
const oldPivotAlias = this.getAliasForJoinPath(path + '[pivot]');
|
|
@@ -585,7 +618,7 @@ class QueryBuilder {
|
|
|
585
618
|
Object.assign(this._joins, joins);
|
|
586
619
|
this.createAlias(prop.pivotEntity, pivotAlias);
|
|
587
620
|
}
|
|
588
|
-
else if (prop.
|
|
621
|
+
else if (prop.kind === core_1.ReferenceKind.ONE_TO_ONE) {
|
|
589
622
|
this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond);
|
|
590
623
|
}
|
|
591
624
|
else { // MANY_TO_ONE
|
|
@@ -600,16 +633,18 @@ class QueryBuilder {
|
|
|
600
633
|
const ret = [];
|
|
601
634
|
fields.forEach(field => {
|
|
602
635
|
if (!core_1.Utils.isString(field)) {
|
|
603
|
-
|
|
636
|
+
ret.push(field);
|
|
637
|
+
return;
|
|
604
638
|
}
|
|
605
639
|
const join = Object.keys(this._joins).find(k => field === k.substring(0, k.indexOf('#')));
|
|
606
640
|
if (join && type === 'where') {
|
|
607
|
-
|
|
641
|
+
ret.push(...this.helper.mapJoinColumns(this.type ?? enums_1.QueryType.SELECT, this._joins[join]));
|
|
642
|
+
return;
|
|
608
643
|
}
|
|
609
644
|
const [a, f] = this.helper.splitField(field);
|
|
610
645
|
const prop = this.helper.getProperty(f, a);
|
|
611
646
|
/* istanbul ignore next */
|
|
612
|
-
if (prop && [core_1.
|
|
647
|
+
if (prop && [core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
|
|
613
648
|
return;
|
|
614
649
|
}
|
|
615
650
|
if (prop?.embedded) {
|
|
@@ -617,7 +652,7 @@ class QueryBuilder {
|
|
|
617
652
|
ret.push(fieldName);
|
|
618
653
|
return;
|
|
619
654
|
}
|
|
620
|
-
if (prop?.
|
|
655
|
+
if (prop?.kind === core_1.ReferenceKind.EMBEDDED) {
|
|
621
656
|
if (prop.object) {
|
|
622
657
|
ret.push(this.helper.mapper(prop.fieldNames[0], this.type));
|
|
623
658
|
}
|
|
@@ -649,7 +684,7 @@ class QueryBuilder {
|
|
|
649
684
|
const cols = this.helper.mapJoinColumns(this.type ?? enums_1.QueryType.SELECT, this._joins[f]);
|
|
650
685
|
ret.push(...cols);
|
|
651
686
|
}
|
|
652
|
-
if (this._joins[f].prop.
|
|
687
|
+
if (this._joins[f].prop.kind !== core_1.ReferenceKind.ONE_TO_ONE && this._joins[f].inverseJoinColumns) {
|
|
653
688
|
this._joins[f].inverseJoinColumns.forEach(inverseJoinColumn => {
|
|
654
689
|
core_1.Utils.renameKey(this._cond, inverseJoinColumn, `${this._joins[f].alias}.${inverseJoinColumn}`);
|
|
655
690
|
});
|
|
@@ -668,7 +703,7 @@ class QueryBuilder {
|
|
|
668
703
|
}
|
|
669
704
|
if (data) {
|
|
670
705
|
if (core_1.Utils.isEntity(data)) {
|
|
671
|
-
data = (0, core_1.
|
|
706
|
+
data = this.em?.getComparator().prepareEntity(data) ?? (0, core_1.serialize)(data);
|
|
672
707
|
}
|
|
673
708
|
this._data = this.helper.processData(data, this.flags.has(core_1.QueryFlag.CONVERT_CUSTOM_TYPES));
|
|
674
709
|
}
|
|
@@ -733,7 +768,7 @@ class QueryBuilder {
|
|
|
733
768
|
if (meta && this.flags.has(core_1.QueryFlag.AUTO_JOIN_ONE_TO_ONE_OWNER)) {
|
|
734
769
|
const relationsToPopulate = this._populate.map(({ field }) => field);
|
|
735
770
|
meta.relations
|
|
736
|
-
.filter(prop => prop.
|
|
771
|
+
.filter(prop => prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner && !relationsToPopulate.includes(prop.name))
|
|
737
772
|
.map(prop => ({ field: prop.name }))
|
|
738
773
|
.forEach(item => this._populate.push(item));
|
|
739
774
|
}
|
|
@@ -742,7 +777,8 @@ class QueryBuilder {
|
|
|
742
777
|
const aliasedField = `${fromAlias}.${fromField}`;
|
|
743
778
|
const join = Object.keys(this._joins).find(k => `${aliasedField}#${this._joins[k].alias}` === k);
|
|
744
779
|
if (join && this._joins[join] && this.helper.isOneToOneInverse(fromField)) {
|
|
745
|
-
|
|
780
|
+
this._populateMap[join] = this._joins[join].alias;
|
|
781
|
+
return;
|
|
746
782
|
}
|
|
747
783
|
if (this.metadata.find(field)?.pivotTable) { // pivot table entity
|
|
748
784
|
this.autoJoinPivotTable(field);
|
|
@@ -766,6 +802,7 @@ class QueryBuilder {
|
|
|
766
802
|
.filter(field => !this._fields.includes(field))
|
|
767
803
|
.forEach(field => this.addSelect(field));
|
|
768
804
|
}
|
|
805
|
+
this.processPopulateWhere();
|
|
769
806
|
core_1.QueryHelper.processObjectParams(this._data);
|
|
770
807
|
core_1.QueryHelper.processObjectParams(this._cond);
|
|
771
808
|
core_1.QueryHelper.processObjectParams(this._having);
|
|
@@ -781,17 +818,54 @@ class QueryBuilder {
|
|
|
781
818
|
}
|
|
782
819
|
this.finalized = true;
|
|
783
820
|
}
|
|
821
|
+
processPopulateWhere() {
|
|
822
|
+
if (this._populateWhere == null || this._populateWhere === core_1.PopulateHint.ALL) {
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
const joins = Object.values(this._joins);
|
|
826
|
+
joins.forEach(join => {
|
|
827
|
+
join.cond_ = join.cond;
|
|
828
|
+
join.cond = {};
|
|
829
|
+
});
|
|
830
|
+
const replaceOnConditions = (cond) => {
|
|
831
|
+
Object.keys(cond).forEach(k => {
|
|
832
|
+
if (core_1.Utils.isOperator(k)) {
|
|
833
|
+
if (Array.isArray(cond[k])) {
|
|
834
|
+
return cond[k].forEach((c) => replaceOnConditions(c));
|
|
835
|
+
}
|
|
836
|
+
return replaceOnConditions(cond[k]);
|
|
837
|
+
}
|
|
838
|
+
const [a] = this.helper.splitField(k);
|
|
839
|
+
const join = joins.find(j => j.alias === a);
|
|
840
|
+
if (join) {
|
|
841
|
+
join.cond = { ...join.cond, [k]: cond[k] };
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
};
|
|
845
|
+
if (this._populateWhere === core_1.PopulateHint.INFER) {
|
|
846
|
+
replaceOnConditions(this._cond);
|
|
847
|
+
}
|
|
848
|
+
else if (typeof this._populateWhere === 'object') {
|
|
849
|
+
const cond = CriteriaNodeFactory_1.CriteriaNodeFactory
|
|
850
|
+
.createNode(this.metadata, this.mainAlias.entityName, this._populateWhere)
|
|
851
|
+
.process(this);
|
|
852
|
+
replaceOnConditions(cond);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
784
855
|
hasToManyJoins() {
|
|
785
856
|
return Object.values(this._joins).some(join => {
|
|
786
|
-
return [core_1.
|
|
857
|
+
return [core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(join.prop.kind);
|
|
787
858
|
});
|
|
788
859
|
}
|
|
789
860
|
wrapPaginateSubQuery(meta) {
|
|
790
861
|
const pks = this.prepareFields(meta.primaryKeys, 'sub-query');
|
|
791
862
|
const subQuery = this.clone().select(pks).groupBy(pks).limit(this._limit);
|
|
863
|
+
// revert the on conditions added via populateWhere, we want to apply those only once
|
|
864
|
+
Object.values(subQuery._joins).forEach(join => join.cond = join.cond_ ?? {});
|
|
792
865
|
if (this._offset) {
|
|
793
866
|
subQuery.offset(this._offset);
|
|
794
867
|
}
|
|
868
|
+
const addToSelect = [];
|
|
795
869
|
if (this._orderBy.length > 0) {
|
|
796
870
|
const orderBy = [];
|
|
797
871
|
for (const orderMap of this._orderBy) {
|
|
@@ -799,28 +873,37 @@ class QueryBuilder {
|
|
|
799
873
|
const [a, f] = this.helper.splitField(field);
|
|
800
874
|
const prop = this.helper.getProperty(f, a);
|
|
801
875
|
const type = this.platform.castColumn(prop);
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
876
|
+
const fieldName = this.helper.mapper(field, this.type, undefined, null);
|
|
877
|
+
if (!prop?.persist && !prop?.formula) {
|
|
878
|
+
addToSelect.push(fieldName);
|
|
879
|
+
}
|
|
880
|
+
orderBy.push({ [`min(${this.ref(fieldName)}${type})`]: direction });
|
|
805
881
|
}
|
|
806
882
|
}
|
|
807
883
|
subQuery.orderBy(orderBy);
|
|
808
884
|
}
|
|
809
885
|
subQuery.finalized = true;
|
|
810
886
|
const knexQuery = subQuery.as(this.mainAlias.aliasName).clearSelect().select(pks);
|
|
887
|
+
if (addToSelect.length > 0) {
|
|
888
|
+
addToSelect.forEach(prop => {
|
|
889
|
+
const field = this._fields.find(field => {
|
|
890
|
+
if (typeof field === 'object' && field && '__as' in field) {
|
|
891
|
+
return field.__as === prop;
|
|
892
|
+
}
|
|
893
|
+
// not perfect, but should work most of the time, ideally we should check only the alias (`... as alias`)
|
|
894
|
+
return field.toString().includes(prop);
|
|
895
|
+
});
|
|
896
|
+
if (field) {
|
|
897
|
+
knexQuery.select(field);
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
}
|
|
811
901
|
// multiple sub-queries are needed to get around mysql limitations with order by + limit + where in + group by (o.O)
|
|
812
902
|
// https://stackoverflow.com/questions/17892762/mysql-this-version-of-mysql-doesnt-yet-support-limit-in-all-any-some-subqu
|
|
813
903
|
const subSubQuery = this.getKnex().select(pks).from(knexQuery);
|
|
814
904
|
this._limit = undefined;
|
|
815
905
|
this._offset = undefined;
|
|
816
|
-
const cond = this._cond;
|
|
817
906
|
this.select(this._fields).where({ [core_1.Utils.getPrimaryKeyHash(meta.primaryKeys)]: { $in: subSubQuery } });
|
|
818
|
-
if (this._populateWhere === core_1.PopulateHint.INFER) {
|
|
819
|
-
this.andWhere(cond);
|
|
820
|
-
}
|
|
821
|
-
else if (typeof this._populateWhere === 'object') {
|
|
822
|
-
this.andWhere(this._populateWhere);
|
|
823
|
-
}
|
|
824
907
|
}
|
|
825
908
|
wrapModifySubQuery(meta) {
|
|
826
909
|
const subQuery = this.clone();
|
|
@@ -864,11 +947,11 @@ class QueryBuilder {
|
|
|
864
947
|
fromSubQuery(target, aliasName) {
|
|
865
948
|
const subQuery = target.getKnexQuery();
|
|
866
949
|
const { entityName } = target.mainAlias;
|
|
867
|
-
aliasName
|
|
950
|
+
aliasName ??= this.getNextAlias(entityName);
|
|
868
951
|
this.createMainAlias(entityName, aliasName, subQuery);
|
|
869
952
|
}
|
|
870
953
|
fromEntityName(entityName, aliasName) {
|
|
871
|
-
aliasName
|
|
954
|
+
aliasName ??= this._mainAlias?.aliasName ?? this.getNextAlias(entityName);
|
|
872
955
|
this.createMainAlias(entityName, aliasName);
|
|
873
956
|
}
|
|
874
957
|
createQueryBuilderHelper() {
|
|
@@ -885,5 +968,27 @@ class QueryBuilder {
|
|
|
885
968
|
throw new Error('This QueryBuilder instance is already finalized, clone it first if you want to modify it.');
|
|
886
969
|
}
|
|
887
970
|
}
|
|
971
|
+
/* istanbul ignore next */
|
|
972
|
+
[util_1.inspect.custom](depth) {
|
|
973
|
+
const object = { ...this };
|
|
974
|
+
const hidden = ['metadata', 'driver', 'context', 'platform', 'knex', 'type'];
|
|
975
|
+
Object.keys(object).filter(k => k.startsWith('_')).forEach(k => delete object[k]);
|
|
976
|
+
Object.keys(object).filter(k => object[k] == null).forEach(k => delete object[k]);
|
|
977
|
+
hidden.forEach(k => delete object[k]);
|
|
978
|
+
let prefix = this.type ? this.type.substring(0, 1) + this.type.toLowerCase().substring(1) : '';
|
|
979
|
+
if (this._data) {
|
|
980
|
+
object.data = this._data;
|
|
981
|
+
}
|
|
982
|
+
if (!core_1.Utils.isEmpty(this._cond)) {
|
|
983
|
+
object.where = this._cond;
|
|
984
|
+
}
|
|
985
|
+
if (this._onConflict?.[0]) {
|
|
986
|
+
prefix = 'Upsert';
|
|
987
|
+
object.onConflict = this._onConflict[0];
|
|
988
|
+
}
|
|
989
|
+
const name = this._mainAlias ? `${prefix}QueryBuilder<${this._mainAlias?.entityName}>` : 'QueryBuilder';
|
|
990
|
+
const ret = (0, util_1.inspect)(object, { depth });
|
|
991
|
+
return ret === '[Object]' ? `[${name}]` : name + ' ' + ret;
|
|
992
|
+
}
|
|
888
993
|
}
|
|
889
994
|
exports.QueryBuilder = QueryBuilder;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
-
import type { Dictionary, EntityData, EntityMetadata, EntityProperty, FlatQueryOrderMap, QBFilterQuery } from '@mikro-orm/core';
|
|
2
|
+
import type { Dictionary, EntityData, EntityKey, EntityMetadata, EntityProperty, FlatQueryOrderMap, QBFilterQuery } from '@mikro-orm/core';
|
|
3
3
|
import { LockMode } from '@mikro-orm/core';
|
|
4
4
|
import { QueryType } from './enums';
|
|
5
5
|
import type { Field, JoinOptions } from '../typings';
|
|
@@ -48,8 +48,8 @@ export declare class QueryBuilderHelper {
|
|
|
48
48
|
private getOperatorReplacement;
|
|
49
49
|
getQueryOrder(type: QueryType, orderBy: FlatQueryOrderMap | FlatQueryOrderMap[], populate: Dictionary<string>): string;
|
|
50
50
|
getQueryOrderFromObject(type: QueryType, orderBy: FlatQueryOrderMap, populate: Dictionary<string>): string;
|
|
51
|
-
finalize(type: QueryType, qb: Knex.QueryBuilder, meta?: EntityMetadata): void;
|
|
52
|
-
splitField(field:
|
|
51
|
+
finalize(type: QueryType, qb: Knex.QueryBuilder, meta?: EntityMetadata, data?: Dictionary): void;
|
|
52
|
+
splitField<T>(field: EntityKey<T>, greedyAlias?: boolean): [string, EntityKey<T>];
|
|
53
53
|
getLockSQL(qb: Knex.QueryBuilder, lockMode: LockMode, lockTables?: string[]): void;
|
|
54
54
|
updateVersionProperty(qb: Knex.QueryBuilder, data: Dictionary): void;
|
|
55
55
|
static isCustomExpression(field: string, hasAlias?: boolean): boolean;
|