From 72cefb1b48fa025f190525618ca2a0ee60485d14 Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Thu, 5 Dec 2024 15:56:57 +0100 Subject: [PATCH] BUGFIX: Fix Workspace Metadata upsert adjusts `WorkspaceMetadataAndRoleRepository::updateWorkspaceMetadata()` so that it does not fail with > Failed to update metadata for workspace "workspace-name" (Content Repository "default"): An exception occurred while executing a query: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'default-workspace-name' for key 'PRIMARY' Background: Doctrine DBAL has no support for "upserts" built-in and the [suggested work around](https://github.com/doctrine/dbal/issues/1320#issuecomment-940757112) had a flaw that lead to the above exception when the incoming data wasn't actually changed (because `$affectedRows` is 0 in this case). This is fixed simply by issuing a `SELECT` first --- .../WorkspaceMetadataAndRoleRepository.php | 29 ++++++++++++++----- .../WorkspaceService.feature | 14 +++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/Neos.Neos/Classes/Domain/Repository/WorkspaceMetadataAndRoleRepository.php b/Neos.Neos/Classes/Domain/Repository/WorkspaceMetadataAndRoleRepository.php index ed6c928f6c..cf320af71f 100644 --- a/Neos.Neos/Classes/Domain/Repository/WorkspaceMetadataAndRoleRepository.php +++ b/Neos.Neos/Classes/Domain/Repository/WorkspaceMetadataAndRoleRepository.php @@ -253,15 +253,30 @@ public function updateWorkspaceMetadata(ContentRepositoryId $contentRepositoryId $data = array_filter([ 'title' => $title, 'description' => $description, - ], fn ($value) => $value !== null); + ], static fn ($value) => $value !== null); + $table = self::TABLE_NAME_WORKSPACE_METADATA; + $query = <<dbal->update(self::TABLE_NAME_WORKSPACE_METADATA, $data, [ - 'content_repository_id' => $contentRepositoryId->value, - 'workspace_name' => $workspace->workspaceName->value, - ]); - if ($affectedRows === 0) { - $this->dbal->insert(self::TABLE_NAME_WORKSPACE_METADATA, [ + $rowExists = $this->dbal->fetchOne($query, [ + 'contentRepositoryId' => $contentRepositoryId->value, + 'workspaceName' => $workspace->workspaceName->value, + ]) !== false; + if ($rowExists) { + $this->dbal->update($table, $data, [ + 'content_repository_id' => $contentRepositoryId->value, + 'workspace_name' => $workspace->workspaceName->value, + ]); + } else { + $this->dbal->insert($table, [ 'content_repository_id' => $contentRepositoryId->value, 'workspace_name' => $workspace->workspaceName->value, 'description' => '', diff --git a/Neos.Neos/Tests/Behavior/Features/ContentRepository/WorkspaceService.feature b/Neos.Neos/Tests/Behavior/Features/ContentRepository/WorkspaceService.feature index 22b3ff17e0..1bdac437c3 100644 --- a/Neos.Neos/Tests/Behavior/Features/ContentRepository/WorkspaceService.feature +++ b/Neos.Neos/Tests/Behavior/Features/ContentRepository/WorkspaceService.feature @@ -52,6 +52,13 @@ Feature: Neos WorkspaceService related features | Title | Description | Classification | Owner user id | | Some new workspace title | | ROOT | | + Scenario: Change title of root workspace to the same value + When the root workspace "some-root-workspace" with title "some title" and description "some description" is created + And the title of workspace "some-root-workspace" is set to "some title" + Then the workspace "some-root-workspace" should have the following metadata: + | Title | Description | Classification | Owner user id | + | some title | some description | ROOT | | + Scenario: Set title of root workspace without metadata When a root workspace "some-root-workspace" exists without metadata And the title of workspace "some-root-workspace" is set to "Some new workspace title" @@ -66,6 +73,13 @@ Feature: Neos WorkspaceService related features | Title | Description | Classification | Owner user id | | some-root-workspace | Some new workspace description | ROOT | | + Scenario: Change description of root workspace to the same value + When the root workspace "some-root-workspace" with title "some title" and description "some description" is created + And the description of workspace "some-root-workspace" is set to "some description" + Then the workspace "some-root-workspace" should have the following metadata: + | Title | Description | Classification | Owner user id | + | some title | some description | ROOT | | + Scenario: Change description of root workspace without metadata When a root workspace "some-root-workspace" exists without metadata And the description of workspace "some-root-workspace" is set to "Some new workspace description"