Refacto load all functions

Unbounded LoadAll* loaders materialised an entire result set in one
query with no ceiling. A table that is small in development can grow
without bound in production, so these loaders were a latent memory
and query-time hazard.

Remove the LoadAll* methods from pkg/coredata and walk the cursor-
paginated LoadBy* siblings instead through a shared page.LoadAll
helper. The helper advances a MaxCursorSize forward cursor until the
result set is exhausted and concatenates the pages. It caps a single
call at MaxLoadAllPages (20) batches of 500 rows and errors past that
rather than materialising an unbounded set, so a runaway caller fails
loudly instead of exhausting memory.

Callers that genuinely need every row now express that explicitly,
and the coredata load-naming rule and docs are updated to discourage
new unbounded loaders.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
This commit is contained in:
Sacha Al Himdani
2026-06-09 19:33:36 +02:00
committed by Sacha Al Himdani
parent 853f2404a6
commit 9ab8ea2085
46 changed files with 1218 additions and 1674 deletions

View File

@@ -386,54 +386,6 @@ WHERE
return nil
}
// LoadAllByCampaignSourceID returns the full attempt history for a snapshot,
// newest first.
func (attempts *AccessReviewCampaignSourceFetchAttempts) LoadAllByCampaignSourceID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
campaignSourceID gid.GID,
) error {
q := `
SELECT
id,
organization_id,
tenant_id,
access_review_campaign_source_id,
attempt_number,
status,
fetched_accounts_count,
error,
started_at,
completed_at,
created_at,
updated_at
FROM access_review_campaign_source_fetch_attempts
WHERE
%s
AND access_review_campaign_source_id = @access_review_campaign_source_id
ORDER BY attempt_number DESC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"access_review_campaign_source_id": campaignSourceID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query fetch attempts: %w", err)
}
result, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[AccessReviewCampaignSourceFetchAttempt])
if err != nil {
return fmt.Errorf("cannot collect fetch attempts: %w", err)
}
*attempts = result
return nil
}
func (attempts *AccessReviewCampaignSourceFetchAttempts) CountByCampaignSourceID(
ctx context.Context,
conn pg.Querier,

View File

@@ -16,6 +16,7 @@ package coredata_test
import (
"context"
"fmt"
"testing"
"time"
@@ -25,6 +26,7 @@ import (
"go.probo.inc/probo/internal/test"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
)
func insertAccessReviewEntry(t *testing.T, ctx context.Context, client *pg.Client, fx accessEntryFixture, accountKey string) gid.GID {
@@ -143,7 +145,28 @@ func TestSourceFetchAttempts_AppendOnly(t *testing.T) {
var history coredata.AccessReviewCampaignSourceFetchAttempts
require.NoError(t, client.WithConn(ctx, func(ctx context.Context, conn pg.Querier) error {
return history.LoadAllByCampaignSourceID(ctx, conn, fx.scope, fx.campaignSourceID)
loaded, err := page.LoadAll(
ctx,
page.OrderBy[coredata.AccessReviewCampaignSourceFetchAttemptOrderField]{
Field: coredata.AccessReviewCampaignSourceFetchAttemptOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
},
func(ctx context.Context, cursor *page.Cursor[coredata.AccessReviewCampaignSourceFetchAttemptOrderField]) ([]*coredata.AccessReviewCampaignSourceFetchAttempt, error) {
var batch coredata.AccessReviewCampaignSourceFetchAttempts
if err := batch.LoadByCampaignSourceID(ctx, conn, fx.scope, fx.campaignSourceID, cursor); err != nil {
return nil, fmt.Errorf("cannot load fetch attempts: %w", err)
}
return batch, nil
},
)
if err != nil {
return err
}
history = loaded
return nil
}))
require.Len(t, history, 2, "both attempts must be retained")
assert.Equal(t, coredata.AccessReviewCampaignSourceFetchStatusSuccess, history[0].Status, "history is newest first")

View File

@@ -482,57 +482,6 @@ WHERE
return nil
}
func (sacs *ApplicabilityStatements) LoadAllByStatementOfApplicabilityID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
statementOfApplicabilityID gid.GID,
) error {
q := `
SELECT
a.id,
a.statement_of_applicability_id,
a.control_id,
a.organization_id,
a.applicability,
a.justification,
a.created_at,
a.updated_at,
f.name || ' - ' || c.section_title AS section_title
FROM
applicability_statements a
INNER JOIN
controls c ON c.id = a.control_id
INNER JOIN
frameworks f ON f.id = c.framework_id
WHERE
a.%s
AND a.statement_of_applicability_id = @statement_of_applicability_id
ORDER BY
section_title_sort_key(f.name || ' - ' || c.section_title) ASC;
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{
"statement_of_applicability_id": statementOfApplicabilityID,
}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query applicability_statements: %w", err)
}
controls, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ApplicabilityStatement])
if err != nil {
return fmt.Errorf("cannot collect applicability_statements: %w", err)
}
*sacs = controls
return nil
}
func (sacs *ApplicabilityStatements) CountByStatementOfApplicabilityID(
ctx context.Context,
conn pg.Querier,

View File

@@ -50,6 +50,8 @@ func (a *Asset) CursorKey(field AssetOrderField) page.CursorKey {
return page.NewCursorKey(a.ID, a.CreatedAt)
case AssetOrderFieldAmount:
return page.NewCursorKey(a.ID, a.Amount)
case AssetOrderFieldName:
return page.NewCursorKey(a.ID, a.Name)
}
panic(fmt.Sprintf("unsupported order by: %s", field))
@@ -270,52 +272,6 @@ WHERE
return nil
}
func (a *Assets) LoadAllByOrganizationID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
organizationID gid.GID,
) error {
q := `
SELECT
id,
name,
organization_id,
owner_profile_id,
amount,
asset_type,
data_types_stored,
created_at,
updated_at
FROM
assets
WHERE
%s
AND organization_id = @organization_id
ORDER BY
name ASC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query assets: %w", err)
}
assets, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Asset])
if err != nil {
return fmt.Errorf("cannot collect assets: %w", err)
}
*a = assets
return nil
}
func (a *Asset) Insert(
ctx context.Context,
conn pg.Tx,

View File

@@ -237,56 +237,6 @@ WHERE
return nil
}
func (a *Audits) LoadAllByOrganizationID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
organizationID gid.GID,
filter *AuditFilter,
) error {
q := `
SELECT
id,
name,
organization_id,
framework_id,
report_file_id,
valid_from,
valid_until,
state,
trust_center_visibility,
created_at,
updated_at
FROM
audits
WHERE
%s
AND organization_id = @organization_id
AND %s
ORDER BY valid_from DESC
`
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
args := pgx.StrictNamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, filter.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query audits: %w", err)
}
audits, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Audit])
if err != nil {
return fmt.Errorf("cannot collect audits: %w", err)
}
*a = audits
return nil
}
func (a *Audit) Insert(
ctx context.Context,
conn pg.Tx,

View File

@@ -27,6 +27,7 @@ import (
"go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/iam/policy"
"go.probo.inc/probo/pkg/page"
)
type (
@@ -43,6 +44,17 @@ type (
CookieBannerTranslations []*CookieBannerTranslation
)
func (t CookieBannerTranslation) CursorKey(field CookieBannerTranslationOrderField) page.CursorKey {
switch field {
case CookieBannerTranslationOrderFieldLanguage:
return page.NewCursorKey(t.ID, t.Language)
case CookieBannerTranslationOrderFieldCreatedAt:
return page.NewCursorKey(t.ID, t.CreatedAt)
}
panic(fmt.Sprintf("unsupported order by: %s", field))
}
func (t *CookieBannerTranslation) AuthorizationAttributes(
ctx context.Context,
conn pg.Querier,
@@ -181,11 +193,12 @@ LIMIT 1;
return nil
}
func (t *CookieBannerTranslations) LoadAllByCookieBannerID(
func (t *CookieBannerTranslations) LoadByCookieBannerID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
cookieBannerID gid.GID,
cursor *page.Cursor[CookieBannerTranslationOrderField],
) error {
q := `
SELECT
@@ -201,14 +214,14 @@ FROM
WHERE
%s
AND cookie_banner_id = @cookie_banner_id
ORDER BY
language ASC;
AND %s
`
q = fmt.Sprintf(q, scope.SQLFragment())
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
args := pgx.StrictNamedArgs{"cookie_banner_id": cookieBannerID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, cursor.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {

View File

@@ -0,0 +1,79 @@
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package coredata
import (
"encoding"
"fmt"
"go.probo.inc/probo/pkg/page"
)
type (
CookieBannerTranslationOrderField string
)
const (
CookieBannerTranslationOrderFieldLanguage CookieBannerTranslationOrderField = "LANGUAGE"
CookieBannerTranslationOrderFieldCreatedAt CookieBannerTranslationOrderField = "CREATED_AT"
)
var (
_ page.OrderField = CookieBannerTranslationOrderField("")
_ fmt.Stringer = CookieBannerTranslationOrderField("")
_ encoding.TextMarshaler = CookieBannerTranslationOrderField("")
_ encoding.TextUnmarshaler = (*CookieBannerTranslationOrderField)(nil)
)
func CookieBannerTranslationOrderFields() []CookieBannerTranslationOrderField {
return []CookieBannerTranslationOrderField{
CookieBannerTranslationOrderFieldLanguage,
CookieBannerTranslationOrderFieldCreatedAt,
}
}
func (v CookieBannerTranslationOrderField) IsValid() bool {
switch v {
case
CookieBannerTranslationOrderFieldLanguage,
CookieBannerTranslationOrderFieldCreatedAt:
return true
}
return false
}
func (v CookieBannerTranslationOrderField) String() string {
return string(v)
}
func (v CookieBannerTranslationOrderField) MarshalText() ([]byte, error) {
return []byte(v.String()), nil
}
func (v *CookieBannerTranslationOrderField) UnmarshalText(text []byte) error {
val := CookieBannerTranslationOrderField(text)
if !val.IsValid() {
return fmt.Errorf("invalid CookieBannerTranslationOrderField value: %q", string(text))
}
*v = val
return nil
}
func (p CookieBannerTranslationOrderField) Column() string {
return string(p)
}

View File

@@ -386,58 +386,6 @@ WHERE
return count, nil
}
func (c *CookieCategories) LoadAllByCookieBannerID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
cookieBannerID gid.GID,
filter *CookieCategoryFilter,
) 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 %s
ORDER BY
rank ASC, id ASC;
`
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
args := pgx.StrictNamedArgs{"cookie_banner_id": cookieBannerID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, filter.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query cookie categories: %w", err)
}
categories, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[CookieCategory])
if err != nil {
return fmt.Errorf("cannot collect cookie categories: %w", err)
}
*c = categories
return nil
}
func (c *CookieCategory) Insert(
ctx context.Context,
tx pg.Tx,

View File

@@ -284,51 +284,6 @@ WHERE
return nil
}
func (dpias *DataProtectionImpactAssessments) LoadAllByOrganizationID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
organizationID gid.GID,
) error {
q := `
SELECT
id,
organization_id,
processing_activity_id,
description,
necessity_and_proportionality,
potential_risk,
mitigations,
residual_risk,
created_at,
updated_at
FROM
processing_activity_data_protection_impact_assessments
WHERE
%s
AND organization_id = @organization_id
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query data protection impact assessments: %w", err)
}
results, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[DataProtectionImpactAssessment])
if err != nil {
return fmt.Errorf("cannot collect data protection impact assessments: %w", err)
}
*dpias = results
return nil
}
func (dpia *DataProtectionImpactAssessment) LoadByID(
ctx context.Context,
conn pg.Querier,

View File

@@ -258,50 +258,6 @@ WHERE
return nil
}
func (d *Data) LoadAllByOrganizationID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
organizationID gid.GID,
) error {
q := `
SELECT
id,
name,
organization_id,
owner_profile_id,
data_classification,
created_at,
updated_at
FROM
data
WHERE
%s
AND organization_id = @organization_id
ORDER BY
name ASC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query data: %w", err)
}
data, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Datum])
if err != nil {
return fmt.Errorf("cannot collect data: %w", err)
}
*d = data
return nil
}
func (d *Datum) Insert(
ctx context.Context,
conn pg.Tx,

View File

@@ -295,59 +295,6 @@ LIMIT @limit;
return ids, nil
}
// LoadAllByTrackerPatternID returns every detected tracker linked to the
// pattern, with no pagination. It backs the banner-reset rebuild, which
// recreates exact patterns from a glob's detections.
func (dts *DetectedTrackers) LoadAllByTrackerPatternID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
trackerPatternID gid.GID,
) error {
q := `
SELECT
id,
cookie_banner_id,
tracker_pattern_id,
tracker_type,
identifier,
max_age_seconds,
source,
value_size,
initiator_url,
initiator_domain,
last_detected_at,
created_at,
updated_at
FROM
detected_trackers
WHERE
%s
AND tracker_pattern_id = @tracker_pattern_id
ORDER BY
identifier ASC, id ASC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"tracker_pattern_id": trackerPatternID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query detected trackers: %w", err)
}
trackers, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[DetectedTracker])
if err != nil {
return fmt.Errorf("cannot collect detected trackers: %w", err)
}
*dts = trackers
return nil
}
// UpdateTrackerPatternID repoints a single detected tracker at another
// pattern. It is the per-row counterpart of RelinkByTrackerPatternID,
// used by the banner-reset rebuild where each detection of a glob moves

View File

@@ -377,64 +377,6 @@ SELECT * FROM base WHERE %s
return nil
}
func (p *Documents) LoadAllByOrganizationID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
organizationID gid.GID,
filter *DocumentFilter,
) error {
q := `
WITH latest_versions AS (
SELECT DISTINCT ON (document_id) document_id, title, document_type
FROM document_versions
ORDER BY document_id, major DESC, minor DESC
)
SELECT
documents.id,
documents.organization_id,
documents.current_published_major,
documents.current_published_minor,
documents.write_mode,
documents.trust_center_visibility,
documents.status,
documents.archived_at,
documents.created_at,
documents.updated_at,
COALESCE(lv.title, '') AS title,
COALESCE(lv.document_type, 'OTHER') AS document_type
FROM
documents
LEFT JOIN latest_versions lv ON lv.document_id = documents.id
WHERE
%s
AND documents.deleted_at IS NULL
AND documents.organization_id = @organization_id
AND %s
ORDER BY title ASC
`
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
args := pgx.NamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, filter.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query documents: %w", err)
}
documents, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Document])
if err != nil {
return fmt.Errorf("cannot collect documents: %w", err)
}
*p = documents
return nil
}
func (p *Documents) LoadPublishedByOrganizationID(
ctx context.Context,
conn pg.Querier,

View File

@@ -560,60 +560,6 @@ WHERE
return count, nil
}
func (fs *Findings) LoadAllByOrganizationID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
organizationID gid.GID,
) error {
q := `
SELECT
id,
organization_id,
kind,
reference_id,
description,
source,
identified_on,
root_cause,
corrective_action,
owner_id,
due_date,
status,
priority,
risk_id,
effectiveness_check,
created_at,
updated_at
FROM
findings
WHERE
%s
AND organization_id = @organization_id
ORDER BY
reference_id ASC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query findings: %w", err)
}
findings, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Finding])
if err != nil {
return fmt.Errorf("cannot collect findings: %w", err)
}
*fs = findings
return nil
}
func (f Finding) GetGeneratedDocumentID(
ctx context.Context,
conn pg.Querier,

View File

@@ -344,11 +344,12 @@ WHERE
return count, nil
}
func (cnss *MailingListSubscribers) LoadAllConfirmedByMailingListID(
func (cnss *MailingListSubscribers) LoadConfirmedByMailingListID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
mailingListID gid.GID,
cursor *page.Cursor[MailingListSubscriberOrderField],
) error {
q := `
SELECT
@@ -366,12 +367,14 @@ WHERE
%s
AND mailing_list_id = @mailing_list_id
AND status = 'CONFIRMED'
AND %s
`
q = fmt.Sprintf(q, scope.SQLFragment())
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
args := pgx.StrictNamedArgs{"mailing_list_id": mailingListID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, cursor.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {

View File

@@ -566,118 +566,6 @@ WHERE
return nil
}
func (p *MembershipProfiles) LoadAllByOrganizationID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
organizationID gid.GID,
filter *MembershipProfileFilter,
) error {
q := `
WITH profiles AS (
SELECT
p.id,
p.identity_id,
p.organization_id,
i.email_address,
p.source,
p.state,
p.full_name,
p.kind,
p.additional_email_addresses,
p.position,
p.contract_start_date,
p.contract_end_date,
p.user_name,
p.external_id,
p.nickname,
p.locale,
p.timezone,
p.profile_url,
p.preferred_language,
p.given_name,
p.family_name,
p.formatted_name,
p.middle_name,
p.honorific_prefix,
p.honorific_suffix,
p.employee_number,
p.department,
p.cost_center,
p.enterprise_organization,
p.division,
p.manager_value,
p.created_at,
p.updated_at
FROM
iam_membership_profiles p
INNER JOIN identities i ON i.id = p.identity_id
WHERE
p.%s
AND p.organization_id = @organization_id
AND %s
)
SELECT
id,
identity_id,
organization_id,
email_address,
source,
state,
full_name,
kind,
additional_email_addresses,
position,
contract_start_date,
contract_end_date,
'' AS organization_name,
user_name,
external_id,
nickname,
locale,
timezone,
profile_url,
preferred_language,
given_name,
family_name,
formatted_name,
middle_name,
honorific_prefix,
honorific_suffix,
employee_number,
department,
cost_center,
enterprise_organization,
division,
manager_value,
created_at,
updated_at
FROM profiles
`
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
args := pgx.NamedArgs{
"organization_id": organizationID,
}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, filter.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query profiles: %w", err)
}
profiles, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[MembershipProfile])
if err != nil {
return fmt.Errorf("cannot collect profiles: %w", err)
}
*p = profiles
return nil
}
func (p *MembershipProfiles) LoadByIdentityID(
ctx context.Context,
conn pg.Querier,

View File

@@ -612,57 +612,6 @@ WHERE
return nil
}
func (os *Obligations) LoadAllByOrganizationID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
organizationID gid.GID,
) error {
q := `
SELECT
id,
organization_id,
area,
source,
requirement,
actions_to_be_implemented,
regulator,
owner_profile_id,
last_review_date,
due_date,
status,
type,
created_at,
updated_at
FROM
obligations
WHERE
%s
AND organization_id = @organization_id
ORDER BY
created_at ASC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query obligations: %w", err)
}
obligations, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Obligation])
if err != nil {
return fmt.Errorf("cannot collect obligations: %w", err)
}
*os = obligations
return nil
}
func (o Obligation) GetGeneratedDocumentID(
ctx context.Context,
conn pg.Querier,

View File

@@ -255,11 +255,12 @@ WHERE
return nil
}
func (o *Organizations) LoadAllByIdentityIDWithPendingInvitation(
func (o *Organizations) LoadByIdentityIDWithPendingInvitation(
ctx context.Context,
conn pg.Querier,
scope Scoper,
identityID gid.GID,
cursor *page.Cursor[OrganizationOrderField],
) error {
q := `
WITH invited_org AS (
@@ -292,13 +293,14 @@ INNER JOIN
invited_org ON organizations.id = invited_org.organization_id
WHERE
%s
ORDER BY name ASC
AND %s
`
q = fmt.Sprintf(q, scope.SQLFragment())
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
args := pgx.StrictNamedArgs{"identity_id": identityID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, cursor.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {

View File

@@ -437,65 +437,6 @@ WHERE
return nil
}
func (p *ProcessingActivities) LoadAllByOrganizationID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
organizationID gid.GID,
) error {
q := `
SELECT
id,
organization_id,
name,
purpose,
data_subject_category,
personal_data_category,
special_or_criminal_data,
consent_evidence_link,
lawful_basis,
recipients,
location,
international_transfers,
transfer_safeguards,
retention_period,
security_measures,
data_protection_impact_assessment_needed,
transfer_impact_assessment_needed,
last_review_date,
next_review_date,
role,
dpo_profile_id,
created_at,
updated_at
FROM
processing_activities
WHERE
%s
AND organization_id = @organization_id
ORDER BY created_at DESC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query processing activities: %w", err)
}
processingActivities, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ProcessingActivity])
if err != nil {
return fmt.Errorf("cannot collect processing activities: %w", err)
}
*p = processingActivities
return nil
}
func (p *ProcessingActivity) Insert(
ctx context.Context,
conn pg.Tx,

View File

@@ -464,57 +464,6 @@ WHERE %s
return nil
}
func (r *Risks) LoadAllByOrganizationID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
organizationID gid.GID,
) error {
q := `
SELECT
r.id,
r.organization_id,
r.name,
r.description,
r.category,
r.owner_profile_id,
NULL as owner_full_name,
r.treatment,
r.note,
r.inherent_likelihood,
r.inherent_impact,
r.inherent_risk_score,
r.residual_likelihood,
r.residual_impact,
r.residual_risk_score,
r.created_at,
r.updated_at
FROM
risks r
WHERE %s
AND r.organization_id = @organization_id
ORDER BY r.name ASC, r.id ASC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query risks: %w", err)
}
risks, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Risk])
if err != nil {
return fmt.Errorf("cannot collect risks: %w", err)
}
*r = risks
return nil
}
func (r *Risk) LoadByID(
ctx context.Context,
conn pg.Querier,

View File

@@ -136,48 +136,6 @@ WHERE
return nil
}
func (bs *RiskAssessmentBoundaries) LoadAllByRiskAssessmentScopeID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
riskAssessmentScopeID gid.GID,
) error {
q := `
SELECT
id,
organization_id,
risk_assessment_scope_id,
parent_boundary_id,
name,
created_at,
updated_at
FROM
risk_assessment_boundaries
WHERE
%s
AND risk_assessment_scope_id = @risk_assessment_scope_id
ORDER BY
created_at ASC, id ASC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.NamedArgs{"risk_assessment_scope_id": riskAssessmentScopeID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query risk assessment boundaries: %w", err)
}
results, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[RiskAssessmentBoundary])
if err != nil {
return fmt.Errorf("cannot collect risk assessment boundaries: %w", err)
}
*bs = results
return nil
}
func (bs *RiskAssessmentBoundaries) CountByRiskAssessmentScopeID(
ctx context.Context,
conn pg.Querier,

View File

@@ -138,49 +138,6 @@ WHERE
return nil
}
func (ns *RiskAssessmentNodes) LoadAllByRiskAssessmentScopeID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
riskAssessmentScopeID gid.GID,
) error {
q := `
SELECT
id,
organization_id,
risk_assessment_scope_id,
boundary_id,
node_type,
name,
created_at,
updated_at
FROM
risk_assessment_nodes
WHERE
%s
AND risk_assessment_scope_id = @risk_assessment_scope_id
ORDER BY
created_at ASC, id ASC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.NamedArgs{"risk_assessment_scope_id": riskAssessmentScopeID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query risk assessment nodes: %w", err)
}
results, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[RiskAssessmentNode])
if err != nil {
return fmt.Errorf("cannot collect risk assessment nodes: %w", err)
}
*ns = results
return nil
}
func (ns *RiskAssessmentNodes) CountByRiskAssessmentScopeID(
ctx context.Context,
conn pg.Querier,

View File

@@ -138,49 +138,6 @@ WHERE
return nil
}
func (ps *RiskAssessmentProcesses) LoadAllByRiskAssessmentScopeID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
riskAssessmentScopeID gid.GID,
) error {
q := `
SELECT
id,
organization_id,
risk_assessment_scope_id,
source_node_id,
target_node_id,
name,
created_at,
updated_at
FROM
risk_assessment_processes
WHERE
%s
AND risk_assessment_scope_id = @risk_assessment_scope_id
ORDER BY
created_at ASC, id ASC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.NamedArgs{"risk_assessment_scope_id": riskAssessmentScopeID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query risk assessment processes: %w", err)
}
results, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[RiskAssessmentProcess])
if err != nil {
return fmt.Errorf("cannot collect risk assessment processes: %w", err)
}
*ps = results
return nil
}
func (ps *RiskAssessmentProcesses) CountByRiskAssessmentScopeID(
ctx context.Context,
conn pg.Querier,

View File

@@ -138,49 +138,6 @@ WHERE
return nil
}
func (ts *RiskAssessmentThreats) LoadAllByRiskAssessmentScopeID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
riskAssessmentScopeID gid.GID,
) error {
q := `
SELECT
id,
organization_id,
risk_assessment_scope_id,
process_id,
name,
category,
created_at,
updated_at
FROM
risk_assessment_threats
WHERE
%s
AND risk_assessment_scope_id = @risk_assessment_scope_id
ORDER BY
created_at ASC, id ASC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.NamedArgs{"risk_assessment_scope_id": riskAssessmentScopeID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query risk threats: %w", err)
}
results, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[RiskAssessmentThreat])
if err != nil {
return fmt.Errorf("cannot collect risk threats: %w", err)
}
*ts = results
return nil
}
func (ts *RiskAssessmentThreats) CountByRiskAssessmentScopeID(
ctx context.Context,
conn pg.Querier,

View File

@@ -776,76 +776,6 @@ WHERE
return count, nil
}
func (v *ThirdParties) LoadAllByOrganizationID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
organizationID gid.GID,
filter *ThirdPartyFilter,
) error {
q := `
SELECT
id,
organization_id,
parent_third_party_id,
common_third_party_id,
name,
description,
category,
headquarter_address,
legal_name,
website_url,
privacy_policy_url,
service_level_agreement_url,
data_processing_agreement_url,
business_associate_agreement_url,
subprocessors_list_url,
certifications,
countries,
business_owner_profile_id,
security_owner_profile_id,
status_page_url,
terms_of_service_url,
security_page_url,
trust_page_url,
show_on_trust_center,
level,
vetting_status,
vetting_website_url,
vetting_procedure,
vetting_processing_started_at,
vetting_error_message,
created_at,
updated_at
FROM
third_parties
WHERE
%s
AND organization_id = @organization_id
AND %s
ORDER BY name ASC
`
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
args := pgx.StrictNamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, filter.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query thirdParties: %w", err)
}
thirdParties, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ThirdParty])
if err != nil {
return fmt.Errorf("cannot collect thirdParties: %w", err)
}
*v = thirdParties
return nil
}
func (v *ThirdParties) LoadByOrganizationID(
ctx context.Context,
conn pg.Querier,
@@ -1230,113 +1160,6 @@ WHERE %s
return count, nil
}
func (vs *ThirdParties) LoadAllByDatumID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
datumID gid.GID,
) error {
q := `
WITH vend AS (
SELECT
v.id,
v.tenant_id,
v.organization_id,
v.parent_third_party_id,
v.common_third_party_id,
v.name,
v.description,
v.category,
v.headquarter_address,
v.legal_name,
v.website_url,
v.privacy_policy_url,
v.service_level_agreement_url,
v.data_processing_agreement_url,
v.business_associate_agreement_url,
v.subprocessors_list_url,
v.certifications,
v.countries,
v.business_owner_profile_id,
v.security_owner_profile_id,
v.status_page_url,
v.terms_of_service_url,
v.security_page_url,
v.trust_page_url,
v.show_on_trust_center,
v.level,
v.vetting_status,
v.vetting_website_url,
v.vetting_procedure,
v.vetting_processing_started_at,
v.vetting_error_message,
v.created_at,
v.updated_at
FROM
third_parties v
INNER JOIN
data_third_parties dv ON v.id = dv.third_party_id
WHERE
dv.datum_id = @datum_id
)
SELECT
id,
organization_id,
parent_third_party_id,
common_third_party_id,
name,
description,
category,
headquarter_address,
legal_name,
website_url,
privacy_policy_url,
service_level_agreement_url,
data_processing_agreement_url,
business_associate_agreement_url,
subprocessors_list_url,
certifications,
countries,
business_owner_profile_id,
security_owner_profile_id,
status_page_url,
terms_of_service_url,
security_page_url,
trust_page_url,
show_on_trust_center,
level,
vetting_status,
vetting_website_url,
vetting_procedure,
vetting_processing_started_at,
vetting_error_message,
created_at,
updated_at
FROM
vend
WHERE %s
ORDER BY name ASC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"datum_id": datumID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query thirdParties: %w", err)
}
thirdParties, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ThirdParty])
if err != nil {
return fmt.Errorf("cannot collect thirdParties: %w", err)
}
*vs = thirdParties
return nil
}
func (vs *ThirdParties) LoadByDatumID(
ctx context.Context,
conn pg.Querier,
@@ -1624,113 +1447,6 @@ ORDER BY
return thirdPartyMap, nil
}
func (vs *ThirdParties) LoadAllByAssetID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
assetID gid.GID,
) error {
q := `
WITH vend AS (
SELECT
v.id,
v.tenant_id,
v.organization_id,
v.parent_third_party_id,
v.common_third_party_id,
v.name,
v.description,
v.category,
v.headquarter_address,
v.legal_name,
v.website_url,
v.privacy_policy_url,
v.service_level_agreement_url,
v.data_processing_agreement_url,
v.business_associate_agreement_url,
v.subprocessors_list_url,
v.certifications,
v.countries,
v.business_owner_profile_id,
v.security_owner_profile_id,
v.status_page_url,
v.terms_of_service_url,
v.security_page_url,
v.trust_page_url,
v.show_on_trust_center,
v.level,
v.vetting_status,
v.vetting_website_url,
v.vetting_procedure,
v.vetting_processing_started_at,
v.vetting_error_message,
v.created_at,
v.updated_at
FROM
third_parties v
INNER JOIN
asset_third_parties av ON v.id = av.third_party_id
WHERE
av.asset_id = @asset_id
)
SELECT
id,
organization_id,
parent_third_party_id,
common_third_party_id,
name,
description,
category,
headquarter_address,
legal_name,
website_url,
privacy_policy_url,
service_level_agreement_url,
data_processing_agreement_url,
business_associate_agreement_url,
subprocessors_list_url,
certifications,
countries,
business_owner_profile_id,
security_owner_profile_id,
status_page_url,
terms_of_service_url,
security_page_url,
trust_page_url,
show_on_trust_center,
level,
vetting_status,
vetting_website_url,
vetting_procedure,
vetting_processing_started_at,
vetting_error_message,
created_at,
updated_at
FROM
vend
WHERE %s
ORDER BY name ASC
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"asset_id": assetID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query thirdParties: %w", err)
}
thirdParties, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ThirdParty])
if err != nil {
return fmt.Errorf("cannot collect thirdParties: %w", err)
}
*vs = thirdParties
return nil
}
func (v *ThirdParty) LoadByOrganizationIDAndCommonThirdPartyID(
ctx context.Context,
conn pg.Querier,

View File

@@ -634,75 +634,6 @@ WHERE
return nil
}
func (tps *TrackerPatterns) LoadAllByCookieBannerID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
cookieBannerID gid.GID,
filter *TrackerPatternFilter,
trackerType *TrackerType,
) error {
trackerTypeFragment := "TRUE"
if trackerType != nil {
trackerTypeFragment = "tracker_type = @tracker_type"
}
q := `
SELECT
id,
organization_id,
cookie_banner_id,
cookie_category_id,
common_tracker_pattern_id,
third_party_id,
tracker_type,
pattern,
match_type,
display_name,
description,
excluded,
max_age_seconds,
source,
last_matched_at,
mapping_requested_at,
created_at,
updated_at
FROM
tracker_patterns
WHERE
%s
AND cookie_banner_id = @cookie_banner_id
AND %s
AND %s
ORDER BY
created_at ASC, id ASC;
`
q = fmt.Sprintf(q, scope.SQLFragment(), trackerTypeFragment, filter.SQLFragment())
args := pgx.StrictNamedArgs{"cookie_banner_id": cookieBannerID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, filter.SQLArguments())
if trackerType != nil {
args["tracker_type"] = *trackerType
}
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query tracker patterns: %w", err)
}
patterns, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[TrackerPattern])
if err != nil {
return fmt.Errorf("cannot collect tracker patterns: %w", err)
}
*tps = patterns
return nil
}
func (tps *TrackerPatterns) RefreshLastMatchedAtByCookieBannerID(
ctx context.Context,
tx pg.Tx,

View File

@@ -457,59 +457,6 @@ WHERE
return nil
}
func (trs *TrackerResources) LoadAllByCookieBannerID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
cookieBannerID gid.GID,
filter *TrackerResourceFilter,
) error {
q := `
SELECT
id,
organization_id,
cookie_banner_id,
cookie_category_id,
resource_type,
origin,
path,
display_name,
description,
excluded,
last_detected_at,
created_at,
updated_at
FROM
tracker_resources
WHERE
%s
AND cookie_banner_id = @cookie_banner_id
AND %s
ORDER BY
created_at ASC, id ASC;
`
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
args := pgx.StrictNamedArgs{"cookie_banner_id": cookieBannerID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, filter.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query tracker resources: %w", err)
}
resources, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[TrackerResource])
if err != nil {
return fmt.Errorf("cannot collect tracker resources: %w", err)
}
*trs = resources
return nil
}
func (trs *TrackerResources) LoadUncategorisedByCookieBannerID(
ctx context.Context,
conn pg.Querier,

View File

@@ -283,51 +283,6 @@ WHERE
return nil
}
func (tias *TransferImpactAssessments) LoadAllByOrganizationID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
organizationID gid.GID,
) error {
q := `
SELECT
id,
organization_id,
processing_activity_id,
data_subjects,
legal_mechanism,
transfer,
local_law_risk,
supplementary_measures,
created_at,
updated_at
FROM
processing_activity_transfer_impact_assessments
WHERE
%s
AND organization_id = @organization_id
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query transfer impact assessments: %w", err)
}
results, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[TransferImpactAssessment])
if err != nil {
return fmt.Errorf("cannot collect transfer impact assessments: %w", err)
}
*tias = results
return nil
}
func (tia *TransferImpactAssessment) LoadByID(
ctx context.Context,
conn pg.Querier,

View File

@@ -594,11 +594,12 @@ WHERE %s
return nil
}
func (tcdas *TrustCenterDocumentAccesses) LoadAllByTrustCenterAccessID(
func (tcdas *TrustCenterDocumentAccesses) LoadByTrustCenterAccessID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
trustCenterAccessID gid.GID,
cursor *page.Cursor[TrustCenterDocumentAccessOrderField],
) error {
q := `
SELECT
@@ -616,15 +617,16 @@ FROM
WHERE
%s
AND trust_center_access_id = @trust_center_access_id
ORDER BY id ASC
AND %s
`
q = fmt.Sprintf(q, scope.SQLFragment())
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
args := pgx.StrictNamedArgs{
"trust_center_access_id": trustCenterAccessID,
}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, cursor.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {

View File

@@ -389,51 +389,3 @@ WHERE
return count, nil
}
func (t *TrustCenterFiles) LoadAllByOrganizationID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
organizationID gid.GID,
filter *TrustCenterFileFilter,
) error {
q := `
SELECT
id,
organization_id,
name,
category,
file_id,
trust_center_visibility,
created_at,
updated_at
FROM
trust_center_files
WHERE
%s
AND %s
AND organization_id = @organization_id
ORDER BY
created_at DESC
`
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
args := pgx.StrictNamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, filter.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query trust center files: %w", err)
}
files, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[TrustCenterFile])
if err != nil {
return fmt.Errorf("cannot collect trust center files: %w", err)
}
*t = files
return nil
}