@mikro-orm/knex 6.0.0-dev.2 → 6.0.0-dev.21
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/{dist/AbstractSqlConnection.d.ts → AbstractSqlConnection.d.ts} +0 -0
- package/{dist/AbstractSqlConnection.js → AbstractSqlConnection.js} +5 -0
- package/AbstractSqlDriver.d.ts +66 -0
- package/{dist/AbstractSqlDriver.js → AbstractSqlDriver.js} +230 -71
- package/{dist/AbstractSqlPlatform.d.ts → AbstractSqlPlatform.d.ts} +7 -7
- package/{dist/AbstractSqlPlatform.js → AbstractSqlPlatform.js} +12 -14
- package/{dist/MonkeyPatchable.d.ts → MonkeyPatchable.d.ts} +0 -0
- package/{dist/MonkeyPatchable.js → MonkeyPatchable.js} +0 -0
- package/{dist/README.md → README.md} +2 -2
- package/{dist/SqlEntityManager.d.ts → SqlEntityManager.d.ts} +5 -5
- package/{dist/SqlEntityManager.js → SqlEntityManager.js} +1 -2
- package/{dist/SqlEntityRepository.d.ts → SqlEntityRepository.d.ts} +3 -3
- package/{dist/SqlEntityRepository.js → SqlEntityRepository.js} +1 -1
- package/{dist/index.d.ts → index.d.ts} +1 -0
- package/{dist/index.js → index.js} +6 -1
- package/index.mjs +192 -0
- package/package.json +18 -47
- package/{dist/query → query}/ArrayCriteriaNode.d.ts +0 -0
- package/{dist/query → query}/ArrayCriteriaNode.js +0 -0
- package/{dist/query → query}/CriteriaNode.d.ts +0 -0
- package/{dist/query → query}/CriteriaNode.js +7 -4
- package/{dist/query → query}/CriteriaNodeFactory.d.ts +0 -0
- package/{dist/query → query}/CriteriaNodeFactory.js +0 -0
- package/{dist/query → query}/ObjectCriteriaNode.d.ts +0 -0
- package/{dist/query → query}/ObjectCriteriaNode.js +14 -1
- package/{dist/query → query}/QueryBuilder.d.ts +65 -24
- package/{dist/query → query}/QueryBuilder.js +318 -84
- package/{dist/query → query}/QueryBuilderHelper.d.ts +19 -11
- package/{dist/query → query}/QueryBuilderHelper.js +224 -113
- package/{dist/query → query}/ScalarCriteriaNode.d.ts +0 -0
- package/{dist/query → query}/ScalarCriteriaNode.js +0 -0
- package/{dist/query → query}/enums.d.ts +0 -0
- package/{dist/query → query}/enums.js +0 -0
- package/{dist/query → query}/index.d.ts +0 -0
- package/{dist/query → query}/index.js +5 -1
- package/{dist/schema → schema}/DatabaseSchema.d.ts +1 -1
- package/{dist/schema → schema}/DatabaseSchema.js +8 -16
- package/{dist/schema → schema}/DatabaseTable.d.ts +8 -8
- package/{dist/schema → schema}/DatabaseTable.js +2 -1
- package/{dist/schema → schema}/SchemaComparator.d.ts +7 -5
- package/{dist/schema → schema}/SchemaComparator.js +60 -10
- package/{dist/schema → schema}/SchemaHelper.d.ts +15 -10
- package/{dist/schema → schema}/SchemaHelper.js +46 -8
- package/{dist/schema/SchemaGenerator.d.ts → schema/SqlSchemaGenerator.d.ts} +12 -12
- package/{dist/schema/SchemaGenerator.js → schema/SqlSchemaGenerator.js} +85 -34
- package/{dist/schema → schema}/index.d.ts +1 -1
- package/{dist/schema → schema}/index.js +6 -2
- package/{dist/typings.d.ts → typings.d.ts} +16 -12
- package/{dist/typings.js → typings.js} +0 -0
- package/CHANGELOG.md +0 -661
- package/dist/AbstractSqlDriver.d.ts +0 -55
- package/dist/LICENSE +0 -21
- package/dist/index.mjs +0 -26
- package/dist/package.json +0 -99
|
File without changes
|
|
@@ -102,6 +102,11 @@ class AbstractSqlConnection extends core_1.Connection {
|
|
|
102
102
|
await this.client.raw(buf.toString());
|
|
103
103
|
}
|
|
104
104
|
createKnexClient(type) {
|
|
105
|
+
const driverOptions = this.config.get('driverOptions');
|
|
106
|
+
if (driverOptions.context?.client instanceof knex_1.knex.Client) {
|
|
107
|
+
this.logger.log('info', 'Reusing knex client provided via `driverOptions`');
|
|
108
|
+
return driverOptions;
|
|
109
|
+
}
|
|
105
110
|
return (0, knex_1.knex)(this.getKnexOptions(type))
|
|
106
111
|
.on('query', data => {
|
|
107
112
|
if (!data.__knexQueryUid) {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Knex } from 'knex';
|
|
2
|
+
import type { AnyEntity, Collection, ConnectionType, Configuration, Constructor, CountOptions, DeleteOptions, Dictionary, DriverMethodOptions, EntityData, EntityDictionary, EntityField, EntityMetadata, EntityName, EntityProperty, FilterQuery, FindOneOptions, FindOptions, IDatabaseDriver, LockOptions, NativeInsertUpdateManyOptions, NativeInsertUpdateOptions, PopulateOptions, Primary, QueryOrderMap, QueryResult, Transaction } from '@mikro-orm/core';
|
|
3
|
+
import { DatabaseDriver, EntityManagerType } from '@mikro-orm/core';
|
|
4
|
+
import type { AbstractSqlConnection } from './AbstractSqlConnection';
|
|
5
|
+
import type { AbstractSqlPlatform } from './AbstractSqlPlatform';
|
|
6
|
+
import { QueryBuilder, QueryType } from './query';
|
|
7
|
+
import { SqlEntityManager } from './SqlEntityManager';
|
|
8
|
+
import type { Field } from './typings';
|
|
9
|
+
export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlConnection = AbstractSqlConnection, Platform extends AbstractSqlPlatform = AbstractSqlPlatform> extends DatabaseDriver<Connection> {
|
|
10
|
+
[EntityManagerType]: SqlEntityManager<this>;
|
|
11
|
+
protected readonly connection: Connection;
|
|
12
|
+
protected readonly replicas: Connection[];
|
|
13
|
+
protected readonly platform: Platform;
|
|
14
|
+
protected constructor(config: Configuration, platform: Platform, connection: Constructor<Connection>, connector: string[]);
|
|
15
|
+
getPlatform(): Platform;
|
|
16
|
+
createEntityManager<D extends IDatabaseDriver = IDatabaseDriver>(useContext?: boolean): D[typeof EntityManagerType];
|
|
17
|
+
find<T extends object, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOptions<T, P>): Promise<EntityData<T>[]>;
|
|
18
|
+
findOne<T extends object, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOneOptions<T, P>): Promise<EntityData<T> | null>;
|
|
19
|
+
findVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: FindOptions<T, any>): Promise<EntityData<T>[]>;
|
|
20
|
+
countVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: CountOptions<T>): Promise<number>;
|
|
21
|
+
protected wrapVirtualExpressionInSubquery<T extends object>(meta: EntityMetadata<T>, expression: string, where: FilterQuery<T>, options: FindOptions<T, any>, type: QueryType.COUNT): Promise<number>;
|
|
22
|
+
protected wrapVirtualExpressionInSubquery<T extends object>(meta: EntityMetadata<T>, expression: string, where: FilterQuery<T>, options: FindOptions<T, any>, type: QueryType.SELECT): Promise<T[]>;
|
|
23
|
+
protected wrapVirtualExpressionInSubquery<T extends object>(meta: EntityMetadata<T>, expression: string, where: FilterQuery<T>, options: FindOptions<T, any>): Promise<T[]>;
|
|
24
|
+
mapResult<T extends object>(result: EntityData<T>, meta: EntityMetadata<T>, populate?: PopulateOptions<T>[], qb?: QueryBuilder<T>, map?: Dictionary): EntityData<T> | null;
|
|
25
|
+
private mapJoinedProps;
|
|
26
|
+
private appendToCollection;
|
|
27
|
+
count<T extends object>(entityName: string, where: any, options?: CountOptions<T>): Promise<number>;
|
|
28
|
+
nativeInsert<T extends object>(entityName: string, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
|
|
29
|
+
nativeInsertMany<T extends object>(entityName: string, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
|
|
30
|
+
nativeUpdate<T extends object>(entityName: string, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
|
|
31
|
+
nativeUpdateMany<T extends object>(entityName: string, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
|
|
32
|
+
nativeDelete<T extends object>(entityName: string, where: FilterQuery<T> | string | any, options?: DeleteOptions<T>): Promise<QueryResult<T>>;
|
|
33
|
+
syncCollection<T extends object, O extends object>(coll: Collection<T, O>, options?: DriverMethodOptions): Promise<void>;
|
|
34
|
+
loadFromPivotTable<T extends object, O extends object>(prop: EntityProperty, owners: Primary<O>[][], where?: FilterQuery<any>, orderBy?: QueryOrderMap<T>[], ctx?: Transaction, options?: FindOptions<T, any>): Promise<Dictionary<T[]>>;
|
|
35
|
+
execute<T extends QueryResult | EntityData<AnyEntity> | EntityData<AnyEntity>[] = EntityData<AnyEntity>[]>(queryOrKnex: string | Knex.QueryBuilder | Knex.Raw, params?: any[], method?: 'all' | 'get' | 'run', ctx?: Transaction): Promise<T>;
|
|
36
|
+
/**
|
|
37
|
+
* 1:1 owner side needs to be marked for population so QB auto-joins the owner id
|
|
38
|
+
*/
|
|
39
|
+
protected autoJoinOneToOneOwner<T extends object, P extends string = never>(meta: EntityMetadata, populate: PopulateOptions<T>[], fields?: readonly EntityField<T, P>[]): PopulateOptions<T>[];
|
|
40
|
+
protected joinedProps<T>(meta: EntityMetadata, populate: PopulateOptions<T>[]): PopulateOptions<T>[];
|
|
41
|
+
/**
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
mergeJoinedResult<T extends object>(rawResults: EntityData<T>[], meta: EntityMetadata<T>): EntityData<T>[];
|
|
45
|
+
protected getFieldsForJoinedLoad<T extends object>(qb: QueryBuilder<T>, meta: EntityMetadata<T>, explicitFields?: Field<T>[], populate?: PopulateOptions<T>[], parentTableAlias?: string, parentJoinPath?: string): Field<T>[];
|
|
46
|
+
/**
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
mapPropToFieldNames<T extends object>(qb: QueryBuilder<T>, prop: EntityProperty<T>, tableAlias?: string): Field<T>[];
|
|
50
|
+
/** @internal */
|
|
51
|
+
createQueryBuilder<T extends object>(entityName: EntityName<T> | QueryBuilder<T>, ctx?: Transaction<Knex.Transaction>, preferredConnectionType?: ConnectionType, convertCustomTypes?: boolean): QueryBuilder<T>;
|
|
52
|
+
protected resolveConnectionType(args: {
|
|
53
|
+
ctx?: Transaction<Knex.Transaction>;
|
|
54
|
+
connectionType?: ConnectionType;
|
|
55
|
+
}): ConnectionType;
|
|
56
|
+
protected extractManyToMany<T>(entityName: string, data: EntityDictionary<T>): EntityData<T>;
|
|
57
|
+
protected processManyToMany<T extends object>(meta: EntityMetadata<T> | undefined, pks: Primary<T>[], collections: EntityData<T>, clear: boolean, options?: DriverMethodOptions): Promise<void>;
|
|
58
|
+
protected updateCollectionDiff<T extends object, O extends object>(meta: EntityMetadata<O>, prop: EntityProperty<T>, pks: Primary<O>[], deleteDiff: Primary<T>[][] | boolean, insertDiff: Primary<T>[][], options?: DriverMethodOptions & {
|
|
59
|
+
ownerSchema?: string;
|
|
60
|
+
}): Promise<void>;
|
|
61
|
+
lockPessimistic<T>(entity: T, options: LockOptions): Promise<void>;
|
|
62
|
+
protected buildJoinedPropsOrderBy<T extends object>(entityName: string, qb: QueryBuilder<T>, meta: EntityMetadata<T>, populate: PopulateOptions<T>[], parentPath?: string): QueryOrderMap<T>[];
|
|
63
|
+
protected normalizeFields<T extends object>(fields: Field<T>[], prefix?: string): string[];
|
|
64
|
+
protected processField<T extends object>(meta: EntityMetadata<T>, prop: EntityProperty<T> | undefined, field: string, ret: Field<T>[], populate: PopulateOptions<T>[], joinedProps: PopulateOptions<T>[], qb: QueryBuilder<T>): void;
|
|
65
|
+
protected buildFields<T extends object>(meta: EntityMetadata<T>, populate: PopulateOptions<T>[], joinedProps: PopulateOptions<T>[], qb: QueryBuilder<T>, fields?: Field<T>[]): Field<T>[];
|
|
66
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AbstractSqlDriver = void 0;
|
|
4
4
|
const core_1 = require("@mikro-orm/core");
|
|
5
|
-
const
|
|
5
|
+
const query_1 = require("./query");
|
|
6
6
|
const SqlEntityManager_1 = require("./SqlEntityManager");
|
|
7
7
|
class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
8
8
|
constructor(config, platform, connection, connector) {
|
|
@@ -21,16 +21,19 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
21
21
|
async find(entityName, where, options = {}) {
|
|
22
22
|
options = { populate: [], orderBy: [], ...options };
|
|
23
23
|
const meta = this.metadata.find(entityName);
|
|
24
|
+
if (meta?.virtual) {
|
|
25
|
+
return this.findVirtual(entityName, where, options);
|
|
26
|
+
}
|
|
24
27
|
const populate = this.autoJoinOneToOneOwner(meta, options.populate, options.fields);
|
|
25
28
|
const joinedProps = this.joinedProps(meta, populate);
|
|
26
|
-
const qb = this.createQueryBuilder(entityName, options.ctx,
|
|
29
|
+
const qb = this.createQueryBuilder(entityName, options.ctx, options.connectionType, false);
|
|
27
30
|
const fields = this.buildFields(meta, populate, joinedProps, qb, options.fields);
|
|
28
31
|
const joinedPropsOrderBy = this.buildJoinedPropsOrderBy(entityName, qb, meta, joinedProps);
|
|
29
32
|
if (core_1.Utils.isPrimaryKey(where, meta.compositePK)) {
|
|
30
33
|
where = { [core_1.Utils.getPrimaryKeyHash(meta.primaryKeys)]: where };
|
|
31
34
|
}
|
|
32
35
|
qb.select(fields)
|
|
33
|
-
.populate(populate)
|
|
36
|
+
.populate(populate, joinedProps.length > 0 ? options.populateWhere : undefined)
|
|
34
37
|
.where(where)
|
|
35
38
|
.orderBy([...core_1.Utils.asArray(options.orderBy), ...joinedPropsOrderBy])
|
|
36
39
|
.groupBy(options.groupBy)
|
|
@@ -57,9 +60,70 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
57
60
|
if (joinedProps.length === 0) {
|
|
58
61
|
opts.limit = 1;
|
|
59
62
|
}
|
|
63
|
+
if (opts.limit > 0 && !opts.flags?.includes(core_1.QueryFlag.DISABLE_PAGINATE)) {
|
|
64
|
+
opts.flags ?? (opts.flags = []);
|
|
65
|
+
opts.flags.push(core_1.QueryFlag.DISABLE_PAGINATE);
|
|
66
|
+
}
|
|
60
67
|
const res = await this.find(entityName, where, opts);
|
|
61
68
|
return res[0] || null;
|
|
62
69
|
}
|
|
70
|
+
async findVirtual(entityName, where, options) {
|
|
71
|
+
const meta = this.metadata.get(entityName);
|
|
72
|
+
/* istanbul ignore next */
|
|
73
|
+
if (!meta.expression) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
if (typeof meta.expression === 'string') {
|
|
77
|
+
return this.wrapVirtualExpressionInSubquery(meta, meta.expression, where, options);
|
|
78
|
+
}
|
|
79
|
+
const em = this.createEntityManager(false);
|
|
80
|
+
em.setTransactionContext(options.ctx);
|
|
81
|
+
const res = meta.expression(em, where, options);
|
|
82
|
+
if (res instanceof (query_1.QueryBuilder)) {
|
|
83
|
+
return this.wrapVirtualExpressionInSubquery(meta, res.getFormattedQuery(), where, options);
|
|
84
|
+
}
|
|
85
|
+
/* istanbul ignore next */
|
|
86
|
+
return res;
|
|
87
|
+
}
|
|
88
|
+
async countVirtual(entityName, where, options) {
|
|
89
|
+
const meta = this.metadata.get(entityName);
|
|
90
|
+
/* istanbul ignore next */
|
|
91
|
+
if (!meta.expression) {
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
94
|
+
if (typeof meta.expression === 'string') {
|
|
95
|
+
return this.wrapVirtualExpressionInSubquery(meta, meta.expression, where, options, query_1.QueryType.COUNT);
|
|
96
|
+
}
|
|
97
|
+
const em = this.createEntityManager(false);
|
|
98
|
+
em.setTransactionContext(options.ctx);
|
|
99
|
+
const res = meta.expression(em, where, options);
|
|
100
|
+
if (res instanceof (query_1.QueryBuilder)) {
|
|
101
|
+
return this.wrapVirtualExpressionInSubquery(meta, res.getFormattedQuery(), where, options, query_1.QueryType.COUNT);
|
|
102
|
+
}
|
|
103
|
+
/* istanbul ignore next */
|
|
104
|
+
return res;
|
|
105
|
+
}
|
|
106
|
+
async wrapVirtualExpressionInSubquery(meta, expression, where, options, type = query_1.QueryType.SELECT) {
|
|
107
|
+
const qb = this.createQueryBuilder(meta.className, options?.ctx, options.connectionType, options.convertCustomTypes)
|
|
108
|
+
.limit(options?.limit, options?.offset);
|
|
109
|
+
if (options.orderBy) {
|
|
110
|
+
qb.orderBy(options.orderBy);
|
|
111
|
+
}
|
|
112
|
+
qb.where(where);
|
|
113
|
+
const kqb = qb.getKnexQuery().clear('select');
|
|
114
|
+
if (type === query_1.QueryType.COUNT) {
|
|
115
|
+
kqb.select(qb.raw('count(*) as count'));
|
|
116
|
+
}
|
|
117
|
+
else { // select
|
|
118
|
+
kqb.select('*');
|
|
119
|
+
}
|
|
120
|
+
kqb.fromRaw(`(${expression}) as ${this.platform.quoteIdentifier(qb.alias)}`);
|
|
121
|
+
const res = await this.execute(kqb);
|
|
122
|
+
if (type === query_1.QueryType.COUNT) {
|
|
123
|
+
return res[0].count;
|
|
124
|
+
}
|
|
125
|
+
return res.map(row => this.mapResult(row, meta));
|
|
126
|
+
}
|
|
63
127
|
mapResult(result, meta, populate = [], qb, map = {}) {
|
|
64
128
|
const ret = super.mapResult(result, meta);
|
|
65
129
|
/* istanbul ignore if */
|
|
@@ -137,23 +201,25 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
137
201
|
collection.push(relationPojo);
|
|
138
202
|
}
|
|
139
203
|
}
|
|
140
|
-
async count(entityName, where, options = {}
|
|
204
|
+
async count(entityName, where, options = {}) {
|
|
141
205
|
const meta = this.metadata.find(entityName);
|
|
142
|
-
|
|
143
|
-
|
|
206
|
+
if (meta?.virtual) {
|
|
207
|
+
return this.countVirtual(entityName, where, options);
|
|
208
|
+
}
|
|
209
|
+
const qb = this.createQueryBuilder(entityName, options.ctx, options.connectionType, false)
|
|
144
210
|
.groupBy(options.groupBy)
|
|
145
211
|
.having(options.having)
|
|
146
212
|
.populate(options.populate ?? [])
|
|
147
213
|
.withSchema(this.getSchemaName(meta, options))
|
|
148
214
|
.where(where);
|
|
149
|
-
return this.rethrow(qb.getCount(
|
|
215
|
+
return this.rethrow(qb.getCount());
|
|
150
216
|
}
|
|
151
217
|
async nativeInsert(entityName, data, options = {}) {
|
|
152
218
|
options.convertCustomTypes ?? (options.convertCustomTypes = true);
|
|
153
219
|
const meta = this.metadata.find(entityName);
|
|
154
220
|
const collections = this.extractManyToMany(entityName, data);
|
|
155
|
-
const pks = this.
|
|
156
|
-
const qb = this.createQueryBuilder(entityName, options.ctx,
|
|
221
|
+
const pks = meta?.primaryKeys ?? [this.config.getNamingStrategy().referenceColumnName()];
|
|
222
|
+
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', options.convertCustomTypes).withSchema(this.getSchemaName(meta, options));
|
|
157
223
|
const res = await this.rethrow(qb.insert(data).execute('run', false));
|
|
158
224
|
res.row = res.row || {};
|
|
159
225
|
let pk;
|
|
@@ -161,7 +227,8 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
161
227
|
pk = core_1.Utils.getPrimaryKeyCond(data, pks);
|
|
162
228
|
}
|
|
163
229
|
else {
|
|
164
|
-
|
|
230
|
+
/* istanbul ignore next */
|
|
231
|
+
res.insertId = data[pks[0]] ?? res.insertId ?? res.row[pks[0]];
|
|
165
232
|
pk = [res.insertId];
|
|
166
233
|
}
|
|
167
234
|
await this.processManyToMany(meta, pk, collections, false, options);
|
|
@@ -170,29 +237,30 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
170
237
|
async nativeInsertMany(entityName, data, options = {}) {
|
|
171
238
|
options.processCollections ?? (options.processCollections = true);
|
|
172
239
|
options.convertCustomTypes ?? (options.convertCustomTypes = true);
|
|
173
|
-
const meta = this.metadata.
|
|
240
|
+
const meta = this.metadata.find(entityName);
|
|
174
241
|
const collections = options.processCollections ? data.map(d => this.extractManyToMany(entityName, d)) : [];
|
|
175
242
|
const pks = this.getPrimaryKeyFields(entityName);
|
|
176
243
|
const set = new Set();
|
|
177
244
|
data.forEach(row => Object.keys(row).forEach(k => set.add(k)));
|
|
178
|
-
const props = [...set].map(name => meta
|
|
245
|
+
const props = [...set].map(name => meta?.properties[name] ?? { name, fieldNames: [name] });
|
|
179
246
|
const fields = core_1.Utils.flatten(props.map(prop => prop.fieldNames));
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
247
|
+
const params = [];
|
|
248
|
+
/* istanbul ignore next */
|
|
249
|
+
const tableName = meta ? this.getTableName(meta, options) : this.platform.quoteIdentifier(entityName);
|
|
250
|
+
let sql = `insert into ${tableName} `;
|
|
251
|
+
sql += fields.length > 0 ? '(' + fields.map(k => this.platform.quoteIdentifier(k)).join(', ') + ')' : `(${this.platform.quoteIdentifier(pks[0])})`;
|
|
252
|
+
if (fields.length > 0 || this.platform.usesDefaultKeyword()) {
|
|
253
|
+
sql += ' values ';
|
|
184
254
|
}
|
|
185
255
|
else {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
sql += ` values `;
|
|
190
|
-
const params = [];
|
|
256
|
+
sql += ' ' + data.map(() => `select null as ${this.platform.quoteIdentifier(pks[0])}`).join(' union all ');
|
|
257
|
+
}
|
|
258
|
+
if (fields.length > 0 || this.platform.usesDefaultKeyword()) {
|
|
191
259
|
sql += data.map(row => {
|
|
192
260
|
const keys = [];
|
|
193
261
|
props.forEach(prop => {
|
|
194
262
|
if (prop.fieldNames.length > 1) {
|
|
195
|
-
params.push(...row[prop.name]);
|
|
263
|
+
params.push(...(row[prop.name] ?? prop.fieldNames.map(() => null)));
|
|
196
264
|
keys.push(...prop.fieldNames.map(_ => '?'));
|
|
197
265
|
}
|
|
198
266
|
else if (prop.customType && 'convertToDatabaseValueSQL' in prop.customType && !this.platform.isRaw(row[prop.name])) {
|
|
@@ -204,17 +272,17 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
204
272
|
keys.push('?');
|
|
205
273
|
}
|
|
206
274
|
});
|
|
207
|
-
return '(' + keys.join(', ') + ')';
|
|
275
|
+
return '(' + (keys.join(', ') || 'default') + ')';
|
|
208
276
|
}).join(', ');
|
|
209
|
-
if (this.platform.usesReturningStatement()) {
|
|
210
|
-
/* istanbul ignore next */
|
|
211
|
-
const returningProps = meta.props.filter(prop => prop.primary || prop.defaultRaw);
|
|
212
|
-
const returningFields = core_1.Utils.flatten(returningProps.map(prop => prop.fieldNames));
|
|
213
|
-
/* istanbul ignore next */
|
|
214
|
-
sql += returningFields.length > 0 ? ` returning ${returningFields.map(field => this.platform.quoteIdentifier(field)).join(', ')}` : '';
|
|
215
|
-
}
|
|
216
|
-
res = await this.execute(sql, params, 'run', options.ctx);
|
|
217
277
|
}
|
|
278
|
+
if (this.platform.usesReturningStatement()) {
|
|
279
|
+
/* istanbul ignore next */
|
|
280
|
+
const returningProps = meta.hydrateProps.filter(prop => prop.persist !== false && (prop.primary || prop.defaultRaw));
|
|
281
|
+
const returningFields = core_1.Utils.flatten(returningProps.map(prop => prop.fieldNames));
|
|
282
|
+
/* istanbul ignore next */
|
|
283
|
+
sql += returningFields.length > 0 ? ` returning ${returningFields.map(field => this.platform.quoteIdentifier(field)).join(', ')}` : '';
|
|
284
|
+
}
|
|
285
|
+
const res = await this.execute(sql, params, 'run', options.ctx);
|
|
218
286
|
let pk;
|
|
219
287
|
/* istanbul ignore next */
|
|
220
288
|
if (pks.length > 1) { // owner has composite pk
|
|
@@ -238,13 +306,23 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
238
306
|
const collections = this.extractManyToMany(entityName, data);
|
|
239
307
|
let res = { affectedRows: 0, insertId: 0, row: {} };
|
|
240
308
|
if (core_1.Utils.isPrimaryKey(where) && pks.length === 1) {
|
|
241
|
-
|
|
309
|
+
/* istanbul ignore next */
|
|
310
|
+
where = { [meta?.primaryKeys[0] ?? pks[0]]: where };
|
|
242
311
|
}
|
|
243
312
|
if (core_1.Utils.hasObjectKeys(data)) {
|
|
244
|
-
const qb = this.createQueryBuilder(entityName, options.ctx,
|
|
245
|
-
.
|
|
246
|
-
|
|
247
|
-
|
|
313
|
+
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', options.convertCustomTypes)
|
|
314
|
+
.withSchema(this.getSchemaName(meta, options));
|
|
315
|
+
if (options.upsert) {
|
|
316
|
+
/* istanbul ignore next */
|
|
317
|
+
const uniqueFields = core_1.Utils.isPlainObject(where) ? Object.keys(where) : meta.primaryKeys;
|
|
318
|
+
/* istanbul ignore next */
|
|
319
|
+
qb.insert(data)
|
|
320
|
+
.onConflict(uniqueFields.map(p => meta?.properties[p]?.fieldNames[0] ?? p))
|
|
321
|
+
.merge(Object.keys(data).filter(f => !uniqueFields.includes(f)));
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
qb.update(data).where(where);
|
|
325
|
+
}
|
|
248
326
|
res = await this.rethrow(qb.execute('run', false));
|
|
249
327
|
}
|
|
250
328
|
/* istanbul ignore next */
|
|
@@ -256,6 +334,14 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
256
334
|
options.processCollections ?? (options.processCollections = true);
|
|
257
335
|
options.convertCustomTypes ?? (options.convertCustomTypes = true);
|
|
258
336
|
const meta = this.metadata.get(entityName);
|
|
337
|
+
if (options.upsert) {
|
|
338
|
+
const uniqueFields = core_1.Utils.isPlainObject(where[0]) ? Object.keys(where[0]) : meta.primaryKeys;
|
|
339
|
+
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', options.convertCustomTypes).withSchema(this.getSchemaName(meta, options));
|
|
340
|
+
qb.insert(data)
|
|
341
|
+
.onConflict(uniqueFields.map(p => meta?.properties[p]?.fieldNames[0] ?? p))
|
|
342
|
+
.merge(Object.keys(data[0]).filter(f => !uniqueFields.includes(f)));
|
|
343
|
+
return qb.execute('run', false);
|
|
344
|
+
}
|
|
259
345
|
const collections = options.processCollections ? data.map(d => this.extractManyToMany(entityName, d)) : [];
|
|
260
346
|
const keys = new Set();
|
|
261
347
|
data.forEach(row => Object.keys(row).forEach(k => keys.add(k)));
|
|
@@ -276,7 +362,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
276
362
|
else {
|
|
277
363
|
sql += '?';
|
|
278
364
|
}
|
|
279
|
-
params.push(...pks, prop.fieldNames.length > 1 ? data[idx][key][fieldNameIdx] : data[idx][key]);
|
|
365
|
+
params.push(...pks, prop.fieldNames.length > 1 ? data[idx][key]?.[fieldNameIdx] : data[idx][key]);
|
|
280
366
|
}
|
|
281
367
|
});
|
|
282
368
|
sql += ` else ${this.platform.quoteIdentifier(fieldName)} end, `;
|
|
@@ -300,15 +386,24 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
300
386
|
const pks = core_1.Utils.flatten(pkProps.map(pk => meta.properties[pk].fieldNames));
|
|
301
387
|
sql += pks.length > 1 ? `(${pks.map(pk => `${this.platform.quoteIdentifier(pk)}`).join(', ')})` : this.platform.quoteIdentifier(pks[0]);
|
|
302
388
|
const conds = where.map(cond => {
|
|
389
|
+
if (core_1.Utils.isPlainObject(cond) && core_1.Utils.getObjectKeysSize(cond) === 1) {
|
|
390
|
+
cond = Object.values(cond)[0];
|
|
391
|
+
}
|
|
303
392
|
if (pks.length > 1) {
|
|
304
|
-
pkProps.forEach(pk =>
|
|
393
|
+
pkProps.forEach(pk => {
|
|
394
|
+
if (Array.isArray(cond[pk])) {
|
|
395
|
+
params.push(...core_1.Utils.flatten(cond[pk]));
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
params.push(cond[pk]);
|
|
399
|
+
}
|
|
400
|
+
});
|
|
305
401
|
return `(${new Array(pks.length).fill('?').join(', ')})`;
|
|
306
402
|
}
|
|
307
403
|
params.push(cond);
|
|
308
404
|
return '?';
|
|
309
405
|
});
|
|
310
|
-
|
|
311
|
-
sql += ` in (${values}${conds.join(', ')})`;
|
|
406
|
+
sql += ` in (${conds.join(', ')})`;
|
|
312
407
|
const res = await this.rethrow(this.execute(sql, params, 'run', options.ctx));
|
|
313
408
|
for (let i = 0; i < collections.length; i++) {
|
|
314
409
|
await this.processManyToMany(meta, where[i], collections[i], false, options);
|
|
@@ -321,17 +416,17 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
321
416
|
if (core_1.Utils.isPrimaryKey(where) && pks.length === 1) {
|
|
322
417
|
where = { [pks[0]]: where };
|
|
323
418
|
}
|
|
324
|
-
const qb = this.createQueryBuilder(entityName, options.ctx,
|
|
419
|
+
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', false).delete(where).withSchema(this.getSchemaName(meta, options));
|
|
325
420
|
return this.rethrow(qb.execute('run', false));
|
|
326
421
|
}
|
|
327
422
|
async syncCollection(coll, options) {
|
|
328
|
-
const wrapped = coll.owner
|
|
423
|
+
const wrapped = (0, core_1.helper)(coll.owner);
|
|
329
424
|
const meta = wrapped.__meta;
|
|
330
425
|
const pks = wrapped.getPrimaryKeys(true);
|
|
331
426
|
const snap = coll.getSnapshot();
|
|
332
427
|
const includes = (arr, item) => !!arr.find(i => core_1.Utils.equals(i, item));
|
|
333
|
-
const snapshot = snap ? snap.map(item => item.
|
|
334
|
-
const current = coll.getItems(false).map(item => item.
|
|
428
|
+
const snapshot = snap ? snap.map(item => (0, core_1.helper)(item).getPrimaryKeys(true)) : [];
|
|
429
|
+
const current = coll.getItems(false).map(item => (0, core_1.helper)(item).getPrimaryKeys(true));
|
|
335
430
|
const deleteDiff = snap ? snapshot.filter(item => !includes(current, item)) : true;
|
|
336
431
|
const insertDiff = current.filter(item => !includes(snapshot, item));
|
|
337
432
|
const target = snapshot.filter(item => includes(current, item)).concat(...insertDiff);
|
|
@@ -345,7 +440,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
345
440
|
}
|
|
346
441
|
if (coll.property.reference === core_1.ReferenceType.ONE_TO_MANY) {
|
|
347
442
|
const cols = coll.property.referencedColumnNames;
|
|
348
|
-
const qb = this.createQueryBuilder(coll.property.type, ctx,
|
|
443
|
+
const qb = this.createQueryBuilder(coll.property.type, ctx, 'write')
|
|
349
444
|
.withSchema(this.getSchemaName(meta, options))
|
|
350
445
|
.update({ [coll.property.mappedBy]: pks })
|
|
351
446
|
.getKnexQuery()
|
|
@@ -354,7 +449,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
354
449
|
}
|
|
355
450
|
/* istanbul ignore next */
|
|
356
451
|
const ownerSchema = wrapped.getSchema() === '*' ? this.config.get('schema') : wrapped.getSchema();
|
|
357
|
-
const pivotMeta = this.metadata.find(coll.property.
|
|
452
|
+
const pivotMeta = this.metadata.find(coll.property.pivotEntity);
|
|
358
453
|
if (pivotMeta.schema === '*') {
|
|
359
454
|
/* istanbul ignore next */
|
|
360
455
|
options ?? (options = {});
|
|
@@ -365,7 +460,8 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
365
460
|
async loadFromPivotTable(prop, owners, where = {}, orderBy, ctx, options) {
|
|
366
461
|
const pivotProp2 = this.getPivotInverseProperty(prop);
|
|
367
462
|
const ownerMeta = this.metadata.find(pivotProp2.type);
|
|
368
|
-
const
|
|
463
|
+
const pivotMeta = this.metadata.find(prop.pivotEntity);
|
|
464
|
+
const cond = { [`${prop.pivotEntity}.${pivotProp2.name}`]: { $in: ownerMeta.compositePK ? owners : owners.map(o => o[0]) } };
|
|
369
465
|
/* istanbul ignore if */
|
|
370
466
|
if (!core_1.Utils.isEmpty(where) && Object.keys(where).every(k => core_1.Utils.isOperator(k, false))) {
|
|
371
467
|
where = cond;
|
|
@@ -374,15 +470,23 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
374
470
|
where = { ...where, ...cond };
|
|
375
471
|
}
|
|
376
472
|
orderBy = this.getPivotOrderBy(prop, orderBy);
|
|
377
|
-
const qb = this.createQueryBuilder(prop.type, ctx,
|
|
473
|
+
const qb = this.createQueryBuilder(prop.type, ctx, options?.connectionType)
|
|
378
474
|
.unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES)
|
|
379
475
|
.withSchema(this.getSchemaName(prop.targetMeta, options));
|
|
380
|
-
const populate = this.autoJoinOneToOneOwner(prop.targetMeta, [{ field: prop.
|
|
476
|
+
const populate = this.autoJoinOneToOneOwner(prop.targetMeta, [{ field: prop.pivotEntity }]);
|
|
381
477
|
const fields = this.buildFields(prop.targetMeta, (options?.populate ?? []), [], qb, options?.fields);
|
|
382
478
|
qb.select(fields).populate(populate).where(where).orderBy(orderBy).setLockMode(options?.lockMode, options?.lockTableAliases);
|
|
383
479
|
if (owners.length === 1 && (options?.offset != null || options?.limit != null)) {
|
|
384
480
|
qb.limit(options.limit, options.offset);
|
|
385
481
|
}
|
|
482
|
+
if (prop.targetMeta.schema !== '*' && pivotMeta.schema === '*' && options?.schema) {
|
|
483
|
+
// eslint-disable-next-line dot-notation
|
|
484
|
+
qb['finalize']();
|
|
485
|
+
// eslint-disable-next-line dot-notation
|
|
486
|
+
Object.values(qb['_joins']).forEach(join => {
|
|
487
|
+
join.schema = options.schema;
|
|
488
|
+
});
|
|
489
|
+
}
|
|
386
490
|
const items = owners.length ? await this.rethrow(qb.execute('all')) : [];
|
|
387
491
|
const map = {};
|
|
388
492
|
const pkProps = ownerMeta.getPrimaryProps();
|
|
@@ -407,26 +511,17 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
407
511
|
async execute(queryOrKnex, params = [], method = 'all', ctx) {
|
|
408
512
|
return this.rethrow(this.connection.execute(queryOrKnex, params, method, ctx));
|
|
409
513
|
}
|
|
410
|
-
getTableName(meta, options) {
|
|
411
|
-
let tableName = this.platform.quoteIdentifier(meta.collection);
|
|
412
|
-
if (options.schema === '*') {
|
|
413
|
-
return this.platform.quoteIdentifier(this.config.get('schema')) + '.' + tableName;
|
|
414
|
-
}
|
|
415
|
-
if (meta.schema || options.schema) {
|
|
416
|
-
tableName = this.platform.quoteIdentifier(options.schema ?? meta.schema) + '.' + tableName;
|
|
417
|
-
}
|
|
418
|
-
return tableName;
|
|
419
|
-
}
|
|
420
514
|
/**
|
|
421
515
|
* 1:1 owner side needs to be marked for population so QB auto-joins the owner id
|
|
422
516
|
*/
|
|
423
517
|
autoJoinOneToOneOwner(meta, populate, fields = []) {
|
|
424
|
-
if (!this.config.get('autoJoinOneToOneOwner')
|
|
518
|
+
if (!this.config.get('autoJoinOneToOneOwner')) {
|
|
425
519
|
return populate;
|
|
426
520
|
}
|
|
427
521
|
const relationsToPopulate = populate.map(({ field }) => field);
|
|
428
522
|
const toPopulate = meta.relations
|
|
429
523
|
.filter(prop => prop.reference === core_1.ReferenceType.ONE_TO_ONE && !prop.owner && !relationsToPopulate.includes(prop.name))
|
|
524
|
+
.filter(prop => fields.length === 0 || fields.some(f => prop.name === f || prop.name.startsWith(`${String(f)}.`)))
|
|
430
525
|
.map(prop => ({ field: prop.name, strategy: prop.strategy }));
|
|
431
526
|
return [...populate, ...toPopulate];
|
|
432
527
|
}
|
|
@@ -458,12 +553,15 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
458
553
|
getFieldsForJoinedLoad(qb, meta, explicitFields, populate = [], parentTableAlias, parentJoinPath) {
|
|
459
554
|
const fields = [];
|
|
460
555
|
const joinedProps = this.joinedProps(meta, populate);
|
|
556
|
+
if (explicitFields?.includes('*')) {
|
|
557
|
+
fields.push('*');
|
|
558
|
+
}
|
|
461
559
|
const shouldHaveColumn = (prop, populate, fields) => {
|
|
462
560
|
if (!this.platform.shouldHaveColumn(prop, populate)) {
|
|
463
561
|
return false;
|
|
464
562
|
}
|
|
465
563
|
if (!fields || prop.primary) {
|
|
466
|
-
return
|
|
564
|
+
return !fields?.includes('*');
|
|
467
565
|
}
|
|
468
566
|
return fields.includes(prop.name);
|
|
469
567
|
};
|
|
@@ -506,13 +604,27 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
506
604
|
}
|
|
507
605
|
return prop.fieldNames;
|
|
508
606
|
}
|
|
509
|
-
|
|
510
|
-
|
|
607
|
+
/** @internal */
|
|
608
|
+
createQueryBuilder(entityName, ctx, preferredConnectionType, convertCustomTypes) {
|
|
609
|
+
const connectionType = this.resolveConnectionType({ ctx, connectionType: preferredConnectionType });
|
|
610
|
+
const qb = new query_1.QueryBuilder(entityName, this.metadata, this, ctx, undefined, connectionType);
|
|
511
611
|
if (!convertCustomTypes) {
|
|
512
612
|
qb.unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES);
|
|
513
613
|
}
|
|
514
614
|
return qb;
|
|
515
615
|
}
|
|
616
|
+
resolveConnectionType(args) {
|
|
617
|
+
if (args.ctx) {
|
|
618
|
+
return 'write';
|
|
619
|
+
}
|
|
620
|
+
else if (args.connectionType) {
|
|
621
|
+
return args.connectionType;
|
|
622
|
+
}
|
|
623
|
+
else if (this.config.get('preferReadReplicas') === true) {
|
|
624
|
+
return 'read';
|
|
625
|
+
}
|
|
626
|
+
return 'write';
|
|
627
|
+
}
|
|
516
628
|
extractManyToMany(entityName, data) {
|
|
517
629
|
if (!this.metadata.has(entityName)) {
|
|
518
630
|
return {};
|
|
@@ -541,7 +653,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
541
653
|
deleteDiff = [];
|
|
542
654
|
}
|
|
543
655
|
if (deleteDiff === true || deleteDiff.length > 0) {
|
|
544
|
-
const qb1 = this.createQueryBuilder(prop.
|
|
656
|
+
const qb1 = this.createQueryBuilder(prop.pivotEntity, options?.ctx, 'write')
|
|
545
657
|
.withSchema(this.getSchemaName(meta, options))
|
|
546
658
|
.unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES);
|
|
547
659
|
const knex = qb1.getKnex();
|
|
@@ -562,11 +674,11 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
562
674
|
});
|
|
563
675
|
/* istanbul ignore else */
|
|
564
676
|
if (this.platform.allowsMultiInsert()) {
|
|
565
|
-
await this.nativeInsertMany(prop.
|
|
677
|
+
await this.nativeInsertMany(prop.pivotEntity, items, { ...options, convertCustomTypes: false, processCollections: false });
|
|
566
678
|
}
|
|
567
679
|
else {
|
|
568
680
|
await core_1.Utils.runSerial(items, item => {
|
|
569
|
-
return this.createQueryBuilder(prop.
|
|
681
|
+
return this.createQueryBuilder(prop.pivotEntity, options?.ctx, 'write')
|
|
570
682
|
.unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES)
|
|
571
683
|
.withSchema(this.getSchemaName(meta, options))
|
|
572
684
|
.insert(item)
|
|
@@ -575,7 +687,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
575
687
|
}
|
|
576
688
|
}
|
|
577
689
|
async lockPessimistic(entity, options) {
|
|
578
|
-
const meta = entity.
|
|
690
|
+
const meta = (0, core_1.helper)(entity).__meta;
|
|
579
691
|
const qb = this.createQueryBuilder(entity.constructor.name, options.ctx).unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES).withSchema(options.schema ?? meta.schema);
|
|
580
692
|
const cond = core_1.Utils.getPrimaryKeyCond(entity, meta.primaryKeys);
|
|
581
693
|
qb.select('1').where(cond).setLockMode(options.lockMode, options.lockTableAliases);
|
|
@@ -601,6 +713,43 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
601
713
|
});
|
|
602
714
|
return orderBy;
|
|
603
715
|
}
|
|
716
|
+
normalizeFields(fields, prefix = '') {
|
|
717
|
+
const ret = [];
|
|
718
|
+
for (const field of fields) {
|
|
719
|
+
if (typeof field === 'string') {
|
|
720
|
+
ret.push(prefix + field);
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
723
|
+
if (core_1.Utils.isPlainObject(field)) {
|
|
724
|
+
for (const key of Object.keys(field)) {
|
|
725
|
+
ret.push(...this.normalizeFields(field[key], key + '.'));
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
return ret;
|
|
730
|
+
}
|
|
731
|
+
processField(meta, prop, field, ret, populate, joinedProps, qb) {
|
|
732
|
+
if (!prop || (prop.reference === core_1.ReferenceType.ONE_TO_ONE && !prop.owner)) {
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
if (prop.reference === core_1.ReferenceType.EMBEDDED) {
|
|
736
|
+
if (prop.object) {
|
|
737
|
+
ret.push(prop.fieldNames[0]);
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
const parts = field.split('.');
|
|
741
|
+
const top = parts.shift();
|
|
742
|
+
for (const key of Object.keys(prop.embeddedProps)) {
|
|
743
|
+
if (!top || key === top) {
|
|
744
|
+
this.processField(meta, prop.embeddedProps[key], parts.join('.'), ret, populate, joinedProps, qb);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
if (prop.fieldNames) {
|
|
750
|
+
ret.push(prop.fieldNames[0]);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
604
753
|
buildFields(meta, populate, joinedProps, qb, fields) {
|
|
605
754
|
const lazyProps = meta.props.filter(prop => prop.lazy && !populate.some(p => p.field === prop.name || p.all));
|
|
606
755
|
const hasLazyFormulas = meta.props.some(p => p.lazy && p.formula);
|
|
@@ -611,11 +760,21 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
611
760
|
ret.push(...this.getFieldsForJoinedLoad(qb, meta, fields, populate));
|
|
612
761
|
}
|
|
613
762
|
else if (fields) {
|
|
614
|
-
for (const field of
|
|
615
|
-
if (
|
|
763
|
+
for (const field of this.normalizeFields(fields)) {
|
|
764
|
+
if (field === '*') {
|
|
765
|
+
ret.push('*');
|
|
616
766
|
continue;
|
|
617
767
|
}
|
|
618
|
-
|
|
768
|
+
const parts = field.split('.');
|
|
769
|
+
const rootPropName = parts.shift(); // first one is the `prop`
|
|
770
|
+
const prop = core_1.QueryHelper.findProperty(rootPropName, {
|
|
771
|
+
metadata: this.metadata,
|
|
772
|
+
platform: this.platform,
|
|
773
|
+
entityName: meta.className,
|
|
774
|
+
where: {},
|
|
775
|
+
aliasMap: qb.getAliasMap(),
|
|
776
|
+
});
|
|
777
|
+
this.processField(meta, prop, parts.join('.'), ret, populate, joinedProps, qb);
|
|
619
778
|
}
|
|
620
779
|
ret.unshift(...meta.primaryKeys.filter(pk => !fields.includes(pk)));
|
|
621
780
|
}
|
|
@@ -638,7 +797,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
638
797
|
.filter(prop => prop.customType?.convertToDatabaseValueSQL || prop.customType?.convertToJSValueSQL)
|
|
639
798
|
.forEach(prop => ret.push(prop.name));
|
|
640
799
|
}
|
|
641
|
-
return ret.length > 0 ? ret : ['*'];
|
|
800
|
+
return ret.length > 0 ? core_1.Utils.unique(ret) : ['*'];
|
|
642
801
|
}
|
|
643
802
|
}
|
|
644
803
|
exports.AbstractSqlDriver = AbstractSqlDriver;
|