From 5b2cbcb1b5410e8416b7d0e27ceac490b0e06f57 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sat, 11 Apr 2026 18:17:22 +0200 Subject: [PATCH] fix(project): replace CAST(... AS int) with CASE WHEN for MySQL 8 compat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MySQL 8 rejects CAST(... AS int) (only SIGNED/UNSIGNED/CHAR/... are accepted as target types), causing /api/v1/projects, /api/v1/tasks, and /api/v1/labels to return HTTP 500 for every authenticated user on MySQL 8. SQLite, Postgres, and MariaDB lax mode silently accepted the expression, which is why the regression (introduced in e3045dfd0, shipped in v2.3.0) passed CI — the mysql CI matrix leg uses mariadb:12, not real MySQL 8. Replace the two CAST(all_projects.is_archived AS int) expressions in the recursive project CTE with MAX(CASE WHEN ... THEN 1 ELSE 0 END), which is dialect-agnostic and needs no cast on any supported backend. Fixes #2589 --- pkg/models/project.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/models/project.go b/pkg/models/project.go index 39881b06a..65a5f1430 100644 --- a/pkg/models/project.go +++ b/pkg/models/project.go @@ -582,7 +582,7 @@ INNER JOIN all_projects ap ON p.parent_project_id = ap.id` "all_projects.hex_color", "all_projects.owner_id", "CASE WHEN all_projects.parent_project_id IS NULL THEN 0 ELSE all_projects.parent_project_id END AS parent_project_id", - "MAX(CAST(all_projects.is_archived AS int)) AS is_archived", + "MAX(CASE WHEN all_projects.is_archived THEN 1 ELSE 0 END) AS is_archived", "all_projects.background_file_id", "all_projects.background_blur_hash", "all_projects.position", @@ -607,7 +607,7 @@ INNER JOIN all_projects ap ON p.parent_project_id = ap.id` var archivedFilter string if !opts.getArchived { - archivedFilter = "HAVING MAX(CAST(all_projects.is_archived AS int)) = 0 " + archivedFilter = "HAVING MAX(CASE WHEN all_projects.is_archived THEN 1 ELSE 0 END) = 0 " } currentProjects := []*Project{}