From ae17640fbc024cc1cc474f256eec4b83936c78a6 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Mon, 4 Aug 2025 14:13:55 +0200 Subject: [PATCH] Fix upsert in ORM (#13589) Before: image After: image Query: ``` mutation CreatePerson($upsert: Boolean, $data: PersonCreateInput) { createPerson(upsert: $upsert, data: $data) { jobTitle id } } ``` Variables: ``` { "upsert": true, "data": { "name": { "firstName": "marie"} } } ``` --- .../workspace-entity-manager.ts | 6 +++--- .../workspace-insert-query-builder.ts | 20 ++++++++++--------- .../repository/workspace.repository.ts | 4 +++- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.ts b/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.ts index b3d099988a..31f24a8ecb 100644 --- a/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.ts +++ b/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.ts @@ -190,8 +190,8 @@ export class WorkspaceEntityManager extends EntityManager { override upsert( target: EntityTarget, entityOrEntities: - | QueryDeepPartialEntity - | QueryDeepPartialEntity[], + | QueryDeepPartialEntityWithNestedRelationFields + | QueryDeepPartialEntityWithNestedRelationFields[], conflictPathsOrOptions: string[] | UpsertOptions, permissionOptions?: { shouldBypassPermissionChecks?: boolean; @@ -209,7 +209,7 @@ export class WorkspaceEntityManager extends EntityManager { } else { options = conflictPathsOrOptions; } - let entities: QueryDeepPartialEntity[]; + let entities: QueryDeepPartialEntityWithNestedRelationFields[]; if (!Array.isArray(entityOrEntities)) { entities = [entityOrEntities]; diff --git a/packages/twenty-server/src/engine/twenty-orm/repository/workspace-insert-query-builder.ts b/packages/twenty-server/src/engine/twenty-orm/repository/workspace-insert-query-builder.ts index d40df96cde..0ec313a08e 100644 --- a/packages/twenty-server/src/engine/twenty-orm/repository/workspace-insert-query-builder.ts +++ b/packages/twenty-server/src/engine/twenty-orm/repository/workspace-insert-query-builder.ts @@ -29,6 +29,7 @@ import { WorkspaceUpdateQueryBuilder } from 'src/engine/twenty-orm/repository/wo import { formatData } from 'src/engine/twenty-orm/utils/format-data.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; import { getObjectMetadataFromEntityTarget } from 'src/engine/twenty-orm/utils/get-object-metadata-from-entity-target.util'; +import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager'; export class WorkspaceInsertQueryBuilder< T extends ObjectLiteral, @@ -137,16 +138,17 @@ export class WorkspaceInsertQueryBuilder< } const result = await super.execute(); - const eventSelectQueryBuilder = new WorkspaceSelectQueryBuilder( - this as unknown as WorkspaceSelectQueryBuilder, - this.objectRecordsPermissions, - this.internalContext, - true, - this.authContext, - this.featureFlagMap, - ); + const eventSelectQueryBuilder = ( + this.connection.manager as WorkspaceEntityManager + ).createQueryBuilder( + mainAliasTarget, + this.expressionMap.mainAlias?.metadata.name ?? '', + undefined, + { + shouldBypassPermissionChecks: true, + }, + ) as WorkspaceSelectQueryBuilder; - eventSelectQueryBuilder.expressionMap.aliases = this.expressionMap.aliases; eventSelectQueryBuilder.whereInIds( result.identifiers.map((identifier) => identifier.id), ); diff --git a/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts b/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts index 0d135de9a0..a3b429ea16 100644 --- a/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts +++ b/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts @@ -622,7 +622,9 @@ export class WorkspaceRepository< } override async upsert( - entityOrEntities: QueryDeepPartialEntity | QueryDeepPartialEntity[], + entityOrEntities: + | QueryDeepPartialEntityWithNestedRelationFields + | QueryDeepPartialEntityWithNestedRelationFields[], conflictPathsOrOptions: string[] | UpsertOptions, entityManager?: WorkspaceEntityManager, selectedColumns: string[] = [],