mirror of
https://github.com/zitadel/zitadel.git
synced 2026-11-03 12:47:09 -06:00
<!-- CURSOR_AGENT_PR_BODY_BEGIN --> - Setup 79 rewrites unique-constraint owners in one statement per file. On a large table that statement holds row locks for the whole update, and adding `LIMIT` does not help: the username statement bitmap-scans every empty `owners` value and then index-scans every user in the instance for each constraint. - The backfill joined projection tables before those tables were created and before event replay filled them. - The page cursor is a `text[]`. `database.TextArray.Value` joined elements with commas and never quoted them, so a project role key such as `a,b` became two array elements. The next page repeated the same row and the migration stopped. - Each setup 79 statement pages its projection by primary key and updates `eventstore.unique_constraints` with an equality lookup on `(instance_id, unique_type, unique_field)`. - The original field and `lower(...)` are separate `UNION` arms, so the lookup stays a primary-key probe. - Setup repeats a file until the projection page is empty. A page that matches no constraint still advances the cursor. - `BatchSize` is a `uint16`, configured like `ForceFinalize` (`cmd/setup/steps.yaml`, `ZITADEL_BACKFILLUNIQUECONSTRAINTOWNERS_BATCHSIZE`) and is not stored on lastRun. The default in `steps.yaml` is 5000. - Each page logs the file, the page index, and the number of rows updated. - The backfill runs after projection prefill. When `InitProjections` is disabled or setup is for mirror, it still runs against the projection rows already stored. - `TextArray.Value` quotes every element and backslash-escapes `"` and `\`. An empty array is still SQL `NULL`, so existing `ANY($1)` callers stay unchanged. The setup statements already cast `$1` to `text[]`. - Integration tests for the username and org-domain statements pass an empty cursor and a page size. - `TestTextArray_Value` expects quoted elements, and a round trip through `Scan` covers a comma, a quote, and a backslash. - initial fix https://github.com/zitadel/zitadel/pull/12740 - fix of the setup job, broken by the first fix https://github.com/zitadel/zitadel/pull/12785 - needs to be a `fix` tag because `perf` wouldn't bump the version - Based on `owner-app-fix`. - A setup process already running the old statement keeps that plan until it is restarted. <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-31bfb5c4-5888-43f0-85cf-af1af097ca30?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-31bfb5c4-5888-43f0-85cf-af1af097ca30&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Silvan <adlerhurst@users.noreply.github.com>