@mikro-orm/core 7.1.13-dev.8 → 7.1.13
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/EntityManager.js +15 -1
- package/drivers/IDatabaseDriver.d.ts +1 -0
- package/metadata/MetadataDiscovery.js +3 -0
- package/package.json +1 -1
- package/typings.js +4 -1
- package/utils/Utils.js +1 -1
- package/utils/upsert-utils.d.ts +9 -1
- package/utils/upsert-utils.js +16 -0
package/EntityManager.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getOnConflictReturningFields, getWhereCondition, resetUntouchedCollections } from './utils/upsert-utils.js';
|
|
1
|
+
import { getOnConflictReturningFields, getOnCreateGeneratedFields, getWhereCondition, resetUntouchedCollections, } from './utils/upsert-utils.js';
|
|
2
2
|
import { Utils } from './utils/Utils.js';
|
|
3
3
|
import { Cursor } from './utils/Cursor.js';
|
|
4
4
|
import { QueryHelper } from './utils/QueryHelper.js';
|
|
@@ -793,6 +793,7 @@ export class EntityManager {
|
|
|
793
793
|
}
|
|
794
794
|
const meta = this.metadata.get(entityName);
|
|
795
795
|
const convertCustomTypes = !Utils.isEntity(data);
|
|
796
|
+
let generatedFields = [];
|
|
796
797
|
if (Utils.isEntity(data)) {
|
|
797
798
|
entity = data;
|
|
798
799
|
if (helper(entity).__managed && helper(entity).__em === em && !this.config.get('upsertManaged')) {
|
|
@@ -800,6 +801,7 @@ export class EntityManager {
|
|
|
800
801
|
return entity;
|
|
801
802
|
}
|
|
802
803
|
where = helper(entity).getPrimaryKey();
|
|
804
|
+
generatedFields = getOnCreateGeneratedFields(meta, entity);
|
|
803
805
|
em.#entityFactory.assignDefaultValues(entity, meta);
|
|
804
806
|
data = em.#comparator.prepareEntity(entity);
|
|
805
807
|
}
|
|
@@ -812,6 +814,7 @@ export class EntityManager {
|
|
|
812
814
|
return em.assign(exists, data);
|
|
813
815
|
}
|
|
814
816
|
}
|
|
817
|
+
generatedFields = getOnCreateGeneratedFields(meta, data);
|
|
815
818
|
em.#entityFactory.assignDefaultValues(data, meta, true);
|
|
816
819
|
for (const key of Object.keys(data)) {
|
|
817
820
|
const prop = meta.properties[key];
|
|
@@ -820,6 +823,10 @@ export class EntityManager {
|
|
|
820
823
|
}
|
|
821
824
|
}
|
|
822
825
|
}
|
|
826
|
+
// `onCreate` generated values are for the insert clause only, they must not overwrite an existing row
|
|
827
|
+
if (generatedFields.length > 0 && !options.onConflictMergeFields) {
|
|
828
|
+
options.onConflictExcludeFields = [...(options.onConflictExcludeFields ?? []), ...generatedFields];
|
|
829
|
+
}
|
|
823
830
|
where = getWhereCondition(meta, options.onConflictFields, data, where).where;
|
|
824
831
|
data = QueryHelper.processObjectParams(data);
|
|
825
832
|
validateParams(data, 'insert data');
|
|
@@ -939,6 +946,7 @@ export class EntityManager {
|
|
|
939
946
|
}
|
|
940
947
|
const meta = this.metadata.get(entityName);
|
|
941
948
|
const convertCustomTypes = !Utils.isEntity(data[0]);
|
|
949
|
+
const generatedFields = new Set();
|
|
942
950
|
const allData = [];
|
|
943
951
|
const allWhere = [];
|
|
944
952
|
const entities = new Map();
|
|
@@ -956,6 +964,7 @@ export class EntityManager {
|
|
|
956
964
|
continue;
|
|
957
965
|
}
|
|
958
966
|
where = helper(entity).getPrimaryKey();
|
|
967
|
+
getOnCreateGeneratedFields(meta, entity).forEach(field => generatedFields.add(field));
|
|
959
968
|
em.#entityFactory.assignDefaultValues(entity, meta);
|
|
960
969
|
entitiesByAllDataIdx.set(allData.length, entity);
|
|
961
970
|
row = em.#comparator.prepareEntity(entity);
|
|
@@ -972,6 +981,7 @@ export class EntityManager {
|
|
|
972
981
|
continue;
|
|
973
982
|
}
|
|
974
983
|
}
|
|
984
|
+
getOnCreateGeneratedFields(meta, row).forEach(field => generatedFields.add(field));
|
|
975
985
|
em.#entityFactory.assignDefaultValues(row, meta, true);
|
|
976
986
|
for (const key of Object.keys(row)) {
|
|
977
987
|
const prop = meta.properties[key];
|
|
@@ -1000,6 +1010,10 @@ export class EntityManager {
|
|
|
1000
1010
|
if (entities.size === data.length) {
|
|
1001
1011
|
return [...entities.keys()];
|
|
1002
1012
|
}
|
|
1013
|
+
// `onCreate` generated values are for the insert clause only, they must not overwrite existing rows
|
|
1014
|
+
if (generatedFields.size > 0 && !options.onConflictMergeFields) {
|
|
1015
|
+
options.onConflictExcludeFields = [...(options.onConflictExcludeFields ?? []), ...generatedFields];
|
|
1016
|
+
}
|
|
1003
1017
|
if (em.eventManager.hasListeners(EventType.beforeUpsert, meta)) {
|
|
1004
1018
|
for (const dto of data) {
|
|
1005
1019
|
const entity = entitiesByData.get(dto) ?? dto;
|
|
@@ -345,6 +345,7 @@ export interface CountByOptions<T extends object> {
|
|
|
345
345
|
filters?: FilterOptions;
|
|
346
346
|
having?: FilterQuery<T>;
|
|
347
347
|
schema?: string;
|
|
348
|
+
connectionType?: ConnectionType;
|
|
348
349
|
flushMode?: FlushMode | `${FlushMode}`;
|
|
349
350
|
loggerContext?: LogContext;
|
|
350
351
|
logging?: LoggingOptions;
|
|
@@ -1676,6 +1676,9 @@ export class MetadataDiscovery {
|
|
|
1676
1676
|
if (prop.persist === false || prop.nativeEnumName || !prop.items?.every(item => typeof item === 'string')) {
|
|
1677
1677
|
continue;
|
|
1678
1678
|
}
|
|
1679
|
+
if (prop.customType instanceof t.json || ['json', 'jsonb'].includes(prop.columnTypes?.[0])) {
|
|
1680
|
+
continue;
|
|
1681
|
+
}
|
|
1679
1682
|
this.initFieldName(prop);
|
|
1680
1683
|
let expression = null;
|
|
1681
1684
|
if (prop.enum) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
|
-
"version": "7.1.13
|
|
3
|
+
"version": "7.1.13",
|
|
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
|
"keywords": [
|
|
6
6
|
"data-mapper",
|
package/typings.js
CHANGED
|
@@ -216,7 +216,10 @@ export class EntityMetadata {
|
|
|
216
216
|
if (config) {
|
|
217
217
|
const platform = config.getPlatform();
|
|
218
218
|
for (const prop of this.props) {
|
|
219
|
-
if (prop.enum &&
|
|
219
|
+
if (prop.enum &&
|
|
220
|
+
!prop.nativeEnumName &&
|
|
221
|
+
prop.items?.every(item => typeof item === 'string') &&
|
|
222
|
+
!['json', 'jsonb'].includes(prop.columnTypes?.[0])) {
|
|
220
223
|
const name = platform.getIndexName(this.tableName, prop.fieldNames, 'check');
|
|
221
224
|
const exists = this.checks.findIndex(check => check.name === name);
|
|
222
225
|
if (exists !== -1) {
|
package/utils/Utils.js
CHANGED
|
@@ -153,7 +153,7 @@ export function parseJsonSafe(value) {
|
|
|
153
153
|
/** Collection of general-purpose utility methods used throughout the ORM. */
|
|
154
154
|
export class Utils {
|
|
155
155
|
static PK_SEPARATOR = '~~~';
|
|
156
|
-
static #ORM_VERSION = '7.1.13
|
|
156
|
+
static #ORM_VERSION = '7.1.13';
|
|
157
157
|
/**
|
|
158
158
|
* Checks if the argument is instance of `Object`. Returns false for arrays.
|
|
159
159
|
*/
|
package/utils/upsert-utils.d.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import type { EntityData, EntityMetadata, FilterQuery } from '../typings.js';
|
|
1
|
+
import type { EntityData, EntityKey, EntityMetadata, FilterQuery } from '../typings.js';
|
|
2
2
|
import type { UpsertOptions } from '../drivers/IDatabaseDriver.js';
|
|
3
3
|
import { type Raw } from '../utils/RawQueryFragment.js';
|
|
4
4
|
/** @internal */
|
|
5
5
|
export declare function getOnConflictFields<T>(meta: EntityMetadata<T> | undefined, data: EntityData<T>, uniqueFields: (keyof T)[] | Raw, options: UpsertOptions<T>): (keyof T)[];
|
|
6
|
+
/**
|
|
7
|
+
* Detects properties that will get their value generated by an `onCreate` hook during the upsert,
|
|
8
|
+
* i.e. those with an `onCreate` hook and no value provided. Such values are meant for the insert
|
|
9
|
+
* clause only and must not overwrite an existing row via the `on conflict do update set` clause.
|
|
10
|
+
* The property filter mirrors `EntityFactory.assignDefaultValues`.
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export declare function getOnCreateGeneratedFields<T extends object>(meta: EntityMetadata<T>, data: T | EntityData<T>): EntityKey<T>[];
|
|
6
14
|
/** @internal */
|
|
7
15
|
export declare function getOnConflictReturningFields<T, P extends string>(meta: EntityMetadata<T> | undefined, data: EntityData<T>, uniqueFields: (keyof T)[] | Raw, options: UpsertOptions<T, P>): (keyof T)[] | '*';
|
|
8
16
|
/** @internal */
|
package/utils/upsert-utils.js
CHANGED
|
@@ -72,6 +72,22 @@ export function getOnConflictFields(meta, data, uniqueFields, options) {
|
|
|
72
72
|
}
|
|
73
73
|
return keys;
|
|
74
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Detects properties that will get their value generated by an `onCreate` hook during the upsert,
|
|
77
|
+
* i.e. those with an `onCreate` hook and no value provided. Such values are meant for the insert
|
|
78
|
+
* clause only and must not overwrite an existing row via the `on conflict do update set` clause.
|
|
79
|
+
* The property filter mirrors `EntityFactory.assignDefaultValues`.
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
82
|
+
export function getOnCreateGeneratedFields(meta, data) {
|
|
83
|
+
return meta.props
|
|
84
|
+
.filter(prop => prop.onCreate &&
|
|
85
|
+
!prop.embedded &&
|
|
86
|
+
![ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
87
|
+
!(prop.getter && !prop.setter) &&
|
|
88
|
+
data[prop.name] == null)
|
|
89
|
+
.map(prop => prop.name);
|
|
90
|
+
}
|
|
75
91
|
/** @internal */
|
|
76
92
|
export function getOnConflictReturningFields(meta, data, uniqueFields, options) {
|
|
77
93
|
/* v8 ignore next */
|