@mikro-orm/knex 6.0.0-dev.4 → 6.0.0-dev.41
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.js → AbstractSqlConnection.js} +6 -1
- package/AbstractSqlDriver.d.ts +66 -0
- package/{dist/AbstractSqlDriver.js → AbstractSqlDriver.js} +277 -95
- package/{dist/AbstractSqlPlatform.d.ts → AbstractSqlPlatform.d.ts} +7 -7
- package/{dist/AbstractSqlPlatform.js → AbstractSqlPlatform.js} +12 -14
- 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 -4
- package/{dist/SqlEntityRepository.js → SqlEntityRepository.js} +1 -2
- package/{dist/index.d.ts → index.d.ts} +1 -0
- package/{dist/index.js → index.js} +6 -1
- package/index.mjs +194 -0
- package/package.json +18 -47
- package/query/ArrayCriteriaNode.d.ts +9 -0
- package/{dist/query → query}/CriteriaNode.d.ts +8 -8
- package/{dist/query → query}/CriteriaNode.js +15 -12
- package/query/CriteriaNodeFactory.d.ts +12 -0
- package/{dist/query → query}/CriteriaNodeFactory.js +10 -10
- package/{dist/query → query}/ObjectCriteriaNode.d.ts +3 -3
- package/{dist/query → query}/ObjectCriteriaNode.js +19 -6
- package/{dist/query → query}/QueryBuilder.d.ts +66 -24
- package/{dist/query → query}/QueryBuilder.js +381 -94
- package/{dist/query → query}/QueryBuilderHelper.d.ts +19 -11
- package/{dist/query → query}/QueryBuilderHelper.js +227 -116
- package/{dist/query → query}/ScalarCriteriaNode.d.ts +2 -2
- package/{dist/query → query}/ScalarCriteriaNode.js +6 -6
- package/{dist/query → query}/index.js +5 -1
- package/{dist/schema → schema}/DatabaseSchema.d.ts +1 -1
- package/{dist/schema → schema}/DatabaseSchema.js +11 -19
- package/{dist/schema → schema}/DatabaseTable.d.ts +9 -9
- package/{dist/schema → schema}/DatabaseTable.js +22 -22
- 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} +10 -12
- package/{dist/schema/SchemaGenerator.js → schema/SqlSchemaGenerator.js} +89 -45
- 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} +21 -16
- 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
- package/dist/query/ArrayCriteriaNode.d.ts +0 -9
- package/dist/query/CriteriaNodeFactory.d.ts +0 -12
- /package/{dist/AbstractSqlConnection.d.ts → AbstractSqlConnection.d.ts} +0 -0
- /package/{dist/MonkeyPatchable.d.ts → MonkeyPatchable.d.ts} +0 -0
- /package/{dist/MonkeyPatchable.js → MonkeyPatchable.js} +0 -0
- /package/{dist/query → query}/ArrayCriteriaNode.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/typings.js → typings.js} +0 -0
|
@@ -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,21 +21,33 @@ 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);
|
|
32
|
+
const orderBy = [...core_1.Utils.asArray(options.orderBy), ...joinedPropsOrderBy];
|
|
29
33
|
if (core_1.Utils.isPrimaryKey(where, meta.compositePK)) {
|
|
30
34
|
where = { [core_1.Utils.getPrimaryKeyHash(meta.primaryKeys)]: where };
|
|
31
35
|
}
|
|
36
|
+
const { first, last, before, after } = options;
|
|
37
|
+
const isCursorPagination = [first, last, before, after].some(v => v != null);
|
|
32
38
|
qb.select(fields)
|
|
33
|
-
.populate(populate)
|
|
39
|
+
.populate(populate, joinedProps.length > 0 ? options.populateWhere : undefined)
|
|
34
40
|
.where(where)
|
|
35
|
-
.orderBy([...core_1.Utils.asArray(options.orderBy), ...joinedPropsOrderBy])
|
|
36
41
|
.groupBy(options.groupBy)
|
|
37
42
|
.having(options.having)
|
|
38
43
|
.withSchema(this.getSchemaName(meta, options));
|
|
44
|
+
if (isCursorPagination) {
|
|
45
|
+
const { orderBy: newOrderBy, where } = this.processCursorOptions(meta, options, orderBy);
|
|
46
|
+
qb.andWhere(where).orderBy(newOrderBy);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
qb.orderBy(orderBy);
|
|
50
|
+
}
|
|
39
51
|
if (options.limit !== undefined) {
|
|
40
52
|
qb.limit(options.limit, options.offset);
|
|
41
53
|
}
|
|
@@ -44,6 +56,9 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
44
56
|
}
|
|
45
57
|
core_1.Utils.asArray(options.flags).forEach(flag => qb.setFlag(flag));
|
|
46
58
|
const result = await this.rethrow(qb.execute('all'));
|
|
59
|
+
if (isCursorPagination && !first && !!last) {
|
|
60
|
+
result.reverse();
|
|
61
|
+
}
|
|
47
62
|
if (joinedProps.length > 0) {
|
|
48
63
|
return this.mergeJoinedResult(result, meta);
|
|
49
64
|
}
|
|
@@ -57,9 +72,70 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
57
72
|
if (joinedProps.length === 0) {
|
|
58
73
|
opts.limit = 1;
|
|
59
74
|
}
|
|
75
|
+
if (opts.limit > 0 && !opts.flags?.includes(core_1.QueryFlag.DISABLE_PAGINATE)) {
|
|
76
|
+
opts.flags ??= [];
|
|
77
|
+
opts.flags.push(core_1.QueryFlag.DISABLE_PAGINATE);
|
|
78
|
+
}
|
|
60
79
|
const res = await this.find(entityName, where, opts);
|
|
61
80
|
return res[0] || null;
|
|
62
81
|
}
|
|
82
|
+
async findVirtual(entityName, where, options) {
|
|
83
|
+
const meta = this.metadata.get(entityName);
|
|
84
|
+
/* istanbul ignore next */
|
|
85
|
+
if (!meta.expression) {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
if (typeof meta.expression === 'string') {
|
|
89
|
+
return this.wrapVirtualExpressionInSubquery(meta, meta.expression, where, options);
|
|
90
|
+
}
|
|
91
|
+
const em = this.createEntityManager(false);
|
|
92
|
+
em.setTransactionContext(options.ctx);
|
|
93
|
+
const res = meta.expression(em, where, options);
|
|
94
|
+
if (res instanceof (query_1.QueryBuilder)) {
|
|
95
|
+
return this.wrapVirtualExpressionInSubquery(meta, res.getFormattedQuery(), where, options);
|
|
96
|
+
}
|
|
97
|
+
/* istanbul ignore next */
|
|
98
|
+
return res;
|
|
99
|
+
}
|
|
100
|
+
async countVirtual(entityName, where, options) {
|
|
101
|
+
const meta = this.metadata.get(entityName);
|
|
102
|
+
/* istanbul ignore next */
|
|
103
|
+
if (!meta.expression) {
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
if (typeof meta.expression === 'string') {
|
|
107
|
+
return this.wrapVirtualExpressionInSubquery(meta, meta.expression, where, options, query_1.QueryType.COUNT);
|
|
108
|
+
}
|
|
109
|
+
const em = this.createEntityManager(false);
|
|
110
|
+
em.setTransactionContext(options.ctx);
|
|
111
|
+
const res = meta.expression(em, where, options);
|
|
112
|
+
if (res instanceof (query_1.QueryBuilder)) {
|
|
113
|
+
return this.wrapVirtualExpressionInSubquery(meta, res.getFormattedQuery(), where, options, query_1.QueryType.COUNT);
|
|
114
|
+
}
|
|
115
|
+
/* istanbul ignore next */
|
|
116
|
+
return res;
|
|
117
|
+
}
|
|
118
|
+
async wrapVirtualExpressionInSubquery(meta, expression, where, options, type = query_1.QueryType.SELECT) {
|
|
119
|
+
const qb = this.createQueryBuilder(meta.className, options?.ctx, options.connectionType, options.convertCustomTypes)
|
|
120
|
+
.limit(options?.limit, options?.offset);
|
|
121
|
+
if (options.orderBy) {
|
|
122
|
+
qb.orderBy(options.orderBy);
|
|
123
|
+
}
|
|
124
|
+
qb.where(where);
|
|
125
|
+
const kqb = qb.getKnexQuery().clear('select');
|
|
126
|
+
if (type === query_1.QueryType.COUNT) {
|
|
127
|
+
kqb.select(qb.raw('count(*) as count'));
|
|
128
|
+
}
|
|
129
|
+
else { // select
|
|
130
|
+
kqb.select('*');
|
|
131
|
+
}
|
|
132
|
+
kqb.fromRaw(`(${expression}) as ${this.platform.quoteIdentifier(qb.alias)}`);
|
|
133
|
+
const res = await this.execute(kqb);
|
|
134
|
+
if (type === query_1.QueryType.COUNT) {
|
|
135
|
+
return res[0].count;
|
|
136
|
+
}
|
|
137
|
+
return res.map(row => this.mapResult(row, meta));
|
|
138
|
+
}
|
|
63
139
|
mapResult(result, meta, populate = [], qb, map = {}) {
|
|
64
140
|
const ret = super.mapResult(result, meta);
|
|
65
141
|
/* istanbul ignore if */
|
|
@@ -90,8 +166,8 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
90
166
|
}));
|
|
91
167
|
if (!hasPK) {
|
|
92
168
|
// initialize empty collections
|
|
93
|
-
if ([core_1.
|
|
94
|
-
result[relation.name]
|
|
169
|
+
if ([core_1.ReferenceKind.MANY_TO_MANY, core_1.ReferenceKind.ONE_TO_MANY].includes(relation.kind)) {
|
|
170
|
+
result[relation.name] ??= [];
|
|
95
171
|
}
|
|
96
172
|
return;
|
|
97
173
|
}
|
|
@@ -115,8 +191,8 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
115
191
|
else {
|
|
116
192
|
map[key] = result;
|
|
117
193
|
}
|
|
118
|
-
if ([core_1.
|
|
119
|
-
result[relation.name]
|
|
194
|
+
if ([core_1.ReferenceKind.MANY_TO_MANY, core_1.ReferenceKind.ONE_TO_MANY].includes(relation.kind)) {
|
|
195
|
+
result[relation.name] ??= [];
|
|
120
196
|
this.appendToCollection(meta2, result[relation.name], relationPojo);
|
|
121
197
|
}
|
|
122
198
|
else {
|
|
@@ -137,23 +213,25 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
137
213
|
collection.push(relationPojo);
|
|
138
214
|
}
|
|
139
215
|
}
|
|
140
|
-
async count(entityName, where, options = {}
|
|
216
|
+
async count(entityName, where, options = {}) {
|
|
141
217
|
const meta = this.metadata.find(entityName);
|
|
142
|
-
|
|
143
|
-
|
|
218
|
+
if (meta?.virtual) {
|
|
219
|
+
return this.countVirtual(entityName, where, options);
|
|
220
|
+
}
|
|
221
|
+
const qb = this.createQueryBuilder(entityName, options.ctx, options.connectionType, false)
|
|
144
222
|
.groupBy(options.groupBy)
|
|
145
223
|
.having(options.having)
|
|
146
224
|
.populate(options.populate ?? [])
|
|
147
225
|
.withSchema(this.getSchemaName(meta, options))
|
|
148
226
|
.where(where);
|
|
149
|
-
return this.rethrow(qb.getCount(
|
|
227
|
+
return this.rethrow(qb.getCount());
|
|
150
228
|
}
|
|
151
229
|
async nativeInsert(entityName, data, options = {}) {
|
|
152
|
-
options.convertCustomTypes
|
|
230
|
+
options.convertCustomTypes ??= true;
|
|
153
231
|
const meta = this.metadata.find(entityName);
|
|
154
232
|
const collections = this.extractManyToMany(entityName, data);
|
|
155
|
-
const pks = this.
|
|
156
|
-
const qb = this.createQueryBuilder(entityName, options.ctx,
|
|
233
|
+
const pks = meta?.primaryKeys ?? [this.config.getNamingStrategy().referenceColumnName()];
|
|
234
|
+
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', options.convertCustomTypes).withSchema(this.getSchemaName(meta, options));
|
|
157
235
|
const res = await this.rethrow(qb.insert(data).execute('run', false));
|
|
158
236
|
res.row = res.row || {};
|
|
159
237
|
let pk;
|
|
@@ -161,68 +239,77 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
161
239
|
pk = core_1.Utils.getPrimaryKeyCond(data, pks);
|
|
162
240
|
}
|
|
163
241
|
else {
|
|
164
|
-
|
|
242
|
+
/* istanbul ignore next */
|
|
243
|
+
res.insertId = data[pks[0]] ?? res.insertId ?? res.row[pks[0]];
|
|
165
244
|
pk = [res.insertId];
|
|
166
245
|
}
|
|
167
246
|
await this.processManyToMany(meta, pk, collections, false, options);
|
|
168
247
|
return res;
|
|
169
248
|
}
|
|
170
249
|
async nativeInsertMany(entityName, data, options = {}) {
|
|
171
|
-
options.processCollections
|
|
172
|
-
options.convertCustomTypes
|
|
173
|
-
const meta = this.metadata.
|
|
250
|
+
options.processCollections ??= true;
|
|
251
|
+
options.convertCustomTypes ??= true;
|
|
252
|
+
const meta = this.metadata.find(entityName);
|
|
174
253
|
const collections = options.processCollections ? data.map(d => this.extractManyToMany(entityName, d)) : [];
|
|
175
254
|
const pks = this.getPrimaryKeyFields(entityName);
|
|
176
255
|
const set = new Set();
|
|
177
|
-
data.forEach(row =>
|
|
178
|
-
const props = [...set].map(name => meta
|
|
256
|
+
data.forEach(row => core_1.Utils.keys(row).forEach(k => set.add(k)));
|
|
257
|
+
const props = [...set].map(name => meta?.properties[name] ?? { name, fieldNames: [name] });
|
|
179
258
|
const fields = core_1.Utils.flatten(props.map(prop => prop.fieldNames));
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
259
|
+
const params = [];
|
|
260
|
+
/* istanbul ignore next */
|
|
261
|
+
const tableName = meta ? this.getTableName(meta, options) : this.platform.quoteIdentifier(entityName);
|
|
262
|
+
let sql = `insert into ${tableName} `;
|
|
263
|
+
sql += fields.length > 0 ? '(' + fields.map(k => this.platform.quoteIdentifier(k)).join(', ') + ')' : `(${this.platform.quoteIdentifier(pks[0])})`;
|
|
264
|
+
if (fields.length > 0 || this.platform.usesDefaultKeyword()) {
|
|
265
|
+
sql += ' values ';
|
|
184
266
|
}
|
|
185
267
|
else {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
268
|
+
sql += ' ' + data.map(() => `select null as ${this.platform.quoteIdentifier(pks[0])}`).join(' union all ');
|
|
269
|
+
}
|
|
270
|
+
const addParams = (prop, row) => {
|
|
271
|
+
if (options.convertCustomTypes && prop.customType) {
|
|
272
|
+
params.push(prop.customType.convertToDatabaseValue(row[prop.name], this.platform, { key: prop.name, mode: 'query' }));
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
params.push(row[prop.name]);
|
|
276
|
+
};
|
|
277
|
+
if (fields.length > 0 || this.platform.usesDefaultKeyword()) {
|
|
191
278
|
sql += data.map(row => {
|
|
192
279
|
const keys = [];
|
|
193
280
|
props.forEach(prop => {
|
|
194
281
|
if (prop.fieldNames.length > 1) {
|
|
195
|
-
params.push(...row[prop.name]);
|
|
196
|
-
keys.push(...prop.fieldNames.map(
|
|
282
|
+
params.push(...(row[prop.name] ?? prop.fieldNames.map(() => null)));
|
|
283
|
+
keys.push(...(row[prop.name] ?? prop.fieldNames).map(() => '?'));
|
|
197
284
|
}
|
|
198
285
|
else if (prop.customType && 'convertToDatabaseValueSQL' in prop.customType && !this.platform.isRaw(row[prop.name])) {
|
|
199
286
|
keys.push(prop.customType.convertToDatabaseValueSQL('?', this.platform));
|
|
200
|
-
|
|
287
|
+
addParams(prop, row);
|
|
201
288
|
}
|
|
202
289
|
else {
|
|
203
|
-
|
|
290
|
+
addParams(prop, row);
|
|
204
291
|
keys.push('?');
|
|
205
292
|
}
|
|
206
293
|
});
|
|
207
|
-
return '(' + keys.join(', ') + ')';
|
|
294
|
+
return '(' + (keys.join(', ') || 'default') + ')';
|
|
208
295
|
}).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
296
|
}
|
|
297
|
+
if (this.platform.usesReturningStatement()) {
|
|
298
|
+
/* istanbul ignore next */
|
|
299
|
+
const returningProps = meta.hydrateProps.filter(prop => prop.persist !== false && (prop.primary || prop.defaultRaw));
|
|
300
|
+
const returningFields = core_1.Utils.flatten(returningProps.map(prop => prop.fieldNames));
|
|
301
|
+
/* istanbul ignore next */
|
|
302
|
+
sql += returningFields.length > 0 ? ` returning ${returningFields.map(field => this.platform.quoteIdentifier(field)).join(', ')}` : '';
|
|
303
|
+
}
|
|
304
|
+
const res = await this.execute(sql, params, 'run', options.ctx);
|
|
218
305
|
let pk;
|
|
219
306
|
/* istanbul ignore next */
|
|
220
307
|
if (pks.length > 1) { // owner has composite pk
|
|
221
308
|
pk = data.map(d => core_1.Utils.getPrimaryKeyCond(d, pks));
|
|
222
309
|
}
|
|
223
310
|
else {
|
|
224
|
-
res.row
|
|
225
|
-
res.rows
|
|
311
|
+
res.row ??= {};
|
|
312
|
+
res.rows ??= [];
|
|
226
313
|
pk = data.map((d, i) => d[pks[0]] ?? res.rows[i]?.[pks[0]]).map(d => [d]);
|
|
227
314
|
res.insertId = res.insertId || res.row[pks[0]];
|
|
228
315
|
}
|
|
@@ -232,19 +319,29 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
232
319
|
return res;
|
|
233
320
|
}
|
|
234
321
|
async nativeUpdate(entityName, where, data, options = {}) {
|
|
235
|
-
options.convertCustomTypes
|
|
322
|
+
options.convertCustomTypes ??= true;
|
|
236
323
|
const meta = this.metadata.find(entityName);
|
|
237
324
|
const pks = this.getPrimaryKeyFields(entityName);
|
|
238
325
|
const collections = this.extractManyToMany(entityName, data);
|
|
239
326
|
let res = { affectedRows: 0, insertId: 0, row: {} };
|
|
240
327
|
if (core_1.Utils.isPrimaryKey(where) && pks.length === 1) {
|
|
241
|
-
|
|
328
|
+
/* istanbul ignore next */
|
|
329
|
+
where = { [meta?.primaryKeys[0] ?? pks[0]]: where };
|
|
242
330
|
}
|
|
243
331
|
if (core_1.Utils.hasObjectKeys(data)) {
|
|
244
|
-
const qb = this.createQueryBuilder(entityName, options.ctx,
|
|
245
|
-
.
|
|
246
|
-
|
|
247
|
-
|
|
332
|
+
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', options.convertCustomTypes)
|
|
333
|
+
.withSchema(this.getSchemaName(meta, options));
|
|
334
|
+
if (options.upsert) {
|
|
335
|
+
/* istanbul ignore next */
|
|
336
|
+
const uniqueFields = core_1.Utils.isPlainObject(where) ? core_1.Utils.keys(where) : meta.primaryKeys;
|
|
337
|
+
/* istanbul ignore next */
|
|
338
|
+
qb.insert(data)
|
|
339
|
+
.onConflict(uniqueFields.map(p => meta?.properties[p]?.fieldNames[0] ?? p))
|
|
340
|
+
.merge(core_1.Utils.keys(data).filter(f => !uniqueFields.includes(f)));
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
qb.update(data).where(where);
|
|
344
|
+
}
|
|
248
345
|
res = await this.rethrow(qb.execute('run', false));
|
|
249
346
|
}
|
|
250
347
|
/* istanbul ignore next */
|
|
@@ -253,12 +350,20 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
253
350
|
return res;
|
|
254
351
|
}
|
|
255
352
|
async nativeUpdateMany(entityName, where, data, options = {}) {
|
|
256
|
-
options.processCollections
|
|
257
|
-
options.convertCustomTypes
|
|
353
|
+
options.processCollections ??= true;
|
|
354
|
+
options.convertCustomTypes ??= true;
|
|
258
355
|
const meta = this.metadata.get(entityName);
|
|
356
|
+
if (options.upsert) {
|
|
357
|
+
const uniqueFields = core_1.Utils.isPlainObject(where[0]) ? Object.keys(where[0]) : meta.primaryKeys;
|
|
358
|
+
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', options.convertCustomTypes).withSchema(this.getSchemaName(meta, options));
|
|
359
|
+
qb.insert(data)
|
|
360
|
+
.onConflict(uniqueFields.map(p => meta?.properties[p]?.fieldNames[0] ?? p))
|
|
361
|
+
.merge(Object.keys(data[0]).filter(f => !uniqueFields.includes(f)));
|
|
362
|
+
return qb.execute('run', false);
|
|
363
|
+
}
|
|
259
364
|
const collections = options.processCollections ? data.map(d => this.extractManyToMany(entityName, d)) : [];
|
|
260
365
|
const keys = new Set();
|
|
261
|
-
data.forEach(row =>
|
|
366
|
+
data.forEach(row => core_1.Utils.keys(row).forEach(k => keys.add(k)));
|
|
262
367
|
const pkCond = core_1.Utils.flatten(meta.primaryKeys.map(pk => meta.properties[pk].fieldNames)).map(pk => `${this.platform.quoteIdentifier(pk)} = ?`).join(' and ');
|
|
263
368
|
const params = [];
|
|
264
369
|
let sql = `update ${this.getTableName(meta, options)} set `;
|
|
@@ -276,7 +381,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
276
381
|
else {
|
|
277
382
|
sql += '?';
|
|
278
383
|
}
|
|
279
|
-
params.push(...pks, prop.fieldNames.length > 1 ? data[idx][key][fieldNameIdx] : data[idx][key]);
|
|
384
|
+
params.push(...pks, prop.fieldNames.length > 1 ? data[idx][key]?.[fieldNameIdx] : data[idx][key]);
|
|
280
385
|
}
|
|
281
386
|
});
|
|
282
387
|
sql += ` else ${this.platform.quoteIdentifier(fieldName)} end, `;
|
|
@@ -300,15 +405,24 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
300
405
|
const pks = core_1.Utils.flatten(pkProps.map(pk => meta.properties[pk].fieldNames));
|
|
301
406
|
sql += pks.length > 1 ? `(${pks.map(pk => `${this.platform.quoteIdentifier(pk)}`).join(', ')})` : this.platform.quoteIdentifier(pks[0]);
|
|
302
407
|
const conds = where.map(cond => {
|
|
408
|
+
if (core_1.Utils.isPlainObject(cond) && core_1.Utils.getObjectKeysSize(cond) === 1) {
|
|
409
|
+
cond = Object.values(cond)[0];
|
|
410
|
+
}
|
|
303
411
|
if (pks.length > 1) {
|
|
304
|
-
pkProps.forEach(pk =>
|
|
412
|
+
pkProps.forEach(pk => {
|
|
413
|
+
if (Array.isArray(cond[pk])) {
|
|
414
|
+
params.push(...core_1.Utils.flatten(cond[pk]));
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
params.push(cond[pk]);
|
|
418
|
+
}
|
|
419
|
+
});
|
|
305
420
|
return `(${new Array(pks.length).fill('?').join(', ')})`;
|
|
306
421
|
}
|
|
307
422
|
params.push(cond);
|
|
308
423
|
return '?';
|
|
309
424
|
});
|
|
310
|
-
|
|
311
|
-
sql += ` in (${values}${conds.join(', ')})`;
|
|
425
|
+
sql += ` in (${conds.join(', ')})`;
|
|
312
426
|
const res = await this.rethrow(this.execute(sql, params, 'run', options.ctx));
|
|
313
427
|
for (let i = 0; i < collections.length; i++) {
|
|
314
428
|
await this.processManyToMany(meta, where[i], collections[i], false, options);
|
|
@@ -321,17 +435,17 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
321
435
|
if (core_1.Utils.isPrimaryKey(where) && pks.length === 1) {
|
|
322
436
|
where = { [pks[0]]: where };
|
|
323
437
|
}
|
|
324
|
-
const qb = this.createQueryBuilder(entityName, options.ctx,
|
|
438
|
+
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', false).delete(where).withSchema(this.getSchemaName(meta, options));
|
|
325
439
|
return this.rethrow(qb.execute('run', false));
|
|
326
440
|
}
|
|
327
441
|
async syncCollection(coll, options) {
|
|
328
|
-
const wrapped = coll.owner
|
|
442
|
+
const wrapped = (0, core_1.helper)(coll.owner);
|
|
329
443
|
const meta = wrapped.__meta;
|
|
330
444
|
const pks = wrapped.getPrimaryKeys(true);
|
|
331
445
|
const snap = coll.getSnapshot();
|
|
332
446
|
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.
|
|
447
|
+
const snapshot = snap ? snap.map(item => (0, core_1.helper)(item).getPrimaryKeys(true)) : [];
|
|
448
|
+
const current = coll.getItems(false).map(item => (0, core_1.helper)(item).getPrimaryKeys(true));
|
|
335
449
|
const deleteDiff = snap ? snapshot.filter(item => !includes(current, item)) : true;
|
|
336
450
|
const insertDiff = current.filter(item => !includes(snapshot, item));
|
|
337
451
|
const target = snapshot.filter(item => includes(current, item)).concat(...insertDiff);
|
|
@@ -343,9 +457,9 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
343
457
|
deleteDiff.push(...snapshot);
|
|
344
458
|
insertDiff.push(...current);
|
|
345
459
|
}
|
|
346
|
-
if (coll.property.
|
|
460
|
+
if (coll.property.kind === core_1.ReferenceKind.ONE_TO_MANY) {
|
|
347
461
|
const cols = coll.property.referencedColumnNames;
|
|
348
|
-
const qb = this.createQueryBuilder(coll.property.type, ctx,
|
|
462
|
+
const qb = this.createQueryBuilder(coll.property.type, ctx, 'write')
|
|
349
463
|
.withSchema(this.getSchemaName(meta, options))
|
|
350
464
|
.update({ [coll.property.mappedBy]: pks })
|
|
351
465
|
.getKnexQuery()
|
|
@@ -354,10 +468,10 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
354
468
|
}
|
|
355
469
|
/* istanbul ignore next */
|
|
356
470
|
const ownerSchema = wrapped.getSchema() === '*' ? this.config.get('schema') : wrapped.getSchema();
|
|
357
|
-
const pivotMeta = this.metadata.find(coll.property.
|
|
471
|
+
const pivotMeta = this.metadata.find(coll.property.pivotEntity);
|
|
358
472
|
if (pivotMeta.schema === '*') {
|
|
359
473
|
/* istanbul ignore next */
|
|
360
|
-
options
|
|
474
|
+
options ??= {};
|
|
361
475
|
options.schema = ownerSchema;
|
|
362
476
|
}
|
|
363
477
|
return this.rethrow(this.updateCollectionDiff(meta, coll.property, pks, deleteDiff, insertDiff, options));
|
|
@@ -365,7 +479,8 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
365
479
|
async loadFromPivotTable(prop, owners, where = {}, orderBy, ctx, options) {
|
|
366
480
|
const pivotProp2 = this.getPivotInverseProperty(prop);
|
|
367
481
|
const ownerMeta = this.metadata.find(pivotProp2.type);
|
|
368
|
-
const
|
|
482
|
+
const pivotMeta = this.metadata.find(prop.pivotEntity);
|
|
483
|
+
const cond = { [`${prop.pivotEntity}.${pivotProp2.name}`]: { $in: ownerMeta.compositePK ? owners : owners.map(o => o[0]) } };
|
|
369
484
|
/* istanbul ignore if */
|
|
370
485
|
if (!core_1.Utils.isEmpty(where) && Object.keys(where).every(k => core_1.Utils.isOperator(k, false))) {
|
|
371
486
|
where = cond;
|
|
@@ -374,15 +489,23 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
374
489
|
where = { ...where, ...cond };
|
|
375
490
|
}
|
|
376
491
|
orderBy = this.getPivotOrderBy(prop, orderBy);
|
|
377
|
-
const qb = this.createQueryBuilder(prop.type, ctx,
|
|
492
|
+
const qb = this.createQueryBuilder(prop.type, ctx, options?.connectionType)
|
|
378
493
|
.unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES)
|
|
379
494
|
.withSchema(this.getSchemaName(prop.targetMeta, options));
|
|
380
|
-
const populate = this.autoJoinOneToOneOwner(prop.targetMeta, [{ field: prop.
|
|
495
|
+
const populate = this.autoJoinOneToOneOwner(prop.targetMeta, [{ field: prop.pivotEntity }]);
|
|
381
496
|
const fields = this.buildFields(prop.targetMeta, (options?.populate ?? []), [], qb, options?.fields);
|
|
382
497
|
qb.select(fields).populate(populate).where(where).orderBy(orderBy).setLockMode(options?.lockMode, options?.lockTableAliases);
|
|
383
498
|
if (owners.length === 1 && (options?.offset != null || options?.limit != null)) {
|
|
384
499
|
qb.limit(options.limit, options.offset);
|
|
385
500
|
}
|
|
501
|
+
if (prop.targetMeta.schema !== '*' && pivotMeta.schema === '*' && options?.schema) {
|
|
502
|
+
// eslint-disable-next-line dot-notation
|
|
503
|
+
qb['finalize']();
|
|
504
|
+
// eslint-disable-next-line dot-notation
|
|
505
|
+
Object.values(qb['_joins']).forEach(join => {
|
|
506
|
+
join.schema = options.schema;
|
|
507
|
+
});
|
|
508
|
+
}
|
|
386
509
|
const items = owners.length ? await this.rethrow(qb.execute('all')) : [];
|
|
387
510
|
const map = {};
|
|
388
511
|
const pkProps = ownerMeta.getPrimaryProps();
|
|
@@ -407,33 +530,24 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
407
530
|
async execute(queryOrKnex, params = [], method = 'all', ctx) {
|
|
408
531
|
return this.rethrow(this.connection.execute(queryOrKnex, params, method, ctx));
|
|
409
532
|
}
|
|
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
533
|
/**
|
|
421
534
|
* 1:1 owner side needs to be marked for population so QB auto-joins the owner id
|
|
422
535
|
*/
|
|
423
536
|
autoJoinOneToOneOwner(meta, populate, fields = []) {
|
|
424
|
-
if (!this.config.get('autoJoinOneToOneOwner')
|
|
537
|
+
if (!this.config.get('autoJoinOneToOneOwner')) {
|
|
425
538
|
return populate;
|
|
426
539
|
}
|
|
427
540
|
const relationsToPopulate = populate.map(({ field }) => field);
|
|
428
541
|
const toPopulate = meta.relations
|
|
429
|
-
.filter(prop => prop.
|
|
542
|
+
.filter(prop => prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner && !relationsToPopulate.includes(prop.name))
|
|
543
|
+
.filter(prop => fields.length === 0 || fields.some(f => prop.name === f || prop.name.startsWith(`${String(f)}.`)))
|
|
430
544
|
.map(prop => ({ field: prop.name, strategy: prop.strategy }));
|
|
431
545
|
return [...populate, ...toPopulate];
|
|
432
546
|
}
|
|
433
547
|
joinedProps(meta, populate) {
|
|
434
548
|
return populate.filter(p => {
|
|
435
549
|
const prop = meta.properties[p.field] || {};
|
|
436
|
-
return (p.strategy || prop.strategy || this.config.get('loadStrategy')) === core_1.LoadStrategy.JOINED && prop.
|
|
550
|
+
return (p.strategy || prop.strategy || this.config.get('loadStrategy')) === core_1.LoadStrategy.JOINED && prop.kind !== core_1.ReferenceKind.SCALAR;
|
|
437
551
|
});
|
|
438
552
|
}
|
|
439
553
|
/**
|
|
@@ -458,12 +572,15 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
458
572
|
getFieldsForJoinedLoad(qb, meta, explicitFields, populate = [], parentTableAlias, parentJoinPath) {
|
|
459
573
|
const fields = [];
|
|
460
574
|
const joinedProps = this.joinedProps(meta, populate);
|
|
575
|
+
if (explicitFields?.includes('*')) {
|
|
576
|
+
fields.push('*');
|
|
577
|
+
}
|
|
461
578
|
const shouldHaveColumn = (prop, populate, fields) => {
|
|
462
579
|
if (!this.platform.shouldHaveColumn(prop, populate)) {
|
|
463
580
|
return false;
|
|
464
581
|
}
|
|
465
582
|
if (!fields || prop.primary) {
|
|
466
|
-
return
|
|
583
|
+
return !fields?.includes('*');
|
|
467
584
|
}
|
|
468
585
|
return fields.includes(prop.name);
|
|
469
586
|
};
|
|
@@ -506,20 +623,34 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
506
623
|
}
|
|
507
624
|
return prop.fieldNames;
|
|
508
625
|
}
|
|
509
|
-
|
|
510
|
-
|
|
626
|
+
/** @internal */
|
|
627
|
+
createQueryBuilder(entityName, ctx, preferredConnectionType, convertCustomTypes) {
|
|
628
|
+
const connectionType = this.resolveConnectionType({ ctx, connectionType: preferredConnectionType });
|
|
629
|
+
const qb = new query_1.QueryBuilder(entityName, this.metadata, this, ctx, undefined, connectionType);
|
|
511
630
|
if (!convertCustomTypes) {
|
|
512
631
|
qb.unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES);
|
|
513
632
|
}
|
|
514
633
|
return qb;
|
|
515
634
|
}
|
|
635
|
+
resolveConnectionType(args) {
|
|
636
|
+
if (args.ctx) {
|
|
637
|
+
return 'write';
|
|
638
|
+
}
|
|
639
|
+
else if (args.connectionType) {
|
|
640
|
+
return args.connectionType;
|
|
641
|
+
}
|
|
642
|
+
else if (this.config.get('preferReadReplicas') === true) {
|
|
643
|
+
return 'read';
|
|
644
|
+
}
|
|
645
|
+
return 'write';
|
|
646
|
+
}
|
|
516
647
|
extractManyToMany(entityName, data) {
|
|
517
648
|
if (!this.metadata.has(entityName)) {
|
|
518
649
|
return {};
|
|
519
650
|
}
|
|
520
651
|
const ret = {};
|
|
521
652
|
this.metadata.find(entityName).relations.forEach(prop => {
|
|
522
|
-
if (prop.
|
|
653
|
+
if (prop.kind === core_1.ReferenceKind.MANY_TO_MANY && data[prop.name]) {
|
|
523
654
|
ret[prop.name] = data[prop.name].map((item) => core_1.Utils.asArray(item));
|
|
524
655
|
delete data[prop.name];
|
|
525
656
|
}
|
|
@@ -541,7 +672,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
541
672
|
deleteDiff = [];
|
|
542
673
|
}
|
|
543
674
|
if (deleteDiff === true || deleteDiff.length > 0) {
|
|
544
|
-
const qb1 = this.createQueryBuilder(prop.
|
|
675
|
+
const qb1 = this.createQueryBuilder(prop.pivotEntity, options?.ctx, 'write')
|
|
545
676
|
.withSchema(this.getSchemaName(meta, options))
|
|
546
677
|
.unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES);
|
|
547
678
|
const knex = qb1.getKnex();
|
|
@@ -562,11 +693,15 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
562
693
|
});
|
|
563
694
|
/* istanbul ignore else */
|
|
564
695
|
if (this.platform.allowsMultiInsert()) {
|
|
565
|
-
await this.nativeInsertMany(prop.
|
|
696
|
+
await this.nativeInsertMany(prop.pivotEntity, items, {
|
|
697
|
+
...options,
|
|
698
|
+
convertCustomTypes: false,
|
|
699
|
+
processCollections: false,
|
|
700
|
+
});
|
|
566
701
|
}
|
|
567
702
|
else {
|
|
568
703
|
await core_1.Utils.runSerial(items, item => {
|
|
569
|
-
return this.createQueryBuilder(prop.
|
|
704
|
+
return this.createQueryBuilder(prop.pivotEntity, options?.ctx, 'write')
|
|
570
705
|
.unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES)
|
|
571
706
|
.withSchema(this.getSchemaName(meta, options))
|
|
572
707
|
.insert(item)
|
|
@@ -575,7 +710,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
575
710
|
}
|
|
576
711
|
}
|
|
577
712
|
async lockPessimistic(entity, options) {
|
|
578
|
-
const meta = entity.
|
|
713
|
+
const meta = (0, core_1.helper)(entity).__meta;
|
|
579
714
|
const qb = this.createQueryBuilder(entity.constructor.name, options.ctx).unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES).withSchema(options.schema ?? meta.schema);
|
|
580
715
|
const cond = core_1.Utils.getPrimaryKeyCond(entity, meta.primaryKeys);
|
|
581
716
|
qb.select('1').where(cond).setLockMode(options.lockMode, options.lockTableAliases);
|
|
@@ -590,7 +725,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
590
725
|
const path = `${parentPath ? parentPath : entityName}.${relation.field}`;
|
|
591
726
|
const propAlias = qb.getAliasForJoinPath(path);
|
|
592
727
|
if (propOrderBy) {
|
|
593
|
-
|
|
728
|
+
core_1.Utils.keys(propOrderBy).forEach(field => {
|
|
594
729
|
orderBy.push({ [`${propAlias}.${field}`]: propOrderBy[field] });
|
|
595
730
|
});
|
|
596
731
|
}
|
|
@@ -601,6 +736,43 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
601
736
|
});
|
|
602
737
|
return orderBy;
|
|
603
738
|
}
|
|
739
|
+
normalizeFields(fields, prefix = '') {
|
|
740
|
+
const ret = [];
|
|
741
|
+
for (const field of fields) {
|
|
742
|
+
if (typeof field === 'string') {
|
|
743
|
+
ret.push(prefix + field);
|
|
744
|
+
continue;
|
|
745
|
+
}
|
|
746
|
+
if (core_1.Utils.isPlainObject(field)) {
|
|
747
|
+
for (const key of Object.keys(field)) {
|
|
748
|
+
ret.push(...this.normalizeFields(field[key], key + '.'));
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
return ret;
|
|
753
|
+
}
|
|
754
|
+
processField(meta, prop, field, ret, populate, joinedProps, qb) {
|
|
755
|
+
if (!prop || (prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner)) {
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
if (prop.kind === core_1.ReferenceKind.EMBEDDED) {
|
|
759
|
+
if (prop.object) {
|
|
760
|
+
ret.push(prop.fieldNames[0]);
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
const parts = field.split('.');
|
|
764
|
+
const top = parts.shift();
|
|
765
|
+
for (const key of Object.keys(prop.embeddedProps)) {
|
|
766
|
+
if (!top || key === top) {
|
|
767
|
+
this.processField(meta, prop.embeddedProps[key], parts.join('.'), ret, populate, joinedProps, qb);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
if (prop.fieldNames) {
|
|
773
|
+
ret.push(...prop.fieldNames);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
604
776
|
buildFields(meta, populate, joinedProps, qb, fields) {
|
|
605
777
|
const lazyProps = meta.props.filter(prop => prop.lazy && !populate.some(p => p.field === prop.name || p.all));
|
|
606
778
|
const hasLazyFormulas = meta.props.some(p => p.lazy && p.formula);
|
|
@@ -611,11 +783,21 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
611
783
|
ret.push(...this.getFieldsForJoinedLoad(qb, meta, fields, populate));
|
|
612
784
|
}
|
|
613
785
|
else if (fields) {
|
|
614
|
-
for (const field of
|
|
615
|
-
if (
|
|
786
|
+
for (const field of this.normalizeFields(fields)) {
|
|
787
|
+
if (field === '*') {
|
|
788
|
+
ret.push('*');
|
|
616
789
|
continue;
|
|
617
790
|
}
|
|
618
|
-
|
|
791
|
+
const parts = field.split('.');
|
|
792
|
+
const rootPropName = parts.shift(); // first one is the `prop`
|
|
793
|
+
const prop = core_1.QueryHelper.findProperty(rootPropName, {
|
|
794
|
+
metadata: this.metadata,
|
|
795
|
+
platform: this.platform,
|
|
796
|
+
entityName: meta.className,
|
|
797
|
+
where: {},
|
|
798
|
+
aliasMap: qb.getAliasMap(),
|
|
799
|
+
});
|
|
800
|
+
this.processField(meta, prop, parts.join('.'), ret, populate, joinedProps, qb);
|
|
619
801
|
}
|
|
620
802
|
ret.unshift(...meta.primaryKeys.filter(pk => !fields.includes(pk)));
|
|
621
803
|
}
|
|
@@ -638,7 +820,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
638
820
|
.filter(prop => prop.customType?.convertToDatabaseValueSQL || prop.customType?.convertToJSValueSQL)
|
|
639
821
|
.forEach(prop => ret.push(prop.name));
|
|
640
822
|
}
|
|
641
|
-
return ret.length > 0 ? ret : ['*'];
|
|
823
|
+
return ret.length > 0 ? core_1.Utils.unique(ret) : ['*'];
|
|
642
824
|
}
|
|
643
825
|
}
|
|
644
826
|
exports.AbstractSqlDriver = AbstractSqlDriver;
|