@mikro-orm/knex 7.0.0-dev.9 → 7.0.0-dev.90
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 +11 -5
- package/AbstractSqlConnection.js +78 -32
- package/AbstractSqlDriver.d.ts +9 -5
- package/AbstractSqlDriver.js +267 -227
- package/AbstractSqlPlatform.js +5 -5
- package/PivotCollectionPersister.d.ts +8 -4
- package/PivotCollectionPersister.js +55 -31
- package/README.md +3 -2
- package/SqlEntityManager.d.ts +10 -2
- package/SqlEntityManager.js +11 -2
- package/dialects/mssql/MsSqlNativeQueryBuilder.d.ts +2 -0
- package/dialects/mssql/MsSqlNativeQueryBuilder.js +42 -3
- package/dialects/mysql/MySqlExceptionConverter.d.ts +3 -3
- package/dialects/mysql/MySqlExceptionConverter.js +4 -5
- package/dialects/mysql/MySqlSchemaHelper.js +2 -2
- package/dialects/postgresql/PostgreSqlTableCompiler.d.ts +1 -0
- package/dialects/postgresql/PostgreSqlTableCompiler.js +1 -0
- package/dialects/sqlite/BaseSqliteConnection.d.ts +3 -2
- package/dialects/sqlite/BaseSqliteConnection.js +2 -14
- package/dialects/sqlite/BaseSqlitePlatform.js +1 -2
- package/dialects/sqlite/SqliteExceptionConverter.d.ts +2 -2
- package/dialects/sqlite/SqliteExceptionConverter.js +6 -4
- package/dialects/sqlite/SqliteSchemaHelper.js +5 -6
- package/index.d.ts +2 -1
- package/index.js +2 -1
- package/package.json +5 -5
- package/plugin/index.d.ts +53 -0
- package/plugin/index.js +42 -0
- package/plugin/transformer.d.ts +115 -0
- package/plugin/transformer.js +883 -0
- package/query/ArrayCriteriaNode.d.ts +1 -0
- package/query/ArrayCriteriaNode.js +3 -0
- package/query/CriteriaNode.d.ts +4 -5
- package/query/CriteriaNode.js +13 -9
- package/query/CriteriaNodeFactory.js +12 -7
- package/query/NativeQueryBuilder.js +1 -1
- package/query/ObjectCriteriaNode.d.ts +1 -0
- package/query/ObjectCriteriaNode.js +35 -8
- package/query/QueryBuilder.d.ts +59 -10
- package/query/QueryBuilder.js +166 -50
- package/query/QueryBuilderHelper.d.ts +1 -1
- package/query/QueryBuilderHelper.js +20 -14
- package/query/ScalarCriteriaNode.d.ts +3 -3
- package/query/ScalarCriteriaNode.js +9 -7
- package/query/index.d.ts +1 -0
- package/query/index.js +1 -0
- package/query/raw.d.ts +59 -0
- package/query/raw.js +68 -0
- package/query/rawKnex.d.ts +58 -0
- package/query/rawKnex.js +72 -0
- package/schema/DatabaseSchema.js +25 -4
- package/schema/DatabaseTable.d.ts +5 -4
- package/schema/DatabaseTable.js +65 -34
- package/schema/SchemaComparator.js +5 -6
- package/schema/SchemaHelper.d.ts +2 -0
- package/schema/SchemaHelper.js +14 -10
- package/schema/SqlSchemaGenerator.d.ts +13 -6
- package/schema/SqlSchemaGenerator.js +41 -20
- package/typings.d.ts +85 -3
|
@@ -7,4 +7,5 @@ export declare class ArrayCriteriaNode<T extends object> extends CriteriaNode<T>
|
|
|
7
7
|
process(qb: IQueryBuilder<T>, options?: ICriteriaNodeProcessOptions): any;
|
|
8
8
|
unwrap(): any;
|
|
9
9
|
willAutoJoin(qb: IQueryBuilder<T>, alias?: string, options?: ICriteriaNodeProcessOptions): any;
|
|
10
|
+
isStrict(): boolean;
|
|
10
11
|
}
|
package/query/CriteriaNode.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { inspect } from 'node:util';
|
|
2
1
|
import { type EntityKey, type EntityProperty, type MetadataStorage } from '@mikro-orm/core';
|
|
3
2
|
import type { ICriteriaNode, ICriteriaNodeProcessOptions, IQueryBuilder } from '../typings.js';
|
|
4
3
|
/**
|
|
@@ -11,20 +10,20 @@ export declare class CriteriaNode<T extends object> implements ICriteriaNode<T>
|
|
|
11
10
|
readonly entityName: string;
|
|
12
11
|
readonly parent?: ICriteriaNode<T> | undefined;
|
|
13
12
|
readonly key?: EntityKey<T> | undefined;
|
|
13
|
+
readonly strict: boolean;
|
|
14
14
|
payload: any;
|
|
15
15
|
prop?: EntityProperty<T>;
|
|
16
16
|
index?: number;
|
|
17
|
-
constructor(metadata: MetadataStorage, entityName: string, parent?: ICriteriaNode<T> | undefined, key?: EntityKey<T> | undefined, validate?: boolean);
|
|
17
|
+
constructor(metadata: MetadataStorage, entityName: string, parent?: ICriteriaNode<T> | undefined, key?: EntityKey<T> | undefined, validate?: boolean, strict?: boolean);
|
|
18
18
|
process(qb: IQueryBuilder<T>, options?: ICriteriaNodeProcessOptions): any;
|
|
19
19
|
unwrap(): any;
|
|
20
20
|
shouldInline(payload: any): boolean;
|
|
21
21
|
willAutoJoin(qb: IQueryBuilder<T>, alias?: string, options?: ICriteriaNodeProcessOptions): boolean;
|
|
22
22
|
shouldRename(payload: any): boolean;
|
|
23
|
-
renameFieldToPK<T>(qb: IQueryBuilder<T
|
|
23
|
+
renameFieldToPK<T>(qb: IQueryBuilder<T>, ownerAlias?: string): string;
|
|
24
24
|
getPath(addIndex?: boolean): string;
|
|
25
25
|
private isPivotJoin;
|
|
26
26
|
getPivotPath(path: string): string;
|
|
27
27
|
aliased(field: string, alias?: string): string;
|
|
28
|
-
|
|
29
|
-
[inspect.custom](): string;
|
|
28
|
+
isStrict(): boolean;
|
|
30
29
|
}
|
package/query/CriteriaNode.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { inspect } from '
|
|
2
|
-
import { RawQueryFragment, ReferenceKind, Utils, } from '@mikro-orm/core';
|
|
1
|
+
import { RawQueryFragment, ReferenceKind, Utils, inspect, } from '@mikro-orm/core';
|
|
3
2
|
/**
|
|
4
3
|
* Helper for working with deeply nested where/orderBy/having criteria. Uses composite pattern to build tree from the payload.
|
|
5
4
|
* Auto-joins relations and converts payload from { books: { publisher: { name: '...' } } } to { 'publisher_alias.name': '...' }
|
|
@@ -10,14 +9,16 @@ export class CriteriaNode {
|
|
|
10
9
|
entityName;
|
|
11
10
|
parent;
|
|
12
11
|
key;
|
|
12
|
+
strict;
|
|
13
13
|
payload;
|
|
14
14
|
prop;
|
|
15
15
|
index;
|
|
16
|
-
constructor(metadata, entityName, parent, key, validate = true) {
|
|
16
|
+
constructor(metadata, entityName, parent, key, validate = true, strict = false) {
|
|
17
17
|
this.metadata = metadata;
|
|
18
18
|
this.entityName = entityName;
|
|
19
19
|
this.parent = parent;
|
|
20
20
|
this.key = key;
|
|
21
|
+
this.strict = strict;
|
|
21
22
|
const meta = parent && metadata.find(parent.entityName);
|
|
22
23
|
if (meta && key) {
|
|
23
24
|
const pks = Utils.splitPrimaryKeys(key);
|
|
@@ -65,13 +66,13 @@ export class CriteriaNode {
|
|
|
65
66
|
default: return false;
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
|
-
renameFieldToPK(qb) {
|
|
69
|
-
|
|
69
|
+
renameFieldToPK(qb, ownerAlias) {
|
|
70
|
+
const joinAlias = qb.getAliasForJoinPath(this.getPath(), { matchPopulateJoins: true });
|
|
70
71
|
if (!joinAlias && this.parent && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind) && this.prop.owner) {
|
|
71
|
-
|
|
72
|
-
return Utils.getPrimaryKeyHash(this.prop.joinColumns.map(col => `${
|
|
72
|
+
const alias = qb.getAliasForJoinPath(this.parent.getPath()) ?? ownerAlias ?? qb.alias;
|
|
73
|
+
return Utils.getPrimaryKeyHash(this.prop.joinColumns.map(col => `${alias}.${col}`));
|
|
73
74
|
}
|
|
74
|
-
const alias = joinAlias ?? qb.alias;
|
|
75
|
+
const alias = joinAlias ?? ownerAlias ?? qb.alias;
|
|
75
76
|
if (this.prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
76
77
|
return Utils.getPrimaryKeyHash(this.prop.inverseJoinColumns.map(col => `${alias}.${col}`));
|
|
77
78
|
}
|
|
@@ -106,8 +107,11 @@ export class CriteriaNode {
|
|
|
106
107
|
aliased(field, alias) {
|
|
107
108
|
return alias ? `${alias}.${field}` : field;
|
|
108
109
|
}
|
|
110
|
+
isStrict() {
|
|
111
|
+
return this.strict;
|
|
112
|
+
}
|
|
109
113
|
/** @ignore */
|
|
110
|
-
[inspect.custom]() {
|
|
114
|
+
[Symbol.for('nodejs.util.inspect.custom')]() {
|
|
111
115
|
const o = {};
|
|
112
116
|
['entityName', 'key', 'index', 'payload']
|
|
113
117
|
.filter(k => this[k] !== undefined)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isRaw, JsonType, RawQueryFragment, ReferenceKind, Utils, ValidationError, } from '@mikro-orm/core';
|
|
1
|
+
import { GroupOperator, isRaw, JsonType, RawQueryFragment, ReferenceKind, Utils, ValidationError, } from '@mikro-orm/core';
|
|
2
2
|
import { ObjectCriteriaNode } from './ObjectCriteriaNode.js';
|
|
3
3
|
import { ArrayCriteriaNode } from './ArrayCriteriaNode.js';
|
|
4
4
|
import { ScalarCriteriaNode } from './ScalarCriteriaNode.js';
|
|
@@ -36,7 +36,7 @@ export class CriteriaNodeFactory {
|
|
|
36
36
|
}
|
|
37
37
|
static createObjectNode(metadata, entityName, payload, parent, key) {
|
|
38
38
|
const meta = metadata.find(entityName);
|
|
39
|
-
const node = new ObjectCriteriaNode(metadata, entityName, parent, key);
|
|
39
|
+
const node = new ObjectCriteriaNode(metadata, entityName, parent, key, true, payload.__strict);
|
|
40
40
|
node.payload = {};
|
|
41
41
|
for (const key of Object.keys(payload)) {
|
|
42
42
|
node.payload[key] = this.createObjectItemNode(metadata, entityName, node, payload, key, meta);
|
|
@@ -46,10 +46,14 @@ export class CriteriaNodeFactory {
|
|
|
46
46
|
static createObjectItemNode(metadata, entityName, node, payload, key, meta) {
|
|
47
47
|
const prop = meta?.properties[key];
|
|
48
48
|
const childEntity = prop && prop.kind !== ReferenceKind.SCALAR ? prop.type : entityName;
|
|
49
|
-
|
|
49
|
+
const isNotEmbedded = prop?.kind !== ReferenceKind.EMBEDDED;
|
|
50
|
+
if (isNotEmbedded && prop?.customType instanceof JsonType) {
|
|
50
51
|
return this.createScalarNode(metadata, childEntity, payload[key], node, key);
|
|
51
52
|
}
|
|
52
|
-
if (prop?.kind
|
|
53
|
+
if (prop?.kind === ReferenceKind.SCALAR && payload[key] != null && Object.keys(payload[key]).some(f => f in GroupOperator)) {
|
|
54
|
+
throw ValidationError.cannotUseGroupOperatorsInsideScalars(entityName, prop.name, payload);
|
|
55
|
+
}
|
|
56
|
+
if (isNotEmbedded) {
|
|
53
57
|
return this.createNode(metadata, childEntity, payload[key], node, key);
|
|
54
58
|
}
|
|
55
59
|
if (payload[key] == null) {
|
|
@@ -66,11 +70,12 @@ export class CriteriaNodeFactory {
|
|
|
66
70
|
throw ValidationError.cannotUseOperatorsInsideEmbeddables(entityName, prop.name, payload);
|
|
67
71
|
}
|
|
68
72
|
const map = Object.keys(payload[key]).reduce((oo, k) => {
|
|
69
|
-
|
|
73
|
+
const embeddedProp = prop.embeddedProps[k] ?? Object.values(prop.embeddedProps).find(p => p.name === k);
|
|
74
|
+
if (!embeddedProp && !allowedOperators.includes(k)) {
|
|
70
75
|
throw ValidationError.invalidEmbeddableQuery(entityName, k, prop.type);
|
|
71
76
|
}
|
|
72
|
-
if (
|
|
73
|
-
oo[
|
|
77
|
+
if (embeddedProp) {
|
|
78
|
+
oo[embeddedProp.name] = payload[key][k];
|
|
74
79
|
}
|
|
75
80
|
else if (typeof payload[key][k] === 'object') {
|
|
76
81
|
oo[k] = JSON.stringify(payload[key][k]);
|
|
@@ -261,7 +261,7 @@ export class NativeQueryBuilder {
|
|
|
261
261
|
}
|
|
262
262
|
if (this.options.where?.sql.trim()) {
|
|
263
263
|
this.parts.push(`where ${this.options.where.sql}`);
|
|
264
|
-
this.params.
|
|
264
|
+
this.options.where.params.forEach(p => this.params.push(p));
|
|
265
265
|
}
|
|
266
266
|
if (this.options.groupBy) {
|
|
267
267
|
const fields = this.options.groupBy.map(field => this.quote(field));
|
|
@@ -5,6 +5,7 @@ import type { ICriteriaNodeProcessOptions, IQueryBuilder } from '../typings.js';
|
|
|
5
5
|
*/
|
|
6
6
|
export declare class ObjectCriteriaNode<T extends object> extends CriteriaNode<T> {
|
|
7
7
|
process(qb: IQueryBuilder<T>, options?: ICriteriaNodeProcessOptions): any;
|
|
8
|
+
isStrict(): boolean;
|
|
8
9
|
unwrap(): any;
|
|
9
10
|
willAutoJoin(qb: IQueryBuilder<T>, alias?: string, options?: ICriteriaNodeProcessOptions): boolean;
|
|
10
11
|
shouldInline(payload: any): boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ALIAS_REPLACEMENT, QueryFlag, raw, RawQueryFragment, ReferenceKind, Utils, } from '@mikro-orm/core';
|
|
1
|
+
import { ALIAS_REPLACEMENT, GroupOperator, QueryFlag, raw, RawQueryFragment, ReferenceKind, Utils, } from '@mikro-orm/core';
|
|
2
2
|
import { CriteriaNode } from './CriteriaNode.js';
|
|
3
3
|
import { JoinType, QueryType } from './enums.js';
|
|
4
4
|
/**
|
|
@@ -6,7 +6,8 @@ import { JoinType, QueryType } from './enums.js';
|
|
|
6
6
|
*/
|
|
7
7
|
export class ObjectCriteriaNode extends CriteriaNode {
|
|
8
8
|
process(qb, options) {
|
|
9
|
-
const
|
|
9
|
+
const matchPopulateJoins = options?.matchPopulateJoins || (this.prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind));
|
|
10
|
+
const nestedAlias = qb.getAliasForJoinPath(this.getPath(), { ...options, matchPopulateJoins });
|
|
10
11
|
const ownerAlias = options?.alias || qb.alias;
|
|
11
12
|
const keys = Object.keys(this.payload);
|
|
12
13
|
let alias = options?.alias;
|
|
@@ -57,6 +58,22 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
57
58
|
}
|
|
58
59
|
alias = this.autoJoin(qb, ownerAlias, options);
|
|
59
60
|
}
|
|
61
|
+
if (this.prop && nestedAlias) {
|
|
62
|
+
const toOneProperty = [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind);
|
|
63
|
+
// if the property is nullable and the filter is strict, we need to use left join, so we mimic the inner join behaviour
|
|
64
|
+
// with an exclusive condition on the join columns:
|
|
65
|
+
// - if the owning column is null, the row is missing, we don't apply the filter
|
|
66
|
+
// - if the target column is not null, the row is matched, we apply the filter
|
|
67
|
+
if (toOneProperty && this.prop.nullable && this.isStrict()) {
|
|
68
|
+
const key = this.prop.owner ? this.prop.name : this.prop.referencedPKs;
|
|
69
|
+
qb.andWhere({
|
|
70
|
+
$or: [
|
|
71
|
+
{ [ownerAlias + '.' + key]: null },
|
|
72
|
+
{ [nestedAlias + '.' + Utils.getPrimaryKeyHash(this.prop.referencedPKs)]: { $ne: null } },
|
|
73
|
+
],
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
60
77
|
return keys.reduce((o, field) => {
|
|
61
78
|
const childNode = this.payload[field];
|
|
62
79
|
const payload = childNode.process(qb, { ...options, alias: this.prop ? alias : ownerAlias });
|
|
@@ -66,13 +83,14 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
66
83
|
const virtual = childNode.prop?.persist === false && !childNode.prop?.formula;
|
|
67
84
|
// if key is missing, we are inside group operator and we need to prefix with alias
|
|
68
85
|
const primaryKey = this.key && this.metadata.find(this.entityName)?.primaryKeys.includes(field);
|
|
86
|
+
const isToOne = childNode.prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(childNode.prop.kind);
|
|
69
87
|
if (childNode.shouldInline(payload)) {
|
|
70
|
-
const childAlias = qb.getAliasForJoinPath(childNode.getPath(), options);
|
|
88
|
+
const childAlias = qb.getAliasForJoinPath(childNode.getPath(), { preferNoBranch: isToOne, ...options });
|
|
71
89
|
const a = qb.helper.isTableNameAliasRequired(qb.type) ? alias : undefined;
|
|
72
90
|
this.inlineChildPayload(o, payload, field, a, childAlias);
|
|
73
91
|
}
|
|
74
92
|
else if (childNode.shouldRename(payload)) {
|
|
75
|
-
this.inlineCondition(childNode.renameFieldToPK(qb), o, payload);
|
|
93
|
+
this.inlineCondition(childNode.renameFieldToPK(qb, alias), o, payload);
|
|
76
94
|
}
|
|
77
95
|
else if (isRawField) {
|
|
78
96
|
const rawField = RawQueryFragment.getKnownFragment(field);
|
|
@@ -87,6 +105,11 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
87
105
|
return o;
|
|
88
106
|
}, {});
|
|
89
107
|
}
|
|
108
|
+
isStrict() {
|
|
109
|
+
return this.strict || Object.keys(this.payload).some(key => {
|
|
110
|
+
return this.payload[key].isStrict();
|
|
111
|
+
});
|
|
112
|
+
}
|
|
90
113
|
unwrap() {
|
|
91
114
|
return Object.keys(this.payload).reduce((o, field) => {
|
|
92
115
|
o[field] = this.payload[field].unwrap();
|
|
@@ -137,7 +160,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
137
160
|
delete payload[k];
|
|
138
161
|
o[this.aliased(field, alias)] = { [k]: tmp, ...o[this.aliased(field, alias)] };
|
|
139
162
|
}
|
|
140
|
-
else if (
|
|
163
|
+
else if (k in GroupOperator && Array.isArray(payload[k])) {
|
|
141
164
|
this.inlineArrayChildPayload(o, payload[k], k, prop, childAlias, alias);
|
|
142
165
|
}
|
|
143
166
|
else if (this.isPrefixed(k) || Utils.isOperator(k) || !childAlias) {
|
|
@@ -157,7 +180,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
157
180
|
o[key] = value;
|
|
158
181
|
return;
|
|
159
182
|
}
|
|
160
|
-
/* v8 ignore next
|
|
183
|
+
/* v8 ignore next */
|
|
161
184
|
if (key === '$and') {
|
|
162
185
|
o.$and.push({ [key]: value });
|
|
163
186
|
return;
|
|
@@ -206,12 +229,16 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
206
229
|
}
|
|
207
230
|
else {
|
|
208
231
|
const prev = qb._fields?.slice();
|
|
209
|
-
|
|
232
|
+
const toOneProperty = [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind);
|
|
233
|
+
const joinType = toOneProperty && !this.prop.nullable
|
|
234
|
+
? JoinType.innerJoin
|
|
235
|
+
: JoinType.leftJoin;
|
|
236
|
+
qb[method](field, nestedAlias, undefined, joinType, path);
|
|
210
237
|
if (!qb.hasFlag(QueryFlag.INFER_POPULATE)) {
|
|
211
238
|
qb._fields = prev;
|
|
212
239
|
}
|
|
213
240
|
}
|
|
214
|
-
if (
|
|
241
|
+
if (options?.type !== 'orderBy') {
|
|
215
242
|
qb.scheduleFilterCheck(path);
|
|
216
243
|
}
|
|
217
244
|
return nestedAlias;
|
package/query/QueryBuilder.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityKey, type EntityManager, type EntityMetadata, type EntityName, type EntityProperty, type ExpandProperty, type FlushMode, type GroupOperator, type Loaded, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, QueryFlag, type QueryOrderMap, type QueryResult, RawQueryFragment, type RequiredEntityData, type Transaction } from '@mikro-orm/core';
|
|
1
|
+
import { type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityKey, type EntityManager, type EntityMetadata, type EntityName, type EntityProperty, type ExpandProperty, type FilterOptions, type FlushMode, type GroupOperator, type Loaded, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, QueryFlag, type QueryOrderMap, type QueryResult, RawQueryFragment, type RequiredEntityData, type Transaction } from '@mikro-orm/core';
|
|
3
2
|
import { JoinType, QueryType } from './enums.js';
|
|
4
3
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver.js';
|
|
5
4
|
import { type Alias, type OnConflictClause, QueryBuilderHelper } from './QueryBuilderHelper.js';
|
|
@@ -11,6 +10,30 @@ export interface ExecuteOptions {
|
|
|
11
10
|
mapResults?: boolean;
|
|
12
11
|
mergeResults?: boolean;
|
|
13
12
|
}
|
|
13
|
+
export interface QBStreamOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Results are mapped to entities, if you set `mapResults: false` you will get POJOs instead.
|
|
16
|
+
*
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
mapResults?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* When populating to-many relations, the ORM streams fully merged entities instead of yielding every row.
|
|
22
|
+
* You can opt out of this behavior by specifying `mergeResults: false`. This will yield every row from
|
|
23
|
+
* the SQL result, but still mapped to entities, meaning that to-many collections will contain at most
|
|
24
|
+
* one item, and you will get duplicate root entities when they have multiple items in the populated
|
|
25
|
+
* collection.
|
|
26
|
+
*
|
|
27
|
+
* @default true
|
|
28
|
+
*/
|
|
29
|
+
mergeResults?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* When enabled, the driver will return the raw database results without renaming the fields to match the entity property names.
|
|
32
|
+
*
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
rawResults?: boolean;
|
|
36
|
+
}
|
|
14
37
|
type AnyString = string & {};
|
|
15
38
|
type Compute<T> = {
|
|
16
39
|
[K in keyof T]: T[K];
|
|
@@ -140,7 +163,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
140
163
|
/**
|
|
141
164
|
* Apply filters to the QB where condition.
|
|
142
165
|
*/
|
|
143
|
-
applyFilters(filterOptions?:
|
|
166
|
+
applyFilters(filterOptions?: FilterOptions): Promise<void>;
|
|
144
167
|
private readonly autoJoinedPaths;
|
|
145
168
|
/**
|
|
146
169
|
* @internal
|
|
@@ -149,7 +172,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
149
172
|
/**
|
|
150
173
|
* @internal
|
|
151
174
|
*/
|
|
152
|
-
applyJoinedFilters(em: EntityManager, filterOptions
|
|
175
|
+
applyJoinedFilters(em: EntityManager, filterOptions: FilterOptions | undefined): Promise<void>;
|
|
153
176
|
withSubQuery(subQuery: RawQueryFragment | NativeQueryBuilder, alias: string): this;
|
|
154
177
|
where(cond: QBFilterQuery<Entity>, operator?: keyof typeof GroupOperator): this;
|
|
155
178
|
where(cond: string, params?: any[], operator?: keyof typeof GroupOperator): this;
|
|
@@ -158,6 +181,8 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
158
181
|
orWhere(cond: QBFilterQuery<Entity>): this;
|
|
159
182
|
orWhere(cond: string, params?: any[]): this;
|
|
160
183
|
orderBy(orderBy: QBQueryOrderMap<Entity> | QBQueryOrderMap<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
|
|
184
|
+
andOrderBy(orderBy: QBQueryOrderMap<Entity> | QBQueryOrderMap<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
|
|
185
|
+
private processOrderBy;
|
|
161
186
|
groupBy(fields: EntityKeyOrString<Entity> | readonly EntityKeyOrString<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
|
|
162
187
|
having(cond?: QBFilterQuery | string, params?: any[], operator?: keyof typeof GroupOperator): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
|
|
163
188
|
andHaving(cond?: QBFilterQuery | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
|
|
@@ -182,17 +207,17 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
182
207
|
/**
|
|
183
208
|
* Adds index hint to the FROM clause.
|
|
184
209
|
*/
|
|
185
|
-
indexHint(sql: string): this;
|
|
210
|
+
indexHint(sql: string | undefined): this;
|
|
186
211
|
/**
|
|
187
212
|
* Prepend comment to the sql query using the syntax `/* ... *‍/`. Some characters are forbidden such as `/*, *‍/` and `?`.
|
|
188
213
|
*/
|
|
189
|
-
comment(comment: string | string[]): this;
|
|
214
|
+
comment(comment: string | string[] | undefined): this;
|
|
190
215
|
/**
|
|
191
216
|
* Add hints to the query using comment-like syntax `/*+ ... *‍/`. MySQL and Oracle use this syntax for optimizer hints.
|
|
192
217
|
* Also various DB proxies and routers use this syntax to pass hints to alter their behavior. In other dialects the hints
|
|
193
218
|
* are ignored as simple comments.
|
|
194
219
|
*/
|
|
195
|
-
hintComment(comment: string | string[]): this;
|
|
220
|
+
hintComment(comment: string | string[] | undefined): this;
|
|
196
221
|
/**
|
|
197
222
|
* Specifies FROM which entity's table select/update/delete will be executed, removing all previously set FROM-s.
|
|
198
223
|
* Allows setting a main string alias of the selection data.
|
|
@@ -245,14 +270,35 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
245
270
|
* Use `method` to specify what kind of result you want to get (array/single/meta).
|
|
246
271
|
*/
|
|
247
272
|
execute<U = any>(method?: 'all' | 'get' | 'run', options?: ExecuteOptions | boolean): Promise<U>;
|
|
273
|
+
private getConnection;
|
|
274
|
+
/**
|
|
275
|
+
* Executes the query and returns an async iterable (async generator) that yields results one by one.
|
|
276
|
+
* By default, the results are merged and mapped to entity instances, without adding them to the identity map.
|
|
277
|
+
* You can disable merging and mapping by passing the options `{ mergeResults: false, mapResults: false }`.
|
|
278
|
+
* This is useful for processing large datasets without loading everything into memory at once.
|
|
279
|
+
*
|
|
280
|
+
* ```ts
|
|
281
|
+
* const qb = em.createQueryBuilder(Book, 'b');
|
|
282
|
+
* qb.select('*').where({ title: '1984' }).leftJoinAndSelect('b.author', 'a');
|
|
283
|
+
*
|
|
284
|
+
* for await (const book of qb.stream()) {
|
|
285
|
+
* // book is an instance of Book entity
|
|
286
|
+
* console.log(book.title, book.author.name);
|
|
287
|
+
* }
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
stream(options?: QBStreamOptions): AsyncIterableIterator<Loaded<Entity, Hint>>;
|
|
248
291
|
/**
|
|
249
292
|
* Alias for `qb.getResultList()`
|
|
250
293
|
*/
|
|
251
294
|
getResult(): Promise<Loaded<Entity, Hint>[]>;
|
|
252
295
|
/**
|
|
253
|
-
* Executes the query, returning array of results
|
|
296
|
+
* Executes the query, returning array of results mapped to entity instances.
|
|
254
297
|
*/
|
|
255
298
|
getResultList(limit?: number): Promise<Loaded<Entity, Hint>[]>;
|
|
299
|
+
private propagatePopulateHint;
|
|
300
|
+
private mapResult;
|
|
301
|
+
private mapResults;
|
|
256
302
|
/**
|
|
257
303
|
* Executes the query, returning the first result or null
|
|
258
304
|
*/
|
|
@@ -290,6 +336,11 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
290
336
|
processPopulateHint(): void;
|
|
291
337
|
private processPopulateWhere;
|
|
292
338
|
private mergeOnConditions;
|
|
339
|
+
/**
|
|
340
|
+
* When adding an inner join on a left joined relation, we need to nest them,
|
|
341
|
+
* otherwise the inner join could discard rows of the root table.
|
|
342
|
+
*/
|
|
343
|
+
private processNestedJoins;
|
|
293
344
|
private hasToManyJoins;
|
|
294
345
|
protected wrapPaginateSubQuery(meta: EntityMetadata): void;
|
|
295
346
|
private pruneExtraJoins;
|
|
@@ -302,8 +353,6 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
302
353
|
private createQueryBuilderHelper;
|
|
303
354
|
private ensureFromClause;
|
|
304
355
|
private ensureNotFinalized;
|
|
305
|
-
/** @ignore */
|
|
306
|
-
[inspect.custom](depth?: number): string;
|
|
307
356
|
}
|
|
308
357
|
export interface RunQueryBuilder<Entity extends object> extends Omit<QueryBuilder<Entity, any, any>, 'getResult' | 'getSingleResult' | 'getResultList' | 'where'> {
|
|
309
358
|
where(cond: QBFilterQuery<Entity> | string, params?: keyof typeof GroupOperator | any[], operator?: keyof typeof GroupOperator): this;
|