Add merge_request_saved_views table and model
What does this MR do and why?
Introduces persistence for merge request dashboard saved views. Each row belongs to a user and stores a name plus a jsonb filters blob, validated against a new JSON schema derived from the filter vocabulary of MergeRequestsResolver. Sort order is stored as one of those keys, since it is a resolver argument like any other.
Filters keep raw GraphQL argument names - usernames, label names, milestone titles - so they can be handed straight to the resolver and rehydrate the dashboard filter bar. They are deliberately not normalised to IDs: normalising resolves titles against a container namespace, and this table is scoped to a user rather than a namespace. The accepted consequence is that renaming a user or retitling a label changes what a saved view returns.
Two array filters are capped, because the 8 KB byte limit alone is too coarse: label_name at 25, since Issuables::LabelFilter adds one EXISTS subquery per label name, and approved_by at 5, matching the truncation MergeRequests::ByApprovalsFinder already applies. Both caps are mirrored in the negated block to match what the filter bar will offer.
There is no schema version column. additionalProperties: false at both levels makes each payload identifiable against this schema's history, and adding version later is a plain add_column defaulting to 1.
Saved views are limited to 5 per user in CE and 100 in EE. Names are unique per user and compared case sensitively, the same rule saved replies apply (app/models/concerns/saved_reply_concern.rb). Work item saved views scoped their equivalent constraint to a namespace, where a user could collide with someone else's private view; scoping to the owner means the only name a user can collide with is one of their own.
This is the first of four backend merge requests for merge request dashboard saved views. Each subsequent merge request targets the previous one:
- This merge request - table, model, JSON schema, factory
- !247090 (merged) - Services, finder, and authorization policy
- !247106 (merged) - GraphQL read API (
currentUser.mergeRequestSavedViews) - !247119 (merged) - GraphQL mutations (create, update, delete)
Nothing is user-facing yet; there is no API surface or UI until merge requests 3 and 4 land.
How to set up and validate locally
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.