From d35b8777dac58ce546b713dbcf746108dd2db01a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89mile=20R=C3=A9?= Date: Mon, 4 May 2026 15:13:10 +0400 Subject: [PATCH] Filter uncategorised category at the SQL level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of loading all categories and filtering out UNCATEGORISED in Go, add LoadConsentCategoriesByCookieBannerID which excludes it in the query. This avoids fetching data we immediately discard and makes the intent explicit at each call site. Signed-off-by: Émile Ré --- pkg/cookiebanner/service.go | 4 +-- pkg/cookiebanner/snapshot.go | 22 +++++-------- pkg/coredata/cookie_category.go | 55 +++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 16 deletions(-) diff --git a/pkg/cookiebanner/service.go b/pkg/cookiebanner/service.go index 90733f82b..d1a1f9a6f 100644 --- a/pkg/cookiebanner/service.go +++ b/pkg/cookiebanner/service.go @@ -428,7 +428,7 @@ func (s *Service) ensureDraftVersionForBanner( } var categories coredata.CookieCategories - if err := categories.LoadAllByCookieBannerID(ctx, tx, scope, bannerID); err != nil { + if err := categories.LoadConsentCategoriesByCookieBannerID(ctx, tx, scope, bannerID); err != nil { return nil, fmt.Errorf("cannot load cookie categories: %w", err) } @@ -1887,7 +1887,7 @@ func (s *Service) GetActiveBannerConfig( } var categories coredata.CookieCategories - if err := categories.LoadAllByCookieBannerID(ctx, conn, scope, banner.ID); err != nil { + if err := categories.LoadConsentCategoriesByCookieBannerID(ctx, conn, scope, banner.ID); err != nil { return fmt.Errorf("cannot load cookie categories: %w", err) } diff --git a/pkg/cookiebanner/snapshot.go b/pkg/cookiebanner/snapshot.go index 58532aee1..343346ade 100644 --- a/pkg/cookiebanner/snapshot.go +++ b/pkg/cookiebanner/snapshot.go @@ -31,7 +31,8 @@ func resolveTranslations( translations coredata.CookieBannerTranslations, categories coredata.CookieCategories, ) map[string]coredata.CookieBannerVersionSnapshotTranslation { - return buildSnapshotTranslations(translations, consentCategories(categories)) + sortConsentCategories(categories) + return buildSnapshotTranslations(translations, categories) } // snapshotsEqual reports whether two version snapshots are visitor-identical. @@ -56,23 +57,16 @@ func snapshotCategoryKindOrder(k coredata.CookieCategoryKind) int { } } -// consentCategories returns the categories that are part of the consent -// contract (everything except UNCATEGORISED), sorted in snapshot order. -// UNCATEGORISED is an admin-side inbox and never shown to visitors. -func consentCategories(categories coredata.CookieCategories) coredata.CookieCategories { - filtered := make(coredata.CookieCategories, 0, len(categories)) - for _, c := range categories { - if c.Kind != coredata.CookieCategoryKindUncategorised { - filtered = append(filtered, c) - } - } - slices.SortStableFunc(filtered, func(a, b *coredata.CookieCategory) int { +// sortConsentCategories sorts categories in snapshot order: NECESSARY first, +// then NORMAL sorted by ID. The caller is expected to have already excluded +// UNCATEGORISED at load time. +func sortConsentCategories(categories coredata.CookieCategories) { + slices.SortStableFunc(categories, func(a, b *coredata.CookieCategory) int { if d := snapshotCategoryKindOrder(a.Kind) - snapshotCategoryKindOrder(b.Kind); d != 0 { return d } return bytes.Compare(a.ID[:], b.ID[:]) }) - return filtered } func buildSnapshot( @@ -80,7 +74,7 @@ func buildSnapshot( categories coredata.CookieCategories, allPatterns coredata.CookiePatterns, ) coredata.CookieBannerVersionSnapshot { - categories = consentCategories(categories) + sortConsentCategories(categories) cookiesByCategory := make(map[gid.GID]coredata.CookieItems) for _, p := range allPatterns { diff --git a/pkg/coredata/cookie_category.go b/pkg/coredata/cookie_category.go index 8023b3c13..1f6cb063c 100644 --- a/pkg/coredata/cookie_category.go +++ b/pkg/coredata/cookie_category.go @@ -323,6 +323,61 @@ ORDER BY return nil } +// LoadConsentCategoriesByCookieBannerID loads all categories except +// UNCATEGORISED, which is an admin-side inbox never shown to visitors. +func (c *CookieCategories) LoadConsentCategoriesByCookieBannerID( + ctx context.Context, + conn pg.Querier, + scope Scoper, + cookieBannerID gid.GID, +) error { + q := ` +SELECT + id, + organization_id, + cookie_banner_id, + name, + slug, + description, + kind, + rank, + gcm_consent_types, + posthog_consent, + created_at, + updated_at +FROM + cookie_categories +WHERE + %s + AND cookie_banner_id = @cookie_banner_id + AND kind != @excluded_kind +ORDER BY + rank ASC, id ASC; +` + + q = fmt.Sprintf(q, scope.SQLFragment()) + + args := pgx.StrictNamedArgs{ + "cookie_banner_id": cookieBannerID, + "excluded_kind": CookieCategoryKindUncategorised, + } + maps.Copy(args, scope.SQLArguments()) + + rows, err := conn.Query(ctx, q, args) + if err != nil { + return fmt.Errorf("cannot query consent cookie categories: %w", err) + } + + categories, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[CookieCategory]) + if err != nil { + return fmt.Errorf("cannot collect consent cookie categories: %w", err) + } + + *c = categories + + return nil +} + func (c *CookieCategory) Insert( ctx context.Context, tx pg.Tx,