Skip to content

Commit

Permalink
feat(core): support composite unique keys in em.upsert()
Browse files Browse the repository at this point in the history
Closes #3656
  • Loading branch information
B4nan committed Nov 3, 2022
1 parent 18358a6 commit 3cf79d6
Show file tree
Hide file tree
Showing 4 changed files with 447 additions and 8 deletions.
20 changes: 17 additions & 3 deletions packages/core/src/EntityManager.ts
Expand Up @@ -530,12 +530,26 @@ export class EntityManager<D extends IDatabaseDriver = IDatabaseDriver> {
const unique = meta.props.filter(p => p.unique).map(p => p.name);
const propIndex = unique.findIndex(p => data![p] != null);

if (where == null && propIndex >= 0) {
where = { [unique[propIndex]]: data[unique[propIndex]] } as FilterQuery<T>;
if (where == null) {
if (propIndex >= 0) {
where = { [unique[propIndex]]: data[unique[propIndex]] } as FilterQuery<T>;
} else if (meta.uniques.length > 0) {
for (const u of meta.uniques) {
if (Utils.asArray(u.properties).every(p => data![p])) {
where = Utils.asArray(u.properties).reduce((o, key) => {
o[key] = data![key];
return o;
}, {} as FilterQuery<T>);
break;
}
}
}
}

if (where == null) {
throw new Error(`Unique property value required for upsert, provide one of: ${meta.primaryKeys.concat(...unique)}`);
const compositeUniqueProps = meta.uniques.map(u => Utils.asArray(u.properties).join(' + '));
const uniqueProps = meta.primaryKeys.concat(...unique).concat(compositeUniqueProps);
throw new Error(`Unique property value required for upsert, provide one of: ${uniqueProps.join(', ')}`);
}

data = QueryHelper.processObjectParams(data) as EntityData<T>;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/unit-of-work/UnitOfWork.ts
Expand Up @@ -779,7 +779,7 @@ export class UnitOfWork {
if (!Utils.isEntity(reference)) {
entity[prop.name] = this.em.getReference(prop.type, reference as Primary<T[string & keyof T]>, { wrapped: !!prop.wrappedReference }) as T[string & keyof T];
} else if (!helper(reference).__initialized && !helper(reference).__em) {
const pk = helper(reference).getSerializedPrimaryKey();
const pk = helper(reference).getPrimaryKey();
entity[prop.name] = this.em.getReference(prop.type, pk as Primary<T[string & keyof T]>, { wrapped: !!prop.wrappedReference }) as T[string & keyof T];
}
}
Expand Down

0 comments on commit 3cf79d6

Please sign in to comment.