@mikro-orm/knex 5.7.15-dev.8 → 5.8.0
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 +4 -3
- package/AbstractSqlConnection.js +4 -1
- package/AbstractSqlDriver.d.ts +4 -5
- package/AbstractSqlDriver.js +70 -32
- package/AbstractSqlPlatform.d.ts +2 -4
- package/SqlEntityManager.d.ts +1 -2
- package/SqlEntityRepository.d.ts +1 -2
- package/package.json +5 -5
- package/query/CriteriaNode.d.ts +1 -1
- package/query/CriteriaNodeFactory.d.ts +1 -1
- package/query/QueryBuilder.d.ts +16 -5
- package/query/QueryBuilder.js +74 -10
- package/query/QueryBuilderHelper.d.ts +4 -5
- package/query/QueryBuilderHelper.js +3 -2
- package/schema/DatabaseSchema.d.ts +1 -1
- package/schema/DatabaseTable.d.ts +2 -1
- package/schema/DatabaseTable.js +5 -0
- package/schema/SchemaGenerator.d.ts +1 -2
- package/schema/SchemaHelper.d.ts +1 -1
- package/typings.d.ts +1 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type
|
|
3
|
-
import { Connection } from '@mikro-orm/core';
|
|
1
|
+
import { type Knex } from 'knex';
|
|
2
|
+
import { Connection, type AnyEntity, type Configuration, type ConnectionOptions, type EntityData, type IsolationLevel, type QueryResult, type Transaction, type TransactionEventBroadcaster } from '@mikro-orm/core';
|
|
4
3
|
import type { AbstractSqlPlatform } from './AbstractSqlPlatform';
|
|
5
4
|
export declare abstract class AbstractSqlConnection extends Connection {
|
|
6
5
|
private static __patched;
|
|
@@ -12,11 +11,13 @@ export declare abstract class AbstractSqlConnection extends Connection {
|
|
|
12
11
|
isConnected(): Promise<boolean>;
|
|
13
12
|
transactional<T>(cb: (trx: Transaction<Knex.Transaction>) => Promise<T>, options?: {
|
|
14
13
|
isolationLevel?: IsolationLevel;
|
|
14
|
+
readOnly?: boolean;
|
|
15
15
|
ctx?: Knex.Transaction;
|
|
16
16
|
eventBroadcaster?: TransactionEventBroadcaster;
|
|
17
17
|
}): Promise<T>;
|
|
18
18
|
begin(options?: {
|
|
19
19
|
isolationLevel?: IsolationLevel;
|
|
20
|
+
readOnly?: boolean;
|
|
20
21
|
ctx?: Knex.Transaction;
|
|
21
22
|
eventBroadcaster?: TransactionEventBroadcaster;
|
|
22
23
|
}): Promise<Knex.Transaction>;
|
package/AbstractSqlConnection.js
CHANGED
|
@@ -46,7 +46,10 @@ class AbstractSqlConnection extends core_1.Connection {
|
|
|
46
46
|
if (!options.ctx) {
|
|
47
47
|
await options.eventBroadcaster?.dispatchEvent(core_1.EventType.beforeTransactionStart);
|
|
48
48
|
}
|
|
49
|
-
const trx = await (options.ctx || this.client).transaction(null, {
|
|
49
|
+
const trx = await (options.ctx || this.client).transaction(null, {
|
|
50
|
+
isolationLevel: options.isolationLevel,
|
|
51
|
+
readOnly: options.readOnly,
|
|
52
|
+
});
|
|
50
53
|
if (!options.ctx) {
|
|
51
54
|
await options.eventBroadcaster?.dispatchEvent(core_1.EventType.afterTransactionStart, trx);
|
|
52
55
|
}
|
package/AbstractSqlDriver.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
-
import type
|
|
3
|
-
import { DatabaseDriver, EntityManagerType } from '@mikro-orm/core';
|
|
2
|
+
import { type AnyEntity, type Collection, type Configuration, type ConnectionType, type Constructor, type CountOptions, DatabaseDriver, type DeleteOptions, type Dictionary, type DriverMethodOptions, type EntityData, type EntityDictionary, type EntityField, EntityManagerType, type EntityMetadata, type EntityName, type EntityProperty, type FilterQuery, type FindOneOptions, type FindOptions, type IDatabaseDriver, type LockOptions, type NativeInsertUpdateManyOptions, type NativeInsertUpdateOptions, type PopulateOptions, type Primary, type QueryOrderMap, type QueryResult, type Transaction, type UpsertManyOptions, type UpsertOptions } from '@mikro-orm/core';
|
|
4
3
|
import type { AbstractSqlConnection } from './AbstractSqlConnection';
|
|
5
4
|
import type { AbstractSqlPlatform } from './AbstractSqlPlatform';
|
|
6
5
|
import { QueryBuilder, QueryType } from './query';
|
|
@@ -27,8 +26,8 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
|
|
|
27
26
|
count<T extends object>(entityName: string, where: any, options?: CountOptions<T>): Promise<number>;
|
|
28
27
|
nativeInsert<T extends object>(entityName: string, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
|
|
29
28
|
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>>;
|
|
29
|
+
nativeUpdate<T extends object>(entityName: string, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T> & UpsertOptions<T>): Promise<QueryResult<T>>;
|
|
30
|
+
nativeUpdateMany<T extends object>(entityName: string, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T> & UpsertManyOptions<T>): Promise<QueryResult<T>>;
|
|
32
31
|
nativeDelete<T extends object>(entityName: string, where: FilterQuery<T> | string | any, options?: DeleteOptions<T>): Promise<QueryResult<T>>;
|
|
33
32
|
syncCollection<T extends object, O extends object>(coll: Collection<T, O>, options?: DriverMethodOptions): Promise<void>;
|
|
34
33
|
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[]>>;
|
|
@@ -41,7 +40,7 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
|
|
|
41
40
|
/**
|
|
42
41
|
* @internal
|
|
43
42
|
*/
|
|
44
|
-
mergeJoinedResult<T extends object>(rawResults: EntityData<T>[], meta: EntityMetadata<T>): EntityData<T>[];
|
|
43
|
+
mergeJoinedResult<T extends object>(rawResults: EntityData<T>[], meta: EntityMetadata<T>, joinedProps: PopulateOptions<T>[]): EntityData<T>[];
|
|
45
44
|
protected getFieldsForJoinedLoad<T extends object>(qb: QueryBuilder<T>, meta: EntityMetadata<T>, explicitFields?: Field<T>[], populate?: PopulateOptions<T>[], parentTableAlias?: string, parentJoinPath?: string): Field<T>[];
|
|
46
45
|
/**
|
|
47
46
|
* @internal
|
package/AbstractSqlDriver.js
CHANGED
|
@@ -38,6 +38,9 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
38
38
|
.orderBy([...core_1.Utils.asArray(options.orderBy), ...joinedPropsOrderBy])
|
|
39
39
|
.groupBy(options.groupBy)
|
|
40
40
|
.having(options.having)
|
|
41
|
+
.indexHint(options.indexHint)
|
|
42
|
+
.comment(options.comments)
|
|
43
|
+
.hintComment(options.hintComments)
|
|
41
44
|
.withSchema(this.getSchemaName(meta, options));
|
|
42
45
|
if (options.limit !== undefined) {
|
|
43
46
|
qb.limit(options.limit, options.offset);
|
|
@@ -48,7 +51,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
48
51
|
core_1.Utils.asArray(options.flags).forEach(flag => qb.setFlag(flag));
|
|
49
52
|
const result = await this.rethrow(qb.execute('all'));
|
|
50
53
|
if (joinedProps.length > 0) {
|
|
51
|
-
return this.mergeJoinedResult(result, meta);
|
|
54
|
+
return this.mergeJoinedResult(result, meta, joinedProps);
|
|
52
55
|
}
|
|
53
56
|
return result;
|
|
54
57
|
}
|
|
@@ -105,7 +108,10 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
105
108
|
}
|
|
106
109
|
async wrapVirtualExpressionInSubquery(meta, expression, where, options, type = query_1.QueryType.SELECT) {
|
|
107
110
|
const qb = this.createQueryBuilder(meta.className, options?.ctx, options.connectionType, options.convertCustomTypes)
|
|
108
|
-
.limit(options?.limit, options?.offset)
|
|
111
|
+
.limit(options?.limit, options?.offset)
|
|
112
|
+
.indexHint(options.indexHint)
|
|
113
|
+
.comment(options.comments)
|
|
114
|
+
.hintComment(options.hintComments);
|
|
109
115
|
if (options.orderBy) {
|
|
110
116
|
qb.orderBy(options.orderBy);
|
|
111
117
|
}
|
|
@@ -207,6 +213,9 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
207
213
|
return this.countVirtual(entityName, where, options);
|
|
208
214
|
}
|
|
209
215
|
const qb = this.createQueryBuilder(entityName, options.ctx, options.connectionType, false)
|
|
216
|
+
.indexHint(options.indexHint)
|
|
217
|
+
.comment(options.comments)
|
|
218
|
+
.hintComment(options.hintComments)
|
|
210
219
|
.groupBy(options.groupBy)
|
|
211
220
|
.having(options.having)
|
|
212
221
|
.populate(options.populate ?? [])
|
|
@@ -332,12 +341,18 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
332
341
|
.withSchema(this.getSchemaName(meta, options));
|
|
333
342
|
if (options.upsert) {
|
|
334
343
|
/* istanbul ignore next */
|
|
335
|
-
const uniqueFields = core_1.Utils.isPlainObject(where) ? Object.keys(where) : meta.primaryKeys;
|
|
336
|
-
|
|
344
|
+
const uniqueFields = options.onConflictFields ?? (core_1.Utils.isPlainObject(where) ? Object.keys(where) : meta.primaryKeys);
|
|
345
|
+
const returning = (0, core_1.getOnConflictReturningFields)(meta, data, uniqueFields, options);
|
|
337
346
|
qb.insert(data)
|
|
338
|
-
.onConflict(uniqueFields
|
|
339
|
-
.
|
|
340
|
-
|
|
347
|
+
.onConflict(uniqueFields)
|
|
348
|
+
.returning(returning);
|
|
349
|
+
if (!options.onConflictAction || options.onConflictAction === 'merge') {
|
|
350
|
+
const fields = (0, core_1.getOnConflictFields)(data, uniqueFields, options);
|
|
351
|
+
qb.merge(fields);
|
|
352
|
+
}
|
|
353
|
+
if (options.onConflictAction === 'ignore') {
|
|
354
|
+
qb.ignore();
|
|
355
|
+
}
|
|
341
356
|
}
|
|
342
357
|
else {
|
|
343
358
|
qb.update(data).where(where);
|
|
@@ -354,12 +369,19 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
354
369
|
options.convertCustomTypes ?? (options.convertCustomTypes = true);
|
|
355
370
|
const meta = this.metadata.get(entityName);
|
|
356
371
|
if (options.upsert) {
|
|
357
|
-
const uniqueFields = core_1.Utils.isPlainObject(where[0]) ? Object.keys(where[0]) : meta.primaryKeys;
|
|
372
|
+
const uniqueFields = options.onConflictFields ?? (core_1.Utils.isPlainObject(where[0]) ? Object.keys(where[0]) : meta.primaryKeys);
|
|
358
373
|
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', options.convertCustomTypes).withSchema(this.getSchemaName(meta, options));
|
|
374
|
+
const returning = (0, core_1.getOnConflictReturningFields)(meta, data[0], uniqueFields, options);
|
|
359
375
|
qb.insert(data)
|
|
360
|
-
.onConflict(uniqueFields
|
|
361
|
-
.
|
|
362
|
-
|
|
376
|
+
.onConflict(uniqueFields)
|
|
377
|
+
.returning(returning);
|
|
378
|
+
if (!options.onConflictAction || options.onConflictAction === 'merge') {
|
|
379
|
+
const fields = (0, core_1.getOnConflictFields)(data[0], uniqueFields, options);
|
|
380
|
+
qb.merge(fields);
|
|
381
|
+
}
|
|
382
|
+
if (options.onConflictAction === 'ignore') {
|
|
383
|
+
qb.ignore();
|
|
384
|
+
}
|
|
363
385
|
return qb.execute('run', false);
|
|
364
386
|
}
|
|
365
387
|
const collections = options.processCollections ? data.map(d => this.extractManyToMany(entityName, d)) : [];
|
|
@@ -461,11 +483,23 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
461
483
|
if (coll.property.reference === core_1.ReferenceType.ONE_TO_MANY) {
|
|
462
484
|
const cols = coll.property.referencedColumnNames;
|
|
463
485
|
const qb = this.createQueryBuilder(coll.property.type, ctx, 'write')
|
|
464
|
-
.withSchema(this.getSchemaName(meta, options))
|
|
465
|
-
|
|
486
|
+
.withSchema(this.getSchemaName(meta, options));
|
|
487
|
+
if (coll.getSnapshot() === undefined) {
|
|
488
|
+
if (coll.property.orphanRemoval) {
|
|
489
|
+
const kqb = qb.delete({ [coll.property.mappedBy]: pks })
|
|
490
|
+
.getKnexQuery()
|
|
491
|
+
.whereNotIn(cols, insertDiff);
|
|
492
|
+
return this.rethrow(this.execute(kqb));
|
|
493
|
+
}
|
|
494
|
+
const kqb = qb.update({ [coll.property.mappedBy]: null })
|
|
495
|
+
.getKnexQuery()
|
|
496
|
+
.whereNotIn(cols, insertDiff);
|
|
497
|
+
return this.rethrow(this.execute(kqb));
|
|
498
|
+
}
|
|
499
|
+
const kqb = qb.update({ [coll.property.mappedBy]: pks })
|
|
466
500
|
.getKnexQuery()
|
|
467
501
|
.whereIn(cols, insertDiff);
|
|
468
|
-
return this.rethrow(this.execute(
|
|
502
|
+
return this.rethrow(this.execute(kqb));
|
|
469
503
|
}
|
|
470
504
|
/* istanbul ignore next */
|
|
471
505
|
const ownerSchema = wrapped.getSchema() === '*' ? this.config.get('schema') : wrapped.getSchema();
|
|
@@ -489,17 +523,22 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
489
523
|
else {
|
|
490
524
|
where = { ...where, ...cond };
|
|
491
525
|
}
|
|
526
|
+
/* istanbul ignore if */
|
|
527
|
+
options = { ...options };
|
|
492
528
|
orderBy = this.getPivotOrderBy(prop, orderBy);
|
|
493
|
-
const qb = this.createQueryBuilder(prop.type, ctx, options
|
|
529
|
+
const qb = this.createQueryBuilder(prop.type, ctx, options.connectionType)
|
|
530
|
+
.indexHint(options.indexHint)
|
|
531
|
+
.comment(options.comments)
|
|
532
|
+
.hintComment(options.hintComments)
|
|
494
533
|
.unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES)
|
|
495
534
|
.withSchema(this.getSchemaName(prop.targetMeta, options));
|
|
496
535
|
const populate = this.autoJoinOneToOneOwner(prop.targetMeta, [{ field: prop.pivotEntity }]);
|
|
497
|
-
const fields = this.buildFields(prop.targetMeta, (options
|
|
498
|
-
qb.select(fields).populate(populate).where(where).orderBy(orderBy).setLockMode(options
|
|
499
|
-
if (owners.length === 1 && (options
|
|
536
|
+
const fields = this.buildFields(prop.targetMeta, (options.populate ?? []), [], qb, options.fields);
|
|
537
|
+
qb.select(fields).populate(populate).where(where).orderBy(orderBy).setLockMode(options.lockMode, options.lockTableAliases);
|
|
538
|
+
if (owners.length === 1 && (options.offset != null || options.limit != null)) {
|
|
500
539
|
qb.limit(options.limit, options.offset);
|
|
501
540
|
}
|
|
502
|
-
if (prop.targetMeta.schema !== '*' && pivotMeta.schema === '*' && options
|
|
541
|
+
if (prop.targetMeta.schema !== '*' && pivotMeta.schema === '*' && options.schema) {
|
|
503
542
|
// eslint-disable-next-line dot-notation
|
|
504
543
|
qb['finalize']();
|
|
505
544
|
// eslint-disable-next-line dot-notation
|
|
@@ -554,17 +593,21 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
554
593
|
/**
|
|
555
594
|
* @internal
|
|
556
595
|
*/
|
|
557
|
-
mergeJoinedResult(rawResults, meta) {
|
|
596
|
+
mergeJoinedResult(rawResults, meta, joinedProps) {
|
|
558
597
|
// group by the root entity primary key first
|
|
559
598
|
const map = {};
|
|
560
599
|
const res = [];
|
|
561
600
|
rawResults.forEach(item => {
|
|
562
601
|
const pk = core_1.Utils.getCompositeKeyHash(item, meta);
|
|
563
602
|
if (map[pk]) {
|
|
564
|
-
|
|
603
|
+
joinedProps.forEach(hint => {
|
|
604
|
+
if (Array.isArray(map[pk][hint.field]) && Array.isArray(item[hint.field])) {
|
|
605
|
+
map[pk][hint.field].push(...item[hint.field]);
|
|
606
|
+
}
|
|
607
|
+
});
|
|
565
608
|
}
|
|
566
609
|
else {
|
|
567
|
-
map[pk] =
|
|
610
|
+
map[pk] = item;
|
|
568
611
|
res.push(item);
|
|
569
612
|
}
|
|
570
613
|
});
|
|
@@ -672,9 +715,10 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
672
715
|
if (!deleteDiff) {
|
|
673
716
|
deleteDiff = [];
|
|
674
717
|
}
|
|
718
|
+
const pivotMeta = this.metadata.find(prop.pivotEntity);
|
|
675
719
|
if (deleteDiff === true || deleteDiff.length > 0) {
|
|
676
720
|
const qb1 = this.createQueryBuilder(prop.pivotEntity, options?.ctx, 'write')
|
|
677
|
-
.withSchema(this.getSchemaName(
|
|
721
|
+
.withSchema(this.getSchemaName(pivotMeta, options))
|
|
678
722
|
.unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES);
|
|
679
723
|
const knex = qb1.getKnex();
|
|
680
724
|
if (Array.isArray(deleteDiff)) {
|
|
@@ -700,7 +744,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
700
744
|
await core_1.Utils.runSerial(items, item => {
|
|
701
745
|
return this.createQueryBuilder(prop.pivotEntity, options?.ctx, 'write')
|
|
702
746
|
.unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES)
|
|
703
|
-
.withSchema(this.getSchemaName(
|
|
747
|
+
.withSchema(this.getSchemaName(pivotMeta, options))
|
|
704
748
|
.insert(item)
|
|
705
749
|
.execute('run', false);
|
|
706
750
|
});
|
|
@@ -754,7 +798,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
754
798
|
}
|
|
755
799
|
if (prop.reference === core_1.ReferenceType.EMBEDDED) {
|
|
756
800
|
if (prop.object) {
|
|
757
|
-
ret.push(prop.
|
|
801
|
+
ret.push(prop.name);
|
|
758
802
|
return;
|
|
759
803
|
}
|
|
760
804
|
const parts = field.split('.');
|
|
@@ -766,13 +810,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
766
810
|
}
|
|
767
811
|
return;
|
|
768
812
|
}
|
|
769
|
-
|
|
770
|
-
ret.push(prop.name);
|
|
771
|
-
return;
|
|
772
|
-
}
|
|
773
|
-
if (prop.fieldNames) {
|
|
774
|
-
ret.push(...prop.fieldNames);
|
|
775
|
-
}
|
|
813
|
+
ret.push(prop.name);
|
|
776
814
|
}
|
|
777
815
|
buildFields(meta, populate, joinedProps, qb, fields) {
|
|
778
816
|
const lazyProps = meta.props.filter(prop => prop.lazy && !populate.some(p => p.field === prop.name || p.all));
|
package/AbstractSqlPlatform.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import {
|
|
3
|
-
import type { SchemaHelper } from './schema';
|
|
4
|
-
import { SchemaGenerator } from './schema';
|
|
1
|
+
import { Platform, type Constructor, type EntityManager, type EntityRepository, type IDatabaseDriver, type MikroORM } from '@mikro-orm/core';
|
|
2
|
+
import { SchemaGenerator, type SchemaHelper } from './schema';
|
|
5
3
|
export declare abstract class AbstractSqlPlatform extends Platform {
|
|
6
4
|
protected readonly schemaHelper?: SchemaHelper;
|
|
7
5
|
usesPivotTable(): boolean;
|
package/SqlEntityManager.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
-
import type
|
|
3
|
-
import { EntityManager } from '@mikro-orm/core';
|
|
2
|
+
import { EntityManager, type AnyEntity, type ConnectionType, type EntityData, type EntityName, type EntityRepository, type GetRepository, type QueryResult } from '@mikro-orm/core';
|
|
4
3
|
import type { AbstractSqlDriver } from './AbstractSqlDriver';
|
|
5
4
|
import { QueryBuilder } from './query';
|
|
6
5
|
import type { SqlEntityRepository } from './SqlEntityRepository';
|
package/SqlEntityRepository.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
-
import type
|
|
3
|
-
import { EntityRepository } from '@mikro-orm/core';
|
|
2
|
+
import { EntityRepository, type ConnectionType, type EntityName } from '@mikro-orm/core';
|
|
4
3
|
import type { SqlEntityManager } from './SqlEntityManager';
|
|
5
4
|
import type { QueryBuilder } from './query';
|
|
6
5
|
export declare class SqlEntityRepository<T extends object> extends EntityRepository<T> {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/knex",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.8.0",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
@@ -63,12 +63,12 @@
|
|
|
63
63
|
"sqlstring": "2.3.3"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@mikro-orm/core": "^5.
|
|
66
|
+
"@mikro-orm/core": "^5.8.0"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@mikro-orm/core": "
|
|
70
|
-
"@mikro-orm/entity-generator": "
|
|
71
|
-
"@mikro-orm/migrations": "
|
|
69
|
+
"@mikro-orm/core": "^5.0.0",
|
|
70
|
+
"@mikro-orm/entity-generator": "^5.0.0",
|
|
71
|
+
"@mikro-orm/migrations": "^5.0.0",
|
|
72
72
|
"better-sqlite3": "*",
|
|
73
73
|
"mssql": "*",
|
|
74
74
|
"mysql": "*",
|
package/query/CriteriaNode.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { inspect } from 'util';
|
|
3
|
-
import type
|
|
3
|
+
import { type EntityProperty, type MetadataStorage } from '@mikro-orm/core';
|
|
4
4
|
import type { ICriteriaNode, IQueryBuilder } from '../typings';
|
|
5
5
|
/**
|
|
6
6
|
* Helper for working with deeply nested where/orderBy/having criteria. Uses composite pattern to build tree from the payload.
|
package/query/QueryBuilder.d.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { inspect } from 'util';
|
|
3
3
|
import type { Knex } from 'knex';
|
|
4
|
-
import type
|
|
5
|
-
import { LockMode, PopulateHint, QueryFlag } from '@mikro-orm/core';
|
|
4
|
+
import { LockMode, PopulateHint, QueryFlag, type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityName, type EntityProperty, type FlushMode, type GroupOperator, type MetadataStorage, type ObjectQuery, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, type QueryResult, type RequiredEntityData } from '@mikro-orm/core';
|
|
6
5
|
import { QueryType } from './enums';
|
|
7
6
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver';
|
|
8
|
-
import type
|
|
9
|
-
import { QueryBuilderHelper } from './QueryBuilderHelper';
|
|
7
|
+
import { QueryBuilderHelper, type Alias } from './QueryBuilderHelper';
|
|
10
8
|
import type { SqlEntityManager } from '../SqlEntityManager';
|
|
11
9
|
import type { Field } from '../typings';
|
|
12
10
|
/**
|
|
@@ -34,7 +32,7 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
34
32
|
private readonly context?;
|
|
35
33
|
private connectionType?;
|
|
36
34
|
private readonly em?;
|
|
37
|
-
get mainAlias(): Alias
|
|
35
|
+
get mainAlias(): Alias<T>;
|
|
38
36
|
get alias(): string;
|
|
39
37
|
get helper(): QueryBuilderHelper;
|
|
40
38
|
/** @internal */
|
|
@@ -66,6 +64,8 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
66
64
|
private _joinedProps;
|
|
67
65
|
private _cache?;
|
|
68
66
|
private _indexHint?;
|
|
67
|
+
private _comments;
|
|
68
|
+
private _hintComments;
|
|
69
69
|
private flushMode?;
|
|
70
70
|
private lockMode?;
|
|
71
71
|
private lockTables?;
|
|
@@ -132,6 +132,16 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
132
132
|
* Adds index hint to the FROM clause.
|
|
133
133
|
*/
|
|
134
134
|
indexHint(sql: string): this;
|
|
135
|
+
/**
|
|
136
|
+
* Prepend comment to the sql query using the syntax `/* ... *‍/`. Some characters are forbidden such as `/*, *‍/` and `?`.
|
|
137
|
+
*/
|
|
138
|
+
comment(comment: string | string[]): this;
|
|
139
|
+
/**
|
|
140
|
+
* Add hints to the query using comment-like syntax `/*+ ... *‍/`. MySQL and Oracle use this syntax for optimizer hints.
|
|
141
|
+
* Also various DB proxies and routers use this syntax to pass hints to alter their behavior. In other dialects the hints
|
|
142
|
+
* are ignored as simple comments.
|
|
143
|
+
*/
|
|
144
|
+
hintComment(comment: string | string[]): this;
|
|
135
145
|
/**
|
|
136
146
|
* Specifies FROM which entity's table select/update/delete will be executed, removing all previously set FROM-s.
|
|
137
147
|
* Allows setting a main string alias of the selection data.
|
|
@@ -204,6 +214,7 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
204
214
|
private init;
|
|
205
215
|
private getQueryBase;
|
|
206
216
|
private finalize;
|
|
217
|
+
private processPopulateWhere;
|
|
207
218
|
private hasToManyJoins;
|
|
208
219
|
private wrapPaginateSubQuery;
|
|
209
220
|
private wrapModifySubQuery;
|
package/query/QueryBuilder.js
CHANGED
|
@@ -60,6 +60,8 @@ class QueryBuilder {
|
|
|
60
60
|
this._groupBy = [];
|
|
61
61
|
this._having = {};
|
|
62
62
|
this._joinedProps = new Map();
|
|
63
|
+
this._comments = [];
|
|
64
|
+
this._hintComments = [];
|
|
63
65
|
this.subQueries = {};
|
|
64
66
|
this._aliases = {};
|
|
65
67
|
this.platform = this.driver.getPlatform();
|
|
@@ -244,9 +246,16 @@ class QueryBuilder {
|
|
|
244
246
|
return this;
|
|
245
247
|
}
|
|
246
248
|
onConflict(fields = []) {
|
|
249
|
+
const meta = this.mainAlias.metadata;
|
|
247
250
|
this.ensureNotFinalized();
|
|
248
|
-
this._onConflict
|
|
249
|
-
this._onConflict.push({
|
|
251
|
+
this._onConflict ?? (this._onConflict = []);
|
|
252
|
+
this._onConflict.push({
|
|
253
|
+
fields: core_1.Utils.asArray(fields).flatMap(f => {
|
|
254
|
+
const key = f.toString();
|
|
255
|
+
/* istanbul ignore next */
|
|
256
|
+
return meta.properties[key]?.fieldNames ?? [key];
|
|
257
|
+
}),
|
|
258
|
+
});
|
|
250
259
|
return this;
|
|
251
260
|
}
|
|
252
261
|
ignore() {
|
|
@@ -345,6 +354,24 @@ class QueryBuilder {
|
|
|
345
354
|
this._indexHint = sql;
|
|
346
355
|
return this;
|
|
347
356
|
}
|
|
357
|
+
/**
|
|
358
|
+
* Prepend comment to the sql query using the syntax `/* ... *‍/`. Some characters are forbidden such as `/*, *‍/` and `?`.
|
|
359
|
+
*/
|
|
360
|
+
comment(comment) {
|
|
361
|
+
this.ensureNotFinalized();
|
|
362
|
+
this._comments.push(...core_1.Utils.asArray(comment));
|
|
363
|
+
return this;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Add hints to the query using comment-like syntax `/*+ ... *‍/`. MySQL and Oracle use this syntax for optimizer hints.
|
|
367
|
+
* Also various DB proxies and routers use this syntax to pass hints to alter their behavior. In other dialects the hints
|
|
368
|
+
* are ignored as simple comments.
|
|
369
|
+
*/
|
|
370
|
+
hintComment(comment) {
|
|
371
|
+
this.ensureNotFinalized();
|
|
372
|
+
this._hintComments.push(...core_1.Utils.asArray(comment));
|
|
373
|
+
return this;
|
|
374
|
+
}
|
|
348
375
|
from(target, aliasName) {
|
|
349
376
|
this.ensureNotFinalized();
|
|
350
377
|
if (target instanceof QueryBuilder) {
|
|
@@ -374,6 +401,8 @@ class QueryBuilder {
|
|
|
374
401
|
}, this._orderBy);
|
|
375
402
|
core_1.Utils.runIfNotEmpty(() => qb.limit(this._limit), this._limit != null);
|
|
376
403
|
core_1.Utils.runIfNotEmpty(() => qb.offset(this._offset), this._offset);
|
|
404
|
+
core_1.Utils.runIfNotEmpty(() => this._comments.forEach(comment => qb.comment(comment)), this._comments);
|
|
405
|
+
core_1.Utils.runIfNotEmpty(() => this._hintComments.forEach(comment => qb.hintComment(comment)), this._hintComments);
|
|
377
406
|
core_1.Utils.runIfNotEmpty(() => this.helper.appendOnConflictClause(this.type ?? enums_1.QueryType.SELECT, this._onConflict, qb), this._onConflict);
|
|
378
407
|
if (this.type === enums_1.QueryType.TRUNCATE && this.platform.usesCascadeStatement()) {
|
|
379
408
|
return this.knex.raw(qb.toSQL().toNative().sql + ' cascade');
|
|
@@ -471,7 +500,7 @@ class QueryBuilder {
|
|
|
471
500
|
await this.em.tryFlush(this.mainAlias.entityName, { flushMode: this.flushMode });
|
|
472
501
|
let res = await this.execute('all', true);
|
|
473
502
|
if (this._joinedProps.size > 0) {
|
|
474
|
-
res = this.driver.mergeJoinedResult(res, this.mainAlias.metadata);
|
|
503
|
+
res = this.driver.mergeJoinedResult(res, this.mainAlias.metadata, [...this._joinedProps.values()]);
|
|
475
504
|
}
|
|
476
505
|
const entities = [];
|
|
477
506
|
function propagatePopulateHint(entity, hint) {
|
|
@@ -570,6 +599,7 @@ class QueryBuilder {
|
|
|
570
599
|
const properties = [
|
|
571
600
|
'flags', '_populate', '_populateWhere', '_populateMap', '_joins', '_joinedProps', '_cond', '_data', '_orderBy',
|
|
572
601
|
'_schema', '_indexHint', '_cache', 'subQueries', 'lockMode', 'lockTables', '_groupBy', '_having', '_returning',
|
|
602
|
+
'_comments', '_hintComments',
|
|
573
603
|
];
|
|
574
604
|
properties.forEach(prop => qb[prop] = core_1.Utils.copy(this[prop]));
|
|
575
605
|
/* istanbul ignore else */
|
|
@@ -686,6 +716,10 @@ class QueryBuilder {
|
|
|
686
716
|
}
|
|
687
717
|
return;
|
|
688
718
|
}
|
|
719
|
+
if (prop && prop.fieldNames.length > 1) {
|
|
720
|
+
ret.push(...prop.fieldNames.map(f => this.helper.mapper(f, this.type)));
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
689
723
|
ret.push(this.helper.mapper(field, this.type));
|
|
690
724
|
});
|
|
691
725
|
const meta = this.mainAlias.metadata;
|
|
@@ -816,6 +850,7 @@ class QueryBuilder {
|
|
|
816
850
|
.filter(field => !this._fields.includes(field))
|
|
817
851
|
.forEach(field => this.addSelect(field));
|
|
818
852
|
}
|
|
853
|
+
this.processPopulateWhere();
|
|
819
854
|
core_1.QueryHelper.processObjectParams(this._data);
|
|
820
855
|
core_1.QueryHelper.processObjectParams(this._cond);
|
|
821
856
|
core_1.QueryHelper.processObjectParams(this._having);
|
|
@@ -831,6 +866,40 @@ class QueryBuilder {
|
|
|
831
866
|
}
|
|
832
867
|
this.finalized = true;
|
|
833
868
|
}
|
|
869
|
+
processPopulateWhere() {
|
|
870
|
+
if (this._populateWhere == null || this._populateWhere === core_1.PopulateHint.ALL) {
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
const joins = Object.values(this._joins);
|
|
874
|
+
joins.forEach(join => {
|
|
875
|
+
join.cond_ = join.cond;
|
|
876
|
+
join.cond = {};
|
|
877
|
+
});
|
|
878
|
+
const replaceOnConditions = (cond) => {
|
|
879
|
+
Object.keys(cond).forEach(k => {
|
|
880
|
+
if (core_1.Utils.isOperator(k)) {
|
|
881
|
+
if (Array.isArray(cond[k])) {
|
|
882
|
+
return cond[k].forEach((c) => replaceOnConditions(c));
|
|
883
|
+
}
|
|
884
|
+
return replaceOnConditions(cond[k]);
|
|
885
|
+
}
|
|
886
|
+
const [a] = this.helper.splitField(k);
|
|
887
|
+
const join = joins.find(j => j.alias === a);
|
|
888
|
+
if (join) {
|
|
889
|
+
join.cond = { ...join.cond, [k]: cond[k] };
|
|
890
|
+
}
|
|
891
|
+
});
|
|
892
|
+
};
|
|
893
|
+
if (this._populateWhere === core_1.PopulateHint.INFER) {
|
|
894
|
+
replaceOnConditions(this._cond);
|
|
895
|
+
}
|
|
896
|
+
else if (typeof this._populateWhere === 'object') {
|
|
897
|
+
const cond = CriteriaNodeFactory_1.CriteriaNodeFactory
|
|
898
|
+
.createNode(this.metadata, this.mainAlias.entityName, this._populateWhere)
|
|
899
|
+
.process(this);
|
|
900
|
+
replaceOnConditions(cond);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
834
903
|
hasToManyJoins() {
|
|
835
904
|
return Object.values(this._joins).some(join => {
|
|
836
905
|
return [core_1.ReferenceType.ONE_TO_MANY, core_1.ReferenceType.MANY_TO_MANY].includes(join.prop.reference);
|
|
@@ -839,6 +908,8 @@ class QueryBuilder {
|
|
|
839
908
|
wrapPaginateSubQuery(meta) {
|
|
840
909
|
const pks = this.prepareFields(meta.primaryKeys, 'sub-query');
|
|
841
910
|
const subQuery = this.clone().select(pks).groupBy(pks).limit(this._limit);
|
|
911
|
+
// revert the on conditions added via populateWhere, we want to apply those only once
|
|
912
|
+
Object.values(subQuery._joins).forEach(join => join.cond = join.cond_ ?? {});
|
|
842
913
|
if (this._offset) {
|
|
843
914
|
subQuery.offset(this._offset);
|
|
844
915
|
}
|
|
@@ -881,14 +952,7 @@ class QueryBuilder {
|
|
|
881
952
|
subSubQuery.__raw = true; // tag it as there is now way to check via `instanceof`
|
|
882
953
|
this._limit = undefined;
|
|
883
954
|
this._offset = undefined;
|
|
884
|
-
const cond = this._cond;
|
|
885
955
|
this.select(this._fields).where({ [core_1.Utils.getPrimaryKeyHash(meta.primaryKeys)]: { $in: subSubQuery } });
|
|
886
|
-
if (this._populateWhere === core_1.PopulateHint.INFER) {
|
|
887
|
-
this.andWhere(cond);
|
|
888
|
-
}
|
|
889
|
-
else if (typeof this._populateWhere === 'object') {
|
|
890
|
-
this.andWhere(this._populateWhere);
|
|
891
|
-
}
|
|
892
956
|
}
|
|
893
957
|
wrapModifySubQuery(meta) {
|
|
894
958
|
const subQuery = this.clone();
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
-
import type
|
|
3
|
-
import { LockMode } from '@mikro-orm/core';
|
|
2
|
+
import { LockMode, type Dictionary, type EntityData, type EntityMetadata, type EntityProperty, type FlatQueryOrderMap, type QBFilterQuery } from '@mikro-orm/core';
|
|
4
3
|
import { QueryType } from './enums';
|
|
5
4
|
import type { Field, JoinOptions } from '../typings';
|
|
6
5
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver';
|
|
@@ -16,7 +15,7 @@ export declare class QueryBuilderHelper {
|
|
|
16
15
|
private readonly driver;
|
|
17
16
|
private readonly platform;
|
|
18
17
|
private readonly metadata;
|
|
19
|
-
constructor(entityName: string, alias: string, aliasMap: Dictionary<Alias
|
|
18
|
+
constructor(entityName: string, alias: string, aliasMap: Dictionary<Alias<any>>, subQueries: Dictionary<string>, knex: Knex, driver: AbstractSqlDriver);
|
|
20
19
|
mapper(field: string | Knex.Raw, type?: QueryType): string;
|
|
21
20
|
mapper(field: string | Knex.Raw, type?: QueryType, value?: any, alias?: string | null): string;
|
|
22
21
|
processData(data: Dictionary, convertCustomTypes: boolean, multi?: boolean): any;
|
|
@@ -61,9 +60,9 @@ export declare class QueryBuilderHelper {
|
|
|
61
60
|
isTableNameAliasRequired(type?: QueryType): boolean;
|
|
62
61
|
private mapData;
|
|
63
62
|
}
|
|
64
|
-
export interface Alias {
|
|
63
|
+
export interface Alias<T> {
|
|
65
64
|
aliasName: string;
|
|
66
65
|
entityName: string;
|
|
67
|
-
metadata?: EntityMetadata
|
|
66
|
+
metadata?: EntityMetadata<T>;
|
|
68
67
|
subQuery?: Knex.QueryBuilder;
|
|
69
68
|
}
|
|
@@ -128,12 +128,13 @@ class QueryBuilderHelper {
|
|
|
128
128
|
const pivotMeta = this.metadata.find(prop.pivotEntity);
|
|
129
129
|
const ret = {
|
|
130
130
|
[`${ownerAlias}.${prop.name}#${pivotAlias}`]: {
|
|
131
|
-
prop, type,
|
|
131
|
+
prop, type, ownerAlias,
|
|
132
132
|
alias: pivotAlias,
|
|
133
133
|
inverseAlias: alias,
|
|
134
134
|
joinColumns: prop.joinColumns,
|
|
135
135
|
inverseJoinColumns: prop.inverseJoinColumns,
|
|
136
136
|
primaryKeys: prop.referencedColumnNames,
|
|
137
|
+
cond: {},
|
|
137
138
|
table: pivotMeta.tableName,
|
|
138
139
|
schema: this.driver.getSchemaName(pivotMeta),
|
|
139
140
|
path: path.endsWith('[pivot]') ? path : `${path}[pivot]`,
|
|
@@ -143,7 +144,7 @@ class QueryBuilderHelper {
|
|
|
143
144
|
return ret;
|
|
144
145
|
}
|
|
145
146
|
const prop2 = prop.owner ? pivotMeta.relations[1] : pivotMeta.relations[0];
|
|
146
|
-
ret[`${pivotAlias}.${prop2.name}#${alias}`] = this.joinManyToOneReference(prop2, pivotAlias, alias, type);
|
|
147
|
+
ret[`${pivotAlias}.${prop2.name}#${alias}`] = this.joinManyToOneReference(prop2, pivotAlias, alias, type, cond);
|
|
147
148
|
ret[`${pivotAlias}.${prop2.name}#${alias}`].path = path;
|
|
148
149
|
return ret;
|
|
149
150
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Configuration, type Dictionary, type EntityMetadata } from '@mikro-orm/core';
|
|
2
2
|
import { DatabaseTable } from './DatabaseTable';
|
|
3
3
|
import type { AbstractSqlConnection } from '../AbstractSqlConnection';
|
|
4
4
|
import type { AbstractSqlPlatform } from '../AbstractSqlPlatform';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Dictionary, type EntityMetadata, type EntityProperty, type NamingStrategy } from '@mikro-orm/core';
|
|
2
2
|
import type { SchemaHelper } from './SchemaHelper';
|
|
3
3
|
import type { Check, Column, ForeignKey, Index } from '../typings';
|
|
4
4
|
import type { AbstractSqlPlatform } from '../AbstractSqlPlatform';
|
|
@@ -17,6 +17,7 @@ export declare class DatabaseTable {
|
|
|
17
17
|
constructor(platform: AbstractSqlPlatform, name: string, schema?: string | undefined);
|
|
18
18
|
getColumns(): Column[];
|
|
19
19
|
getColumn(name: string): Column | undefined;
|
|
20
|
+
removeColumn(name: string): void;
|
|
20
21
|
getIndexes(): Index[];
|
|
21
22
|
getChecks(): Check[];
|
|
22
23
|
init(cols: Column[], indexes: Index[] | undefined, checks: Check<unknown>[] | undefined, pks: string[], fks?: Dictionary<ForeignKey>, enums?: Dictionary<string[]>): void;
|
package/schema/DatabaseTable.js
CHANGED
|
@@ -24,6 +24,9 @@ class DatabaseTable {
|
|
|
24
24
|
getColumn(name) {
|
|
25
25
|
return this.columns[name];
|
|
26
26
|
}
|
|
27
|
+
removeColumn(name) {
|
|
28
|
+
delete this.columns[name];
|
|
29
|
+
}
|
|
27
30
|
getIndexes() {
|
|
28
31
|
return this.indexes;
|
|
29
32
|
}
|
|
@@ -227,6 +230,8 @@ class DatabaseTable {
|
|
|
227
230
|
primary: column.primary,
|
|
228
231
|
fieldName: column.name,
|
|
229
232
|
length: column.length,
|
|
233
|
+
precision: column.precision,
|
|
234
|
+
scale: column.scale,
|
|
230
235
|
index: index ? index.keyName : undefined,
|
|
231
236
|
unique: unique ? unique.keyName : undefined,
|
|
232
237
|
enum: !!column.enumItems?.length,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { AbstractSchemaGenerator } from '@mikro-orm/core';
|
|
1
|
+
import { AbstractSchemaGenerator, type MikroORM } from '@mikro-orm/core';
|
|
3
2
|
import type { SchemaDifference } from '../typings';
|
|
4
3
|
import { DatabaseSchema } from './DatabaseSchema';
|
|
5
4
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver';
|
package/schema/SchemaHelper.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
-
import type
|
|
2
|
+
import { type Connection, type Dictionary } from '@mikro-orm/core';
|
|
3
3
|
import type { AbstractSqlConnection } from '../AbstractSqlConnection';
|
|
4
4
|
import type { AbstractSqlPlatform } from '../AbstractSqlPlatform';
|
|
5
5
|
import type { Check, Column, Index, Table, TableDifference } from '../typings';
|