diff --git a/backend/migrations/20260624103600_repair_folder_labels_search_path.down.sql b/backend/migrations/20260624103600_repair_folder_labels_search_path.down.sql new file mode 100644 index 0000000000..3d532de9cb --- /dev/null +++ b/backend/migrations/20260624103600_repair_folder_labels_search_path.down.sql @@ -0,0 +1,3 @@ +-- No-op: this migration only re-pins the function's search_path. Reverting would +-- mean restoring the hardcoded `SET search_path = public`, which is the very bug +-- this repairs, so there is nothing to undo. diff --git a/backend/migrations/20260624103600_repair_folder_labels_search_path.up.sql b/backend/migrations/20260624103600_repair_folder_labels_search_path.up.sql new file mode 100644 index 0000000000..f8e448891f --- /dev/null +++ b/backend/migrations/20260624103600_repair_folder_labels_search_path.up.sql @@ -0,0 +1,22 @@ +-- Repair instances that already applied the folder-labels migrations while the +-- function hardcoded `SET search_path = public`. On a non-public schema (PG_SCHEMA) +-- the function was pinned to `public`, so at runtime it read the wrong `folder` +-- table (or a stray public.folder) instead of the workspace's real one. +-- +-- `FROM CURRENT` snapshots the migration connection's search_path (the actual +-- Windmill schema) into the function, keeping the SECURITY DEFINER injection +-- hardening. On public-schema installs this re-pins to `public`, i.e. a no-op. +-- Idempotent: redefining with the same body is harmless on already-correct installs. +CREATE OR REPLACE FUNCTION folder_labels(w_id text, item_path text) RETURNS text[] +LANGUAGE sql STABLE SECURITY DEFINER SET search_path FROM CURRENT AS $$ + SELECT ( + SELECT array_agg(l ORDER BY first_ord) + FROM ( + SELECT u.l, min(u.ord) AS first_ord + FROM unnest(f.labels) WITH ORDINALITY AS u(l, ord) + GROUP BY u.l + ) deduped + ) + FROM folder f + WHERE f.workspace_id = w_id AND item_path LIKE 'f/%' AND f.name = split_part(item_path, '/', 2) +$$; diff --git a/backend/windmill-api/src/db.rs b/backend/windmill-api/src/db.rs index 7b8d468da8..df6c8cc6b5 100644 --- a/backend/windmill-api/src/db.rs +++ b/backend/windmill-api/src/db.rs @@ -84,6 +84,12 @@ lazy_static::lazy_static! { (20260228000000, include_str!( "../../migrations/20260228000000_v2_job_completed_failure_index.up.sql" ).replace("CREATE INDEX", "CREATE INDEX CONCURRENTLY")), + (20260610151334, include_str!( + "../../migrations/20260610151334_folder_labels.up.sql" + ).replace("SET search_path = public", "SET search_path FROM CURRENT").to_string()), + (20260614075900, include_str!( + "../../migrations/20260614075900_dedup_folder_labels.up.sql" + ).replace("SET search_path = public", "SET search_path FROM CURRENT").to_string()), ].into_iter().collect(); }