From 6959499d372faea8c2f9b33f18b9c26930f23f09 Mon Sep 17 00:00:00 2001 From: Eli Ribble Date: Wed, 4 Mar 2026 14:58:43 +0000 Subject: [PATCH] Add signal database schema --- db/dberrors/signal.bob.go | 17 + db/dbinfo/signal.bob.go | 207 ++++ db/dbinfo/signal_pool.bob.go | 98 ++ db/enums/enums.bob.go | 167 ++++ db/factory/bobfactory_context.bob.go | 16 + db/factory/bobfactory_main.bob.go | 109 +++ db/factory/bobfactory_random.bob.go | 20 + db/factory/organization.bob.go | 90 +- db/factory/pool.bob.go | 66 ++ db/factory/signal.bob.go | 926 ++++++++++++++++++ db/factory/signal_pool.bob.go | 262 +++++ db/factory/user_.bob.go | 186 +++- db/migrations/00080_signal.sql | 37 + db/models/bob_counts.bob.go | 8 + db/models/bob_joins.bob.go | 4 + db/models/bob_loaders.bob.go | 8 + db/models/bob_where.bob.go | 6 + db/models/organization.bob.go | 254 +++++ db/models/pool.bob.go | 224 ++++- db/models/signal.bob.go | 1356 ++++++++++++++++++++++++++ db/models/signal_pool.bob.go | 478 +++++++++ db/models/user_.bob.go | 511 ++++++++++ 22 files changed, 5039 insertions(+), 11 deletions(-) create mode 100644 db/dberrors/signal.bob.go create mode 100644 db/dbinfo/signal.bob.go create mode 100644 db/dbinfo/signal_pool.bob.go create mode 100644 db/factory/signal.bob.go create mode 100644 db/factory/signal_pool.bob.go create mode 100644 db/migrations/00080_signal.sql create mode 100644 db/models/signal.bob.go create mode 100644 db/models/signal_pool.bob.go diff --git a/db/dberrors/signal.bob.go b/db/dberrors/signal.bob.go new file mode 100644 index 00000000..98c36bd1 --- /dev/null +++ b/db/dberrors/signal.bob.go @@ -0,0 +1,17 @@ +// Code generated by BobGen psql v0.42.5. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package dberrors + +var SignalErrors = &signalErrors{ + ErrUniqueSignalPkey: &UniqueConstraintError{ + schema: "", + table: "signal", + columns: []string{"id"}, + s: "signal_pkey", + }, +} + +type signalErrors struct { + ErrUniqueSignalPkey *UniqueConstraintError +} diff --git a/db/dbinfo/signal.bob.go b/db/dbinfo/signal.bob.go new file mode 100644 index 00000000..c4f3c930 --- /dev/null +++ b/db/dbinfo/signal.bob.go @@ -0,0 +1,207 @@ +// Code generated by BobGen psql v0.42.5. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package dbinfo + +import "github.com/aarondl/opt/null" + +var Signals = Table[ + signalColumns, + signalIndexes, + signalForeignKeys, + signalUniques, + signalChecks, +]{ + Schema: "", + Name: "signal", + Columns: signalColumns{ + Addressed: column{ + Name: "addressed", + DBType: "timestamp without time zone", + Default: "NULL", + Comment: "", + Nullable: true, + Generated: false, + AutoIncr: false, + }, + Addressor: column{ + Name: "addressor", + DBType: "integer", + Default: "NULL", + Comment: "", + Nullable: true, + Generated: false, + AutoIncr: false, + }, + Created: column{ + Name: "created", + DBType: "timestamp without time zone", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + Creator: column{ + Name: "creator", + DBType: "integer", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + ID: column{ + Name: "id", + DBType: "integer", + Default: "nextval('signal_id_seq'::regclass)", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + OrganizationID: column{ + Name: "organization_id", + DBType: "integer", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + Species: column{ + Name: "species", + DBType: "public.mosquitospecies", + Default: "NULL", + Comment: "", + Nullable: true, + Generated: false, + AutoIncr: false, + }, + Title: column{ + Name: "title", + DBType: "text", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + Type: column{ + Name: "type_", + DBType: "public.signaltype", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + }, + Indexes: signalIndexes{ + SignalPkey: index{ + Type: "btree", + Name: "signal_pkey", + Columns: []indexColumn{ + { + Name: "id", + Desc: null.FromCond(false, true), + IsExpression: false, + }, + }, + Unique: true, + Comment: "", + NullsFirst: []bool{false}, + NullsDistinct: false, + Where: "", + Include: []string{}, + }, + }, + PrimaryKey: &constraint{ + Name: "signal_pkey", + Columns: []string{"id"}, + Comment: "", + }, + ForeignKeys: signalForeignKeys{ + SignalSignalAddressorFkey: foreignKey{ + constraint: constraint{ + Name: "signal.signal_addressor_fkey", + Columns: []string{"addressor"}, + Comment: "", + }, + ForeignTable: "user_", + ForeignColumns: []string{"id"}, + }, + SignalSignalCreatorFkey: foreignKey{ + constraint: constraint{ + Name: "signal.signal_creator_fkey", + Columns: []string{"creator"}, + Comment: "", + }, + ForeignTable: "user_", + ForeignColumns: []string{"id"}, + }, + SignalSignalOrganizationIDFkey: foreignKey{ + constraint: constraint{ + Name: "signal.signal_organization_id_fkey", + Columns: []string{"organization_id"}, + Comment: "", + }, + ForeignTable: "organization", + ForeignColumns: []string{"id"}, + }, + }, + + Comment: "", +} + +type signalColumns struct { + Addressed column + Addressor column + Created column + Creator column + ID column + OrganizationID column + Species column + Title column + Type column +} + +func (c signalColumns) AsSlice() []column { + return []column{ + c.Addressed, c.Addressor, c.Created, c.Creator, c.ID, c.OrganizationID, c.Species, c.Title, c.Type, + } +} + +type signalIndexes struct { + SignalPkey index +} + +func (i signalIndexes) AsSlice() []index { + return []index{ + i.SignalPkey, + } +} + +type signalForeignKeys struct { + SignalSignalAddressorFkey foreignKey + SignalSignalCreatorFkey foreignKey + SignalSignalOrganizationIDFkey foreignKey +} + +func (f signalForeignKeys) AsSlice() []foreignKey { + return []foreignKey{ + f.SignalSignalAddressorFkey, f.SignalSignalCreatorFkey, f.SignalSignalOrganizationIDFkey, + } +} + +type signalUniques struct{} + +func (u signalUniques) AsSlice() []constraint { + return []constraint{} +} + +type signalChecks struct{} + +func (c signalChecks) AsSlice() []check { + return []check{} +} diff --git a/db/dbinfo/signal_pool.bob.go b/db/dbinfo/signal_pool.bob.go new file mode 100644 index 00000000..29965619 --- /dev/null +++ b/db/dbinfo/signal_pool.bob.go @@ -0,0 +1,98 @@ +// Code generated by BobGen psql v0.42.5. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package dbinfo + +var SignalPools = Table[ + signalPoolColumns, + signalPoolIndexes, + signalPoolForeignKeys, + signalPoolUniques, + signalPoolChecks, +]{ + Schema: "", + Name: "signal_pool", + Columns: signalPoolColumns{ + PoolID: column{ + Name: "pool_id", + DBType: "integer", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + SignalID: column{ + Name: "signal_id", + DBType: "integer", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + }, + + ForeignKeys: signalPoolForeignKeys{ + SignalPoolSignalPoolPoolIDFkey: foreignKey{ + constraint: constraint{ + Name: "signal_pool.signal_pool_pool_id_fkey", + Columns: []string{"pool_id"}, + Comment: "", + }, + ForeignTable: "pool", + ForeignColumns: []string{"id"}, + }, + SignalPoolSignalPoolSignalIDFkey: foreignKey{ + constraint: constraint{ + Name: "signal_pool.signal_pool_signal_id_fkey", + Columns: []string{"signal_id"}, + Comment: "", + }, + ForeignTable: "signal", + ForeignColumns: []string{"id"}, + }, + }, + + Comment: "", +} + +type signalPoolColumns struct { + PoolID column + SignalID column +} + +func (c signalPoolColumns) AsSlice() []column { + return []column{ + c.PoolID, c.SignalID, + } +} + +type signalPoolIndexes struct{} + +func (i signalPoolIndexes) AsSlice() []index { + return []index{} +} + +type signalPoolForeignKeys struct { + SignalPoolSignalPoolPoolIDFkey foreignKey + SignalPoolSignalPoolSignalIDFkey foreignKey +} + +func (f signalPoolForeignKeys) AsSlice() []foreignKey { + return []foreignKey{ + f.SignalPoolSignalPoolPoolIDFkey, f.SignalPoolSignalPoolSignalIDFkey, + } +} + +type signalPoolUniques struct{} + +func (u signalPoolUniques) AsSlice() []constraint { + return []constraint{} +} + +type signalPoolChecks struct{} + +func (c signalPoolChecks) AsSlice() []check { + return []check{} +} diff --git a/db/enums/enums.bob.go b/db/enums/enums.bob.go index 5598ff8e..4904755e 100644 --- a/db/enums/enums.bob.go +++ b/db/enums/enums.bob.go @@ -1371,6 +1371,85 @@ func (e *Imagedatatype) Scan(value any) error { return nil } +// Enum values for Mosquitospecies +const ( + MosquitospeciesAedesAegypti Mosquitospecies = "aedes aegypti" + MosquitospeciesAedesAlbopictus Mosquitospecies = "aedes albopictus" + MosquitospeciesCulexPipiens Mosquitospecies = "culex pipiens" + MosquitospeciesCulexTarsalis Mosquitospecies = "culex tarsalis" +) + +func AllMosquitospecies() []Mosquitospecies { + return []Mosquitospecies{ + MosquitospeciesAedesAegypti, + MosquitospeciesAedesAlbopictus, + MosquitospeciesCulexPipiens, + MosquitospeciesCulexTarsalis, + } +} + +type Mosquitospecies string + +func (e Mosquitospecies) String() string { + return string(e) +} + +func (e Mosquitospecies) Valid() bool { + switch e { + case MosquitospeciesAedesAegypti, + MosquitospeciesAedesAlbopictus, + MosquitospeciesCulexPipiens, + MosquitospeciesCulexTarsalis: + return true + default: + return false + } +} + +// useful when testing in other packages +func (e Mosquitospecies) All() []Mosquitospecies { + return AllMosquitospecies() +} + +func (e Mosquitospecies) MarshalText() ([]byte, error) { + return []byte(e), nil +} + +func (e *Mosquitospecies) UnmarshalText(text []byte) error { + return e.Scan(text) +} + +func (e Mosquitospecies) MarshalBinary() ([]byte, error) { + return []byte(e), nil +} + +func (e *Mosquitospecies) UnmarshalBinary(data []byte) error { + return e.Scan(data) +} + +func (e Mosquitospecies) Value() (driver.Value, error) { + return string(e), nil +} + +func (e *Mosquitospecies) Scan(value any) error { + switch x := value.(type) { + case string: + *e = Mosquitospecies(x) + case []byte: + *e = Mosquitospecies(x) + case nil: + return fmt.Errorf("cannot nil into Mosquitospecies") + default: + return fmt.Errorf("cannot scan type %T: %v", value, value) + } + + if !e.Valid() { + return fmt.Errorf("invalid Mosquitospecies value: %s", *e) + } + + return nil +} + // Enum values for Notificationtype const ( NotificationtypeOauthTokenInvalidated Notificationtype = "oauth_token_invalidated" @@ -1866,6 +1945,94 @@ func (e *PublicreportReportstatustype) Scan(value any) error { return nil } +// Enum values for Signaltype +const ( + SignaltypeFlyoverU2epool Signaltype = "flyover.pool" + SignaltypePlanU2efollowup Signaltype = "plan.followup" + SignaltypePublicreportU2ewater Signaltype = "publicreport.water" + SignaltypePublicreportU2enuisance Signaltype = "publicreport.nuisance" + SignaltypeResidualU2eexiring Signaltype = "residual.exiring" + SignaltypeSurveillanceU2eobservation Signaltype = "surveillance.observation" + SignaltypeTrapU2espike Signaltype = "trap.spike" +) + +func AllSignaltype() []Signaltype { + return []Signaltype{ + SignaltypeFlyoverU2epool, + SignaltypePlanU2efollowup, + SignaltypePublicreportU2ewater, + SignaltypePublicreportU2enuisance, + SignaltypeResidualU2eexiring, + SignaltypeSurveillanceU2eobservation, + SignaltypeTrapU2espike, + } +} + +type Signaltype string + +func (e Signaltype) String() string { + return string(e) +} + +func (e Signaltype) Valid() bool { + switch e { + case SignaltypeFlyoverU2epool, + SignaltypePlanU2efollowup, + SignaltypePublicreportU2ewater, + SignaltypePublicreportU2enuisance, + SignaltypeResidualU2eexiring, + SignaltypeSurveillanceU2eobservation, + SignaltypeTrapU2espike: + return true + default: + return false + } +} + +// useful when testing in other packages +func (e Signaltype) All() []Signaltype { + return AllSignaltype() +} + +func (e Signaltype) MarshalText() ([]byte, error) { + return []byte(e), nil +} + +func (e *Signaltype) UnmarshalText(text []byte) error { + return e.Scan(text) +} + +func (e Signaltype) MarshalBinary() ([]byte, error) { + return []byte(e), nil +} + +func (e *Signaltype) UnmarshalBinary(data []byte) error { + return e.Scan(data) +} + +func (e Signaltype) Value() (driver.Value, error) { + return string(e), nil +} + +func (e *Signaltype) Scan(value any) error { + switch x := value.(type) { + case string: + *e = Signaltype(x) + case []byte: + *e = Signaltype(x) + case nil: + return fmt.Errorf("cannot nil into Signaltype") + default: + return fmt.Errorf("cannot scan type %T: %v", value, value) + } + + if !e.Valid() { + return fmt.Errorf("invalid Signaltype value: %s", *e) + } + + return nil +} + // Enum values for Userrole const ( UserroleRoot Userrole = "root" diff --git a/db/factory/bobfactory_context.bob.go b/db/factory/bobfactory_context.bob.go index ef3f92ab..807cf9a4 100644 --- a/db/factory/bobfactory_context.bob.go +++ b/db/factory/bobfactory_context.bob.go @@ -368,6 +368,7 @@ var ( organizationRelNuisancesCtx = newContextual[bool]("organization.publicreport.nuisance.publicreport.nuisance.nuisance_organization_id_fkey") organizationRelPublicreportPoolCtx = newContextual[bool]("organization.publicreport.pool.publicreport.pool.pool_organization_id_fkey") organizationRelQuicksCtx = newContextual[bool]("organization.publicreport.quick.publicreport.quick.quick_organization_id_fkey") + organizationRelSignalsCtx = newContextual[bool]("organization.signal.signal.signal_organization_id_fkey") organizationRelUserCtx = newContextual[bool]("organization.user_.user_.user__organization_id_fkey") // Relationship Contexts for parcel @@ -378,6 +379,7 @@ var ( poolWithParentsCascadingCtx = newContextual[bool]("poolWithParentsCascading") poolRelCreatorUserCtx = newContextual[bool]("pool.user_.pool.pool_creator_id_fkey") poolRelSiteCtx = newContextual[bool]("pool.site.pool.pool_site_id_site_version_fkey") + poolRelSignalPoolsCtx = newContextual[bool]("pool.signal_pool.signal_pool.signal_pool_pool_id_fkey") // Relationship Contexts for publicreport.image publicreportImageWithParentsCascadingCtx = newContextual[bool]("publicreportImageWithParentsCascading") @@ -471,6 +473,18 @@ var ( // Relationship Contexts for sessions sessionWithParentsCascadingCtx = newContextual[bool]("sessionWithParentsCascading") + // Relationship Contexts for signal + signalWithParentsCascadingCtx = newContextual[bool]("signalWithParentsCascading") + signalRelAddressorUserCtx = newContextual[bool]("signal.user_.signal.signal_addressor_fkey") + signalRelCreatorUserCtx = newContextual[bool]("signal.user_.signal.signal_creator_fkey") + signalRelOrganizationCtx = newContextual[bool]("organization.signal.signal.signal_organization_id_fkey") + signalRelSignalPoolsCtx = newContextual[bool]("signal.signal_pool.signal_pool.signal_pool_signal_id_fkey") + + // Relationship Contexts for signal_pool + signalPoolWithParentsCascadingCtx = newContextual[bool]("signalPoolWithParentsCascading") + signalPoolRelPoolCtx = newContextual[bool]("pool.signal_pool.signal_pool.signal_pool_pool_id_fkey") + signalPoolRelSignalCtx = newContextual[bool]("signal.signal_pool.signal_pool.signal_pool_signal_id_fkey") + // Relationship Contexts for site siteWithParentsCascadingCtx = newContextual[bool]("siteWithParentsCascading") siteRelComplianceReportRequestsCtx = newContextual[bool]("compliance_report_request.site.compliance_report_request.compliance_report_request_site_id_site_version_fkey") @@ -498,6 +512,8 @@ var ( userRelUserNotificationsCtx = newContextual[bool]("notification.user_.notification.notification_user_id_fkey") userRelCreatorPoolsCtx = newContextual[bool]("pool.user_.pool.pool_creator_id_fkey") userRelCreatorResidentsCtx = newContextual[bool]("resident.user_.resident.resident_creator_fkey") + userRelAddressorSignalsCtx = newContextual[bool]("signal.user_.signal.signal_addressor_fkey") + userRelCreatorSignalsCtx = newContextual[bool]("signal.user_.signal.signal_creator_fkey") userRelCreatorSitesCtx = newContextual[bool]("site.user_.site.site_creator_id_fkey") userRelOrganizationCtx = newContextual[bool]("organization.user_.user_.user__organization_id_fkey") ) diff --git a/db/factory/bobfactory_main.bob.go b/db/factory/bobfactory_main.bob.go index ef330ee9..2a1e958b 100644 --- a/db/factory/bobfactory_main.bob.go +++ b/db/factory/bobfactory_main.bob.go @@ -107,6 +107,8 @@ type Factory struct { baseRasterOverviewMods RasterOverviewModSlice baseResidentMods ResidentModSlice baseSessionMods SessionModSlice + baseSignalMods SignalModSlice + baseSignalPoolMods SignalPoolModSlice baseSiteMods SiteModSlice baseSpatialRefSyMods SpatialRefSyModSlice baseUserMods UserModSlice @@ -3510,6 +3512,9 @@ func (f *Factory) FromExistingOrganization(m *models.Organization) *Organization if len(m.R.Quicks) > 0 { OrganizationMods.AddExistingQuicks(m.R.Quicks...).Apply(ctx, o) } + if len(m.R.Signals) > 0 { + OrganizationMods.AddExistingSignals(m.R.Signals...).Apply(ctx, o) + } if len(m.R.User) > 0 { OrganizationMods.AddExistingUser(m.R.User...).Apply(ctx, o) } @@ -3582,6 +3587,9 @@ func (f *Factory) FromExistingPool(m *models.Pool) *PoolTemplate { if m.R.Site != nil { PoolMods.WithExistingSite(m.R.Site).Apply(ctx, o) } + if len(m.R.SignalPools) > 0 { + PoolMods.AddExistingSignalPools(m.R.SignalPools...).Apply(ctx, o) + } return o } @@ -4324,6 +4332,85 @@ func (f *Factory) FromExistingSession(m *models.Session) *SessionTemplate { return o } +func (f *Factory) NewSignal(mods ...SignalMod) *SignalTemplate { + return f.NewSignalWithContext(context.Background(), mods...) +} + +func (f *Factory) NewSignalWithContext(ctx context.Context, mods ...SignalMod) *SignalTemplate { + o := &SignalTemplate{f: f} + + if f != nil { + f.baseSignalMods.Apply(ctx, o) + } + + SignalModSlice(mods).Apply(ctx, o) + + return o +} + +func (f *Factory) FromExistingSignal(m *models.Signal) *SignalTemplate { + o := &SignalTemplate{f: f, alreadyPersisted: true} + + o.Addressed = func() null.Val[time.Time] { return m.Addressed } + o.Addressor = func() null.Val[int32] { return m.Addressor } + o.Created = func() time.Time { return m.Created } + o.Creator = func() int32 { return m.Creator } + o.ID = func() int32 { return m.ID } + o.OrganizationID = func() int32 { return m.OrganizationID } + o.Species = func() null.Val[enums.Mosquitospecies] { return m.Species } + o.Title = func() string { return m.Title } + o.Type = func() enums.Signaltype { return m.Type } + + ctx := context.Background() + if m.R.AddressorUser != nil { + SignalMods.WithExistingAddressorUser(m.R.AddressorUser).Apply(ctx, o) + } + if m.R.CreatorUser != nil { + SignalMods.WithExistingCreatorUser(m.R.CreatorUser).Apply(ctx, o) + } + if m.R.Organization != nil { + SignalMods.WithExistingOrganization(m.R.Organization).Apply(ctx, o) + } + if len(m.R.SignalPools) > 0 { + SignalMods.AddExistingSignalPools(m.R.SignalPools...).Apply(ctx, o) + } + + return o +} + +func (f *Factory) NewSignalPool(mods ...SignalPoolMod) *SignalPoolTemplate { + return f.NewSignalPoolWithContext(context.Background(), mods...) +} + +func (f *Factory) NewSignalPoolWithContext(ctx context.Context, mods ...SignalPoolMod) *SignalPoolTemplate { + o := &SignalPoolTemplate{f: f} + + if f != nil { + f.baseSignalPoolMods.Apply(ctx, o) + } + + SignalPoolModSlice(mods).Apply(ctx, o) + + return o +} + +func (f *Factory) FromExistingSignalPool(m *models.SignalPool) *SignalPoolTemplate { + o := &SignalPoolTemplate{f: f, alreadyPersisted: true} + + o.PoolID = func() int32 { return m.PoolID } + o.SignalID = func() int32 { return m.SignalID } + + ctx := context.Background() + if m.R.Pool != nil { + SignalPoolMods.WithExistingPool(m.R.Pool).Apply(ctx, o) + } + if m.R.Signal != nil { + SignalPoolMods.WithExistingSignal(m.R.Signal).Apply(ctx, o) + } + + return o +} + func (f *Factory) NewSite(mods ...SiteMod) *SiteTemplate { return f.NewSiteWithContext(context.Background(), mods...) } @@ -4481,6 +4568,12 @@ func (f *Factory) FromExistingUser(m *models.User) *UserTemplate { if len(m.R.CreatorResidents) > 0 { UserMods.AddExistingCreatorResidents(m.R.CreatorResidents...).Apply(ctx, o) } + if len(m.R.AddressorSignals) > 0 { + UserMods.AddExistingAddressorSignals(m.R.AddressorSignals...).Apply(ctx, o) + } + if len(m.R.CreatorSignals) > 0 { + UserMods.AddExistingCreatorSignals(m.R.CreatorSignals...).Apply(ctx, o) + } if len(m.R.CreatorSites) > 0 { UserMods.AddExistingCreatorSites(m.R.CreatorSites...).Apply(ctx, o) } @@ -5195,6 +5288,22 @@ func (f *Factory) AddBaseSessionMod(mods ...SessionMod) { f.baseSessionMods = append(f.baseSessionMods, mods...) } +func (f *Factory) ClearBaseSignalMods() { + f.baseSignalMods = nil +} + +func (f *Factory) AddBaseSignalMod(mods ...SignalMod) { + f.baseSignalMods = append(f.baseSignalMods, mods...) +} + +func (f *Factory) ClearBaseSignalPoolMods() { + f.baseSignalPoolMods = nil +} + +func (f *Factory) AddBaseSignalPoolMod(mods ...SignalPoolMod) { + f.baseSignalPoolMods = append(f.baseSignalPoolMods, mods...) +} + func (f *Factory) ClearBaseSiteMods() { f.baseSiteMods = nil } diff --git a/db/factory/bobfactory_random.bob.go b/db/factory/bobfactory_random.bob.go index 427dbbe6..5e240e29 100644 --- a/db/factory/bobfactory_random.bob.go +++ b/db/factory/bobfactory_random.bob.go @@ -231,6 +231,16 @@ func random_enums_Hashtype(f *faker.Faker, limits ...string) enums.Hashtype { return all[f.IntBetween(0, len(all)-1)] } +func random_enums_Mosquitospecies(f *faker.Faker, limits ...string) enums.Mosquitospecies { + if f == nil { + f = &defaultFaker + } + + var e enums.Mosquitospecies + all := e.All() + return all[f.IntBetween(0, len(all)-1)] +} + func random_enums_Notificationtype(f *faker.Faker, limits ...string) enums.Notificationtype { if f == nil { f = &defaultFaker @@ -281,6 +291,16 @@ func random_enums_PublicreportReportstatustype(f *faker.Faker, limits ...string) return all[f.IntBetween(0, len(all)-1)] } +func random_enums_Signaltype(f *faker.Faker, limits ...string) enums.Signaltype { + if f == nil { + f = &defaultFaker + } + + var e enums.Signaltype + all := e.All() + return all[f.IntBetween(0, len(all)-1)] +} + func random_enums_Userrole(f *faker.Faker, limits ...string) enums.Userrole { if f == nil { f = &defaultFaker diff --git a/db/factory/organization.bob.go b/db/factory/organization.bob.go index e92fc48f..62b701df 100644 --- a/db/factory/organization.bob.go +++ b/db/factory/organization.bob.go @@ -121,6 +121,7 @@ type organizationR struct { Nuisances []*organizationRNuisancesR PublicreportPool []*organizationRPublicreportPoolR Quicks []*organizationRQuicksR + Signals []*organizationRSignalsR User []*organizationRUserR } @@ -294,6 +295,10 @@ type organizationRQuicksR struct { number int o *PublicreportQuickTemplate } +type organizationRSignalsR struct { + number int + o *SignalTemplate +} type organizationRUserR struct { number int o *UserTemplate @@ -854,6 +859,19 @@ func (t OrganizationTemplate) setModelRels(o *models.Organization) { o.R.Quicks = rel } + if t.r.Signals != nil { + rel := models.SignalSlice{} + for _, r := range t.r.Signals { + related := r.o.BuildMany(r.number) + for _, rel := range related { + rel.OrganizationID = o.ID // h2 + rel.R.Organization = o + } + rel = append(rel, related...) + } + o.R.Signals = rel + } + if t.r.User != nil { rel := models.UserSlice{} for _, r := range t.r.User { @@ -1969,6 +1987,26 @@ func (o *OrganizationTemplate) insertOptRels(ctx context.Context, exec bob.Execu } } + isSignalsDone, _ := organizationRelSignalsCtx.Value(ctx) + if !isSignalsDone && o.r.Signals != nil { + ctx = organizationRelSignalsCtx.WithValue(ctx, true) + for _, r := range o.r.Signals { + if r.o.alreadyPersisted { + m.R.Signals = append(m.R.Signals, r.o.Build()) + } else { + rel43, err := r.o.CreateMany(ctx, exec, r.number) + if err != nil { + return err + } + + err = m.AttachSignals(ctx, exec, rel43...) + if err != nil { + return err + } + } + } + } + isUserDone, _ := organizationRelUserCtx.Value(ctx) if !isUserDone && o.r.User != nil { ctx = organizationRelUserCtx.WithValue(ctx, true) @@ -1976,12 +2014,12 @@ func (o *OrganizationTemplate) insertOptRels(ctx context.Context, exec bob.Execu if r.o.alreadyPersisted { m.R.User = append(m.R.User, r.o.Build()) } else { - rel43, err := r.o.CreateMany(ctx, exec, r.number) + rel44, err := r.o.CreateMany(ctx, exec, r.number) if err != nil { return err } - err = m.AttachUser(ctx, exec, rel43...) + err = m.AttachUser(ctx, exec, rel44...) if err != nil { return err } @@ -5815,6 +5853,54 @@ func (m organizationMods) WithoutQuicks() OrganizationMod { }) } +func (m organizationMods) WithSignals(number int, related *SignalTemplate) OrganizationMod { + return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) { + o.r.Signals = []*organizationRSignalsR{{ + number: number, + o: related, + }} + }) +} + +func (m organizationMods) WithNewSignals(number int, mods ...SignalMod) OrganizationMod { + return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) { + related := o.f.NewSignalWithContext(ctx, mods...) + m.WithSignals(number, related).Apply(ctx, o) + }) +} + +func (m organizationMods) AddSignals(number int, related *SignalTemplate) OrganizationMod { + return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) { + o.r.Signals = append(o.r.Signals, &organizationRSignalsR{ + number: number, + o: related, + }) + }) +} + +func (m organizationMods) AddNewSignals(number int, mods ...SignalMod) OrganizationMod { + return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) { + related := o.f.NewSignalWithContext(ctx, mods...) + m.AddSignals(number, related).Apply(ctx, o) + }) +} + +func (m organizationMods) AddExistingSignals(existingModels ...*models.Signal) OrganizationMod { + return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) { + for _, em := range existingModels { + o.r.Signals = append(o.r.Signals, &organizationRSignalsR{ + o: o.f.FromExistingSignal(em), + }) + } + }) +} + +func (m organizationMods) WithoutSignals() OrganizationMod { + return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) { + o.r.Signals = nil + }) +} + func (m organizationMods) WithUser(number int, related *UserTemplate) OrganizationMod { return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) { o.r.User = []*organizationRUserR{{ diff --git a/db/factory/pool.bob.go b/db/factory/pool.bob.go index 07c5ad91..6608e2c2 100644 --- a/db/factory/pool.bob.go +++ b/db/factory/pool.bob.go @@ -52,6 +52,7 @@ type PoolTemplate struct { type poolR struct { CreatorUser *poolRCreatorUserR Site *poolRSiteR + SignalPools []*poolRSignalPoolsR } type poolRCreatorUserR struct { @@ -60,6 +61,10 @@ type poolRCreatorUserR struct { type poolRSiteR struct { o *SiteTemplate } +type poolRSignalPoolsR struct { + number int + o *SignalPoolTemplate +} // Apply mods to the PoolTemplate func (o *PoolTemplate) Apply(ctx context.Context, mods ...PoolMod) { @@ -85,6 +90,19 @@ func (t PoolTemplate) setModelRels(o *models.Pool) { o.SiteVersion = rel.Version // h2 o.R.Site = rel } + + if t.r.SignalPools != nil { + rel := models.SignalPoolSlice{} + for _, r := range t.r.SignalPools { + related := r.o.BuildMany(r.number) + for _, rel := range related { + rel.PoolID = o.ID // h2 + rel.R.Pool = o + } + rel = append(rel, related...) + } + o.R.SignalPools = rel + } } // BuildSetter returns an *models.PoolSetter @@ -607,3 +625,51 @@ func (m poolMods) WithoutSite() PoolMod { o.r.Site = nil }) } + +func (m poolMods) WithSignalPools(number int, related *SignalPoolTemplate) PoolMod { + return PoolModFunc(func(ctx context.Context, o *PoolTemplate) { + o.r.SignalPools = []*poolRSignalPoolsR{{ + number: number, + o: related, + }} + }) +} + +func (m poolMods) WithNewSignalPools(number int, mods ...SignalPoolMod) PoolMod { + return PoolModFunc(func(ctx context.Context, o *PoolTemplate) { + related := o.f.NewSignalPoolWithContext(ctx, mods...) + m.WithSignalPools(number, related).Apply(ctx, o) + }) +} + +func (m poolMods) AddSignalPools(number int, related *SignalPoolTemplate) PoolMod { + return PoolModFunc(func(ctx context.Context, o *PoolTemplate) { + o.r.SignalPools = append(o.r.SignalPools, &poolRSignalPoolsR{ + number: number, + o: related, + }) + }) +} + +func (m poolMods) AddNewSignalPools(number int, mods ...SignalPoolMod) PoolMod { + return PoolModFunc(func(ctx context.Context, o *PoolTemplate) { + related := o.f.NewSignalPoolWithContext(ctx, mods...) + m.AddSignalPools(number, related).Apply(ctx, o) + }) +} + +func (m poolMods) AddExistingSignalPools(existingModels ...*models.SignalPool) PoolMod { + return PoolModFunc(func(ctx context.Context, o *PoolTemplate) { + for _, em := range existingModels { + o.r.SignalPools = append(o.r.SignalPools, &poolRSignalPoolsR{ + o: o.f.FromExistingSignalPool(em), + }) + } + }) +} + +func (m poolMods) WithoutSignalPools() PoolMod { + return PoolModFunc(func(ctx context.Context, o *PoolTemplate) { + o.r.SignalPools = nil + }) +} diff --git a/db/factory/signal.bob.go b/db/factory/signal.bob.go new file mode 100644 index 00000000..16befe7e --- /dev/null +++ b/db/factory/signal.bob.go @@ -0,0 +1,926 @@ +// Code generated by BobGen psql v0.42.5. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package factory + +import ( + "context" + "testing" + "time" + + "github.com/Gleipnir-Technology/bob" + enums "github.com/Gleipnir-Technology/nidus-sync/db/enums" + models "github.com/Gleipnir-Technology/nidus-sync/db/models" + "github.com/aarondl/opt/null" + "github.com/aarondl/opt/omit" + "github.com/aarondl/opt/omitnull" + "github.com/jaswdr/faker/v2" +) + +type SignalMod interface { + Apply(context.Context, *SignalTemplate) +} + +type SignalModFunc func(context.Context, *SignalTemplate) + +func (f SignalModFunc) Apply(ctx context.Context, n *SignalTemplate) { + f(ctx, n) +} + +type SignalModSlice []SignalMod + +func (mods SignalModSlice) Apply(ctx context.Context, n *SignalTemplate) { + for _, f := range mods { + f.Apply(ctx, n) + } +} + +// SignalTemplate is an object representing the database table. +// all columns are optional and should be set by mods +type SignalTemplate struct { + Addressed func() null.Val[time.Time] + Addressor func() null.Val[int32] + Created func() time.Time + Creator func() int32 + ID func() int32 + OrganizationID func() int32 + Species func() null.Val[enums.Mosquitospecies] + Title func() string + Type func() enums.Signaltype + + r signalR + f *Factory + + alreadyPersisted bool +} + +type signalR struct { + AddressorUser *signalRAddressorUserR + CreatorUser *signalRCreatorUserR + Organization *signalROrganizationR + SignalPools []*signalRSignalPoolsR +} + +type signalRAddressorUserR struct { + o *UserTemplate +} +type signalRCreatorUserR struct { + o *UserTemplate +} +type signalROrganizationR struct { + o *OrganizationTemplate +} +type signalRSignalPoolsR struct { + number int + o *SignalPoolTemplate +} + +// Apply mods to the SignalTemplate +func (o *SignalTemplate) Apply(ctx context.Context, mods ...SignalMod) { + for _, mod := range mods { + mod.Apply(ctx, o) + } +} + +// setModelRels creates and sets the relationships on *models.Signal +// according to the relationships in the template. Nothing is inserted into the db +func (t SignalTemplate) setModelRels(o *models.Signal) { + if t.r.AddressorUser != nil { + rel := t.r.AddressorUser.o.Build() + rel.R.AddressorSignals = append(rel.R.AddressorSignals, o) + o.Addressor = null.From(rel.ID) // h2 + o.R.AddressorUser = rel + } + + if t.r.CreatorUser != nil { + rel := t.r.CreatorUser.o.Build() + rel.R.CreatorSignals = append(rel.R.CreatorSignals, o) + o.Creator = rel.ID // h2 + o.R.CreatorUser = rel + } + + if t.r.Organization != nil { + rel := t.r.Organization.o.Build() + rel.R.Signals = append(rel.R.Signals, o) + o.OrganizationID = rel.ID // h2 + o.R.Organization = rel + } + + if t.r.SignalPools != nil { + rel := models.SignalPoolSlice{} + for _, r := range t.r.SignalPools { + related := r.o.BuildMany(r.number) + for _, rel := range related { + rel.SignalID = o.ID // h2 + rel.R.Signal = o + } + rel = append(rel, related...) + } + o.R.SignalPools = rel + } +} + +// BuildSetter returns an *models.SignalSetter +// this does nothing with the relationship templates +func (o SignalTemplate) BuildSetter() *models.SignalSetter { + m := &models.SignalSetter{} + + if o.Addressed != nil { + val := o.Addressed() + m.Addressed = omitnull.FromNull(val) + } + if o.Addressor != nil { + val := o.Addressor() + m.Addressor = omitnull.FromNull(val) + } + if o.Created != nil { + val := o.Created() + m.Created = omit.From(val) + } + if o.Creator != nil { + val := o.Creator() + m.Creator = omit.From(val) + } + if o.ID != nil { + val := o.ID() + m.ID = omit.From(val) + } + if o.OrganizationID != nil { + val := o.OrganizationID() + m.OrganizationID = omit.From(val) + } + if o.Species != nil { + val := o.Species() + m.Species = omitnull.FromNull(val) + } + if o.Title != nil { + val := o.Title() + m.Title = omit.From(val) + } + if o.Type != nil { + val := o.Type() + m.Type = omit.From(val) + } + + return m +} + +// BuildManySetter returns an []*models.SignalSetter +// this does nothing with the relationship templates +func (o SignalTemplate) BuildManySetter(number int) []*models.SignalSetter { + m := make([]*models.SignalSetter, number) + + for i := range m { + m[i] = o.BuildSetter() + } + + return m +} + +// Build returns an *models.Signal +// Related objects are also created and placed in the .R field +// NOTE: Objects are not inserted into the database. Use SignalTemplate.Create +func (o SignalTemplate) Build() *models.Signal { + m := &models.Signal{} + + if o.Addressed != nil { + m.Addressed = o.Addressed() + } + if o.Addressor != nil { + m.Addressor = o.Addressor() + } + if o.Created != nil { + m.Created = o.Created() + } + if o.Creator != nil { + m.Creator = o.Creator() + } + if o.ID != nil { + m.ID = o.ID() + } + if o.OrganizationID != nil { + m.OrganizationID = o.OrganizationID() + } + if o.Species != nil { + m.Species = o.Species() + } + if o.Title != nil { + m.Title = o.Title() + } + if o.Type != nil { + m.Type = o.Type() + } + + o.setModelRels(m) + + return m +} + +// BuildMany returns an models.SignalSlice +// Related objects are also created and placed in the .R field +// NOTE: Objects are not inserted into the database. Use SignalTemplate.CreateMany +func (o SignalTemplate) BuildMany(number int) models.SignalSlice { + m := make(models.SignalSlice, number) + + for i := range m { + m[i] = o.Build() + } + + return m +} + +func ensureCreatableSignal(m *models.SignalSetter) { + if !(m.Created.IsValue()) { + val := random_time_Time(nil) + m.Created = omit.From(val) + } + if !(m.Creator.IsValue()) { + val := random_int32(nil) + m.Creator = omit.From(val) + } + if !(m.OrganizationID.IsValue()) { + val := random_int32(nil) + m.OrganizationID = omit.From(val) + } + if !(m.Title.IsValue()) { + val := random_string(nil) + m.Title = omit.From(val) + } + if !(m.Type.IsValue()) { + val := random_enums_Signaltype(nil) + m.Type = omit.From(val) + } +} + +// insertOptRels creates and inserts any optional the relationships on *models.Signal +// according to the relationships in the template. +// any required relationship should have already exist on the model +func (o *SignalTemplate) insertOptRels(ctx context.Context, exec bob.Executor, m *models.Signal) error { + var err error + + isAddressorUserDone, _ := signalRelAddressorUserCtx.Value(ctx) + if !isAddressorUserDone && o.r.AddressorUser != nil { + ctx = signalRelAddressorUserCtx.WithValue(ctx, true) + if o.r.AddressorUser.o.alreadyPersisted { + m.R.AddressorUser = o.r.AddressorUser.o.Build() + } else { + var rel0 *models.User + rel0, err = o.r.AddressorUser.o.Create(ctx, exec) + if err != nil { + return err + } + err = m.AttachAddressorUser(ctx, exec, rel0) + if err != nil { + return err + } + } + + } + + return err +} + +// Create builds a signal and inserts it into the database +// Relations objects are also inserted and placed in the .R field +func (o *SignalTemplate) Create(ctx context.Context, exec bob.Executor) (*models.Signal, error) { + var err error + opt := o.BuildSetter() + ensureCreatableSignal(opt) + + if o.r.CreatorUser == nil { + SignalMods.WithNewCreatorUser().Apply(ctx, o) + } + + var rel1 *models.User + + if o.r.CreatorUser.o.alreadyPersisted { + rel1 = o.r.CreatorUser.o.Build() + } else { + rel1, err = o.r.CreatorUser.o.Create(ctx, exec) + if err != nil { + return nil, err + } + } + + opt.Creator = omit.From(rel1.ID) + + if o.r.Organization == nil { + SignalMods.WithNewOrganization().Apply(ctx, o) + } + + var rel2 *models.Organization + + if o.r.Organization.o.alreadyPersisted { + rel2 = o.r.Organization.o.Build() + } else { + rel2, err = o.r.Organization.o.Create(ctx, exec) + if err != nil { + return nil, err + } + } + + opt.OrganizationID = omit.From(rel2.ID) + + m, err := models.Signals.Insert(opt).One(ctx, exec) + if err != nil { + return nil, err + } + + m.R.CreatorUser = rel1 + m.R.Organization = rel2 + + if err := o.insertOptRels(ctx, exec, m); err != nil { + return nil, err + } + return m, err +} + +// MustCreate builds a signal and inserts it into the database +// Relations objects are also inserted and placed in the .R field +// panics if an error occurs +func (o *SignalTemplate) MustCreate(ctx context.Context, exec bob.Executor) *models.Signal { + m, err := o.Create(ctx, exec) + if err != nil { + panic(err) + } + return m +} + +// CreateOrFail builds a signal and inserts it into the database +// Relations objects are also inserted and placed in the .R field +// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs +func (o *SignalTemplate) CreateOrFail(ctx context.Context, tb testing.TB, exec bob.Executor) *models.Signal { + tb.Helper() + m, err := o.Create(ctx, exec) + if err != nil { + tb.Fatal(err) + return nil + } + return m +} + +// CreateMany builds multiple signals and inserts them into the database +// Relations objects are also inserted and placed in the .R field +func (o SignalTemplate) CreateMany(ctx context.Context, exec bob.Executor, number int) (models.SignalSlice, error) { + var err error + m := make(models.SignalSlice, number) + + for i := range m { + m[i], err = o.Create(ctx, exec) + if err != nil { + return nil, err + } + } + + return m, nil +} + +// MustCreateMany builds multiple signals and inserts them into the database +// Relations objects are also inserted and placed in the .R field +// panics if an error occurs +func (o SignalTemplate) MustCreateMany(ctx context.Context, exec bob.Executor, number int) models.SignalSlice { + m, err := o.CreateMany(ctx, exec, number) + if err != nil { + panic(err) + } + return m +} + +// CreateManyOrFail builds multiple signals and inserts them into the database +// Relations objects are also inserted and placed in the .R field +// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs +func (o SignalTemplate) CreateManyOrFail(ctx context.Context, tb testing.TB, exec bob.Executor, number int) models.SignalSlice { + tb.Helper() + m, err := o.CreateMany(ctx, exec, number) + if err != nil { + tb.Fatal(err) + return nil + } + return m +} + +// Signal has methods that act as mods for the SignalTemplate +var SignalMods signalMods + +type signalMods struct{} + +func (m signalMods) RandomizeAllColumns(f *faker.Faker) SignalMod { + return SignalModSlice{ + SignalMods.RandomAddressed(f), + SignalMods.RandomAddressor(f), + SignalMods.RandomCreated(f), + SignalMods.RandomCreator(f), + SignalMods.RandomID(f), + SignalMods.RandomOrganizationID(f), + SignalMods.RandomSpecies(f), + SignalMods.RandomTitle(f), + SignalMods.RandomType(f), + } +} + +// Set the model columns to this value +func (m signalMods) Addressed(val null.Val[time.Time]) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Addressed = func() null.Val[time.Time] { return val } + }) +} + +// Set the Column from the function +func (m signalMods) AddressedFunc(f func() null.Val[time.Time]) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Addressed = f + }) +} + +// Clear any values for the column +func (m signalMods) UnsetAddressed() SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Addressed = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is sometimes null +func (m signalMods) RandomAddressed(f *faker.Faker) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Addressed = func() null.Val[time.Time] { + if f == nil { + f = &defaultFaker + } + + val := random_time_Time(f) + return null.From(val) + } + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is never null +func (m signalMods) RandomAddressedNotNull(f *faker.Faker) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Addressed = func() null.Val[time.Time] { + if f == nil { + f = &defaultFaker + } + + val := random_time_Time(f) + return null.From(val) + } + }) +} + +// Set the model columns to this value +func (m signalMods) Addressor(val null.Val[int32]) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Addressor = func() null.Val[int32] { return val } + }) +} + +// Set the Column from the function +func (m signalMods) AddressorFunc(f func() null.Val[int32]) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Addressor = f + }) +} + +// Clear any values for the column +func (m signalMods) UnsetAddressor() SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Addressor = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is sometimes null +func (m signalMods) RandomAddressor(f *faker.Faker) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Addressor = func() null.Val[int32] { + if f == nil { + f = &defaultFaker + } + + val := random_int32(f) + return null.From(val) + } + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is never null +func (m signalMods) RandomAddressorNotNull(f *faker.Faker) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Addressor = func() null.Val[int32] { + if f == nil { + f = &defaultFaker + } + + val := random_int32(f) + return null.From(val) + } + }) +} + +// Set the model columns to this value +func (m signalMods) Created(val time.Time) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Created = func() time.Time { return val } + }) +} + +// Set the Column from the function +func (m signalMods) CreatedFunc(f func() time.Time) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Created = f + }) +} + +// Clear any values for the column +func (m signalMods) UnsetCreated() SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Created = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m signalMods) RandomCreated(f *faker.Faker) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Created = func() time.Time { + return random_time_Time(f) + } + }) +} + +// Set the model columns to this value +func (m signalMods) Creator(val int32) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Creator = func() int32 { return val } + }) +} + +// Set the Column from the function +func (m signalMods) CreatorFunc(f func() int32) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Creator = f + }) +} + +// Clear any values for the column +func (m signalMods) UnsetCreator() SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Creator = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m signalMods) RandomCreator(f *faker.Faker) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Creator = func() int32 { + return random_int32(f) + } + }) +} + +// Set the model columns to this value +func (m signalMods) ID(val int32) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.ID = func() int32 { return val } + }) +} + +// Set the Column from the function +func (m signalMods) IDFunc(f func() int32) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.ID = f + }) +} + +// Clear any values for the column +func (m signalMods) UnsetID() SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.ID = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m signalMods) RandomID(f *faker.Faker) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.ID = func() int32 { + return random_int32(f) + } + }) +} + +// Set the model columns to this value +func (m signalMods) OrganizationID(val int32) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.OrganizationID = func() int32 { return val } + }) +} + +// Set the Column from the function +func (m signalMods) OrganizationIDFunc(f func() int32) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.OrganizationID = f + }) +} + +// Clear any values for the column +func (m signalMods) UnsetOrganizationID() SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.OrganizationID = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m signalMods) RandomOrganizationID(f *faker.Faker) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.OrganizationID = func() int32 { + return random_int32(f) + } + }) +} + +// Set the model columns to this value +func (m signalMods) Species(val null.Val[enums.Mosquitospecies]) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Species = func() null.Val[enums.Mosquitospecies] { return val } + }) +} + +// Set the Column from the function +func (m signalMods) SpeciesFunc(f func() null.Val[enums.Mosquitospecies]) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Species = f + }) +} + +// Clear any values for the column +func (m signalMods) UnsetSpecies() SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Species = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is sometimes null +func (m signalMods) RandomSpecies(f *faker.Faker) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Species = func() null.Val[enums.Mosquitospecies] { + if f == nil { + f = &defaultFaker + } + + val := random_enums_Mosquitospecies(f) + return null.From(val) + } + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is never null +func (m signalMods) RandomSpeciesNotNull(f *faker.Faker) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Species = func() null.Val[enums.Mosquitospecies] { + if f == nil { + f = &defaultFaker + } + + val := random_enums_Mosquitospecies(f) + return null.From(val) + } + }) +} + +// Set the model columns to this value +func (m signalMods) Title(val string) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Title = func() string { return val } + }) +} + +// Set the Column from the function +func (m signalMods) TitleFunc(f func() string) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Title = f + }) +} + +// Clear any values for the column +func (m signalMods) UnsetTitle() SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Title = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m signalMods) RandomTitle(f *faker.Faker) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Title = func() string { + return random_string(f) + } + }) +} + +// Set the model columns to this value +func (m signalMods) Type(val enums.Signaltype) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Type = func() enums.Signaltype { return val } + }) +} + +// Set the Column from the function +func (m signalMods) TypeFunc(f func() enums.Signaltype) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Type = f + }) +} + +// Clear any values for the column +func (m signalMods) UnsetType() SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Type = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m signalMods) RandomType(f *faker.Faker) SignalMod { + return SignalModFunc(func(_ context.Context, o *SignalTemplate) { + o.Type = func() enums.Signaltype { + return random_enums_Signaltype(f) + } + }) +} + +func (m signalMods) WithParentsCascading() SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + if isDone, _ := signalWithParentsCascadingCtx.Value(ctx); isDone { + return + } + ctx = signalWithParentsCascadingCtx.WithValue(ctx, true) + { + + related := o.f.NewUserWithContext(ctx, UserMods.WithParentsCascading()) + m.WithAddressorUser(related).Apply(ctx, o) + } + { + + related := o.f.NewUserWithContext(ctx, UserMods.WithParentsCascading()) + m.WithCreatorUser(related).Apply(ctx, o) + } + { + + related := o.f.NewOrganizationWithContext(ctx, OrganizationMods.WithParentsCascading()) + m.WithOrganization(related).Apply(ctx, o) + } + }) +} + +func (m signalMods) WithAddressorUser(rel *UserTemplate) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + o.r.AddressorUser = &signalRAddressorUserR{ + o: rel, + } + }) +} + +func (m signalMods) WithNewAddressorUser(mods ...UserMod) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + related := o.f.NewUserWithContext(ctx, mods...) + + m.WithAddressorUser(related).Apply(ctx, o) + }) +} + +func (m signalMods) WithExistingAddressorUser(em *models.User) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + o.r.AddressorUser = &signalRAddressorUserR{ + o: o.f.FromExistingUser(em), + } + }) +} + +func (m signalMods) WithoutAddressorUser() SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + o.r.AddressorUser = nil + }) +} + +func (m signalMods) WithCreatorUser(rel *UserTemplate) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + o.r.CreatorUser = &signalRCreatorUserR{ + o: rel, + } + }) +} + +func (m signalMods) WithNewCreatorUser(mods ...UserMod) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + related := o.f.NewUserWithContext(ctx, mods...) + + m.WithCreatorUser(related).Apply(ctx, o) + }) +} + +func (m signalMods) WithExistingCreatorUser(em *models.User) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + o.r.CreatorUser = &signalRCreatorUserR{ + o: o.f.FromExistingUser(em), + } + }) +} + +func (m signalMods) WithoutCreatorUser() SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + o.r.CreatorUser = nil + }) +} + +func (m signalMods) WithOrganization(rel *OrganizationTemplate) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + o.r.Organization = &signalROrganizationR{ + o: rel, + } + }) +} + +func (m signalMods) WithNewOrganization(mods ...OrganizationMod) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + related := o.f.NewOrganizationWithContext(ctx, mods...) + + m.WithOrganization(related).Apply(ctx, o) + }) +} + +func (m signalMods) WithExistingOrganization(em *models.Organization) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + o.r.Organization = &signalROrganizationR{ + o: o.f.FromExistingOrganization(em), + } + }) +} + +func (m signalMods) WithoutOrganization() SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + o.r.Organization = nil + }) +} + +func (m signalMods) WithSignalPools(number int, related *SignalPoolTemplate) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + o.r.SignalPools = []*signalRSignalPoolsR{{ + number: number, + o: related, + }} + }) +} + +func (m signalMods) WithNewSignalPools(number int, mods ...SignalPoolMod) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + related := o.f.NewSignalPoolWithContext(ctx, mods...) + m.WithSignalPools(number, related).Apply(ctx, o) + }) +} + +func (m signalMods) AddSignalPools(number int, related *SignalPoolTemplate) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + o.r.SignalPools = append(o.r.SignalPools, &signalRSignalPoolsR{ + number: number, + o: related, + }) + }) +} + +func (m signalMods) AddNewSignalPools(number int, mods ...SignalPoolMod) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + related := o.f.NewSignalPoolWithContext(ctx, mods...) + m.AddSignalPools(number, related).Apply(ctx, o) + }) +} + +func (m signalMods) AddExistingSignalPools(existingModels ...*models.SignalPool) SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + for _, em := range existingModels { + o.r.SignalPools = append(o.r.SignalPools, &signalRSignalPoolsR{ + o: o.f.FromExistingSignalPool(em), + }) + } + }) +} + +func (m signalMods) WithoutSignalPools() SignalMod { + return SignalModFunc(func(ctx context.Context, o *SignalTemplate) { + o.r.SignalPools = nil + }) +} diff --git a/db/factory/signal_pool.bob.go b/db/factory/signal_pool.bob.go new file mode 100644 index 00000000..4d2aeff6 --- /dev/null +++ b/db/factory/signal_pool.bob.go @@ -0,0 +1,262 @@ +// Code generated by BobGen psql v0.42.5. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package factory + +import ( + "context" + + models "github.com/Gleipnir-Technology/nidus-sync/db/models" + "github.com/jaswdr/faker/v2" +) + +type SignalPoolMod interface { + Apply(context.Context, *SignalPoolTemplate) +} + +type SignalPoolModFunc func(context.Context, *SignalPoolTemplate) + +func (f SignalPoolModFunc) Apply(ctx context.Context, n *SignalPoolTemplate) { + f(ctx, n) +} + +type SignalPoolModSlice []SignalPoolMod + +func (mods SignalPoolModSlice) Apply(ctx context.Context, n *SignalPoolTemplate) { + for _, f := range mods { + f.Apply(ctx, n) + } +} + +// SignalPoolTemplate is an object representing the database table. +// all columns are optional and should be set by mods +type SignalPoolTemplate struct { + PoolID func() int32 + SignalID func() int32 + + r signalPoolR + f *Factory + + alreadyPersisted bool +} + +type signalPoolR struct { + Pool *signalPoolRPoolR + Signal *signalPoolRSignalR +} + +type signalPoolRPoolR struct { + o *PoolTemplate +} +type signalPoolRSignalR struct { + o *SignalTemplate +} + +// Apply mods to the SignalPoolTemplate +func (o *SignalPoolTemplate) Apply(ctx context.Context, mods ...SignalPoolMod) { + for _, mod := range mods { + mod.Apply(ctx, o) + } +} + +// setModelRels creates and sets the relationships on *models.SignalPool +// according to the relationships in the template. Nothing is inserted into the db +func (t SignalPoolTemplate) setModelRels(o *models.SignalPool) { + if t.r.Pool != nil { + rel := t.r.Pool.o.Build() + rel.R.SignalPools = append(rel.R.SignalPools, o) + o.PoolID = rel.ID // h2 + o.R.Pool = rel + } + + if t.r.Signal != nil { + rel := t.r.Signal.o.Build() + rel.R.SignalPools = append(rel.R.SignalPools, o) + o.SignalID = rel.ID // h2 + o.R.Signal = rel + } +} + +// Build returns an *models.SignalPool +// Related objects are also created and placed in the .R field +// NOTE: Objects are not inserted into the database. Use SignalPoolTemplate.Create +func (o SignalPoolTemplate) Build() *models.SignalPool { + m := &models.SignalPool{} + + if o.PoolID != nil { + m.PoolID = o.PoolID() + } + if o.SignalID != nil { + m.SignalID = o.SignalID() + } + + o.setModelRels(m) + + return m +} + +// BuildMany returns an models.SignalPoolSlice +// Related objects are also created and placed in the .R field +// NOTE: Objects are not inserted into the database. Use SignalPoolTemplate.CreateMany +func (o SignalPoolTemplate) BuildMany(number int) models.SignalPoolSlice { + m := make(models.SignalPoolSlice, number) + + for i := range m { + m[i] = o.Build() + } + + return m +} + +// SignalPool has methods that act as mods for the SignalPoolTemplate +var SignalPoolMods signalPoolMods + +type signalPoolMods struct{} + +func (m signalPoolMods) RandomizeAllColumns(f *faker.Faker) SignalPoolMod { + return SignalPoolModSlice{ + SignalPoolMods.RandomPoolID(f), + SignalPoolMods.RandomSignalID(f), + } +} + +// Set the model columns to this value +func (m signalPoolMods) PoolID(val int32) SignalPoolMod { + return SignalPoolModFunc(func(_ context.Context, o *SignalPoolTemplate) { + o.PoolID = func() int32 { return val } + }) +} + +// Set the Column from the function +func (m signalPoolMods) PoolIDFunc(f func() int32) SignalPoolMod { + return SignalPoolModFunc(func(_ context.Context, o *SignalPoolTemplate) { + o.PoolID = f + }) +} + +// Clear any values for the column +func (m signalPoolMods) UnsetPoolID() SignalPoolMod { + return SignalPoolModFunc(func(_ context.Context, o *SignalPoolTemplate) { + o.PoolID = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m signalPoolMods) RandomPoolID(f *faker.Faker) SignalPoolMod { + return SignalPoolModFunc(func(_ context.Context, o *SignalPoolTemplate) { + o.PoolID = func() int32 { + return random_int32(f) + } + }) +} + +// Set the model columns to this value +func (m signalPoolMods) SignalID(val int32) SignalPoolMod { + return SignalPoolModFunc(func(_ context.Context, o *SignalPoolTemplate) { + o.SignalID = func() int32 { return val } + }) +} + +// Set the Column from the function +func (m signalPoolMods) SignalIDFunc(f func() int32) SignalPoolMod { + return SignalPoolModFunc(func(_ context.Context, o *SignalPoolTemplate) { + o.SignalID = f + }) +} + +// Clear any values for the column +func (m signalPoolMods) UnsetSignalID() SignalPoolMod { + return SignalPoolModFunc(func(_ context.Context, o *SignalPoolTemplate) { + o.SignalID = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m signalPoolMods) RandomSignalID(f *faker.Faker) SignalPoolMod { + return SignalPoolModFunc(func(_ context.Context, o *SignalPoolTemplate) { + o.SignalID = func() int32 { + return random_int32(f) + } + }) +} + +func (m signalPoolMods) WithParentsCascading() SignalPoolMod { + return SignalPoolModFunc(func(ctx context.Context, o *SignalPoolTemplate) { + if isDone, _ := signalPoolWithParentsCascadingCtx.Value(ctx); isDone { + return + } + ctx = signalPoolWithParentsCascadingCtx.WithValue(ctx, true) + { + + related := o.f.NewPoolWithContext(ctx, PoolMods.WithParentsCascading()) + m.WithPool(related).Apply(ctx, o) + } + { + + related := o.f.NewSignalWithContext(ctx, SignalMods.WithParentsCascading()) + m.WithSignal(related).Apply(ctx, o) + } + }) +} + +func (m signalPoolMods) WithPool(rel *PoolTemplate) SignalPoolMod { + return SignalPoolModFunc(func(ctx context.Context, o *SignalPoolTemplate) { + o.r.Pool = &signalPoolRPoolR{ + o: rel, + } + }) +} + +func (m signalPoolMods) WithNewPool(mods ...PoolMod) SignalPoolMod { + return SignalPoolModFunc(func(ctx context.Context, o *SignalPoolTemplate) { + related := o.f.NewPoolWithContext(ctx, mods...) + + m.WithPool(related).Apply(ctx, o) + }) +} + +func (m signalPoolMods) WithExistingPool(em *models.Pool) SignalPoolMod { + return SignalPoolModFunc(func(ctx context.Context, o *SignalPoolTemplate) { + o.r.Pool = &signalPoolRPoolR{ + o: o.f.FromExistingPool(em), + } + }) +} + +func (m signalPoolMods) WithoutPool() SignalPoolMod { + return SignalPoolModFunc(func(ctx context.Context, o *SignalPoolTemplate) { + o.r.Pool = nil + }) +} + +func (m signalPoolMods) WithSignal(rel *SignalTemplate) SignalPoolMod { + return SignalPoolModFunc(func(ctx context.Context, o *SignalPoolTemplate) { + o.r.Signal = &signalPoolRSignalR{ + o: rel, + } + }) +} + +func (m signalPoolMods) WithNewSignal(mods ...SignalMod) SignalPoolMod { + return SignalPoolModFunc(func(ctx context.Context, o *SignalPoolTemplate) { + related := o.f.NewSignalWithContext(ctx, mods...) + + m.WithSignal(related).Apply(ctx, o) + }) +} + +func (m signalPoolMods) WithExistingSignal(em *models.Signal) SignalPoolMod { + return SignalPoolModFunc(func(ctx context.Context, o *SignalPoolTemplate) { + o.r.Signal = &signalPoolRSignalR{ + o: o.f.FromExistingSignal(em), + } + }) +} + +func (m signalPoolMods) WithoutSignal() SignalPoolMod { + return SignalPoolModFunc(func(ctx context.Context, o *SignalPoolTemplate) { + o.r.Signal = nil + }) +} diff --git a/db/factory/user_.bob.go b/db/factory/user_.bob.go index 22d66a94..34c8a1b2 100644 --- a/db/factory/user_.bob.go +++ b/db/factory/user_.bob.go @@ -71,6 +71,8 @@ type userR struct { UserNotifications []*userRUserNotificationsR CreatorPools []*userRCreatorPoolsR CreatorResidents []*userRCreatorResidentsR + AddressorSignals []*userRAddressorSignalsR + CreatorSignals []*userRCreatorSignalsR CreatorSites []*userRCreatorSitesR Organization *userROrganizationR } @@ -123,6 +125,14 @@ type userRCreatorResidentsR struct { number int o *ResidentTemplate } +type userRAddressorSignalsR struct { + number int + o *SignalTemplate +} +type userRCreatorSignalsR struct { + number int + o *SignalTemplate +} type userRCreatorSitesR struct { number int o *SiteTemplate @@ -297,6 +307,32 @@ func (t UserTemplate) setModelRels(o *models.User) { o.R.CreatorResidents = rel } + if t.r.AddressorSignals != nil { + rel := models.SignalSlice{} + for _, r := range t.r.AddressorSignals { + related := r.o.BuildMany(r.number) + for _, rel := range related { + rel.Addressor = null.From(o.ID) // h2 + rel.R.AddressorUser = o + } + rel = append(rel, related...) + } + o.R.AddressorSignals = rel + } + + if t.r.CreatorSignals != nil { + rel := models.SignalSlice{} + for _, r := range t.r.CreatorSignals { + related := r.o.BuildMany(r.number) + for _, rel := range related { + rel.Creator = o.ID // h2 + rel.R.CreatorUser = o + } + rel = append(rel, related...) + } + o.R.CreatorSignals = rel + } + if t.r.CreatorSites != nil { rel := models.SiteSlice{} for _, r := range t.r.CreatorSites { @@ -728,6 +764,46 @@ func (o *UserTemplate) insertOptRels(ctx context.Context, exec bob.Executor, m * } } + isAddressorSignalsDone, _ := userRelAddressorSignalsCtx.Value(ctx) + if !isAddressorSignalsDone && o.r.AddressorSignals != nil { + ctx = userRelAddressorSignalsCtx.WithValue(ctx, true) + for _, r := range o.r.AddressorSignals { + if r.o.alreadyPersisted { + m.R.AddressorSignals = append(m.R.AddressorSignals, r.o.Build()) + } else { + rel12, err := r.o.CreateMany(ctx, exec, r.number) + if err != nil { + return err + } + + err = m.AttachAddressorSignals(ctx, exec, rel12...) + if err != nil { + return err + } + } + } + } + + isCreatorSignalsDone, _ := userRelCreatorSignalsCtx.Value(ctx) + if !isCreatorSignalsDone && o.r.CreatorSignals != nil { + ctx = userRelCreatorSignalsCtx.WithValue(ctx, true) + for _, r := range o.r.CreatorSignals { + if r.o.alreadyPersisted { + m.R.CreatorSignals = append(m.R.CreatorSignals, r.o.Build()) + } else { + rel13, err := r.o.CreateMany(ctx, exec, r.number) + if err != nil { + return err + } + + err = m.AttachCreatorSignals(ctx, exec, rel13...) + if err != nil { + return err + } + } + } + } + isCreatorSitesDone, _ := userRelCreatorSitesCtx.Value(ctx) if !isCreatorSitesDone && o.r.CreatorSites != nil { ctx = userRelCreatorSitesCtx.WithValue(ctx, true) @@ -735,12 +811,12 @@ func (o *UserTemplate) insertOptRels(ctx context.Context, exec bob.Executor, m * if r.o.alreadyPersisted { m.R.CreatorSites = append(m.R.CreatorSites, r.o.Build()) } else { - rel12, err := r.o.CreateMany(ctx, exec, r.number) + rel14, err := r.o.CreateMany(ctx, exec, r.number) if err != nil { return err } - err = m.AttachCreatorSites(ctx, exec, rel12...) + err = m.AttachCreatorSites(ctx, exec, rel14...) if err != nil { return err } @@ -762,25 +838,25 @@ func (o *UserTemplate) Create(ctx context.Context, exec bob.Executor) (*models.U UserMods.WithNewOrganization().Apply(ctx, o) } - var rel13 *models.Organization + var rel15 *models.Organization if o.r.Organization.o.alreadyPersisted { - rel13 = o.r.Organization.o.Build() + rel15 = o.r.Organization.o.Build() } else { - rel13, err = o.r.Organization.o.Create(ctx, exec) + rel15, err = o.r.Organization.o.Create(ctx, exec) if err != nil { return nil, err } } - opt.OrganizationID = omit.From(rel13.ID) + opt.OrganizationID = omit.From(rel15.ID) m, err := models.Users.Insert(opt).One(ctx, exec) if err != nil { return nil, err } - m.R.Organization = rel13 + m.R.Organization = rel15 if err := o.insertOptRels(ctx, exec, m); err != nil { return nil, err @@ -2030,6 +2106,102 @@ func (m userMods) WithoutCreatorResidents() UserMod { }) } +func (m userMods) WithAddressorSignals(number int, related *SignalTemplate) UserMod { + return UserModFunc(func(ctx context.Context, o *UserTemplate) { + o.r.AddressorSignals = []*userRAddressorSignalsR{{ + number: number, + o: related, + }} + }) +} + +func (m userMods) WithNewAddressorSignals(number int, mods ...SignalMod) UserMod { + return UserModFunc(func(ctx context.Context, o *UserTemplate) { + related := o.f.NewSignalWithContext(ctx, mods...) + m.WithAddressorSignals(number, related).Apply(ctx, o) + }) +} + +func (m userMods) AddAddressorSignals(number int, related *SignalTemplate) UserMod { + return UserModFunc(func(ctx context.Context, o *UserTemplate) { + o.r.AddressorSignals = append(o.r.AddressorSignals, &userRAddressorSignalsR{ + number: number, + o: related, + }) + }) +} + +func (m userMods) AddNewAddressorSignals(number int, mods ...SignalMod) UserMod { + return UserModFunc(func(ctx context.Context, o *UserTemplate) { + related := o.f.NewSignalWithContext(ctx, mods...) + m.AddAddressorSignals(number, related).Apply(ctx, o) + }) +} + +func (m userMods) AddExistingAddressorSignals(existingModels ...*models.Signal) UserMod { + return UserModFunc(func(ctx context.Context, o *UserTemplate) { + for _, em := range existingModels { + o.r.AddressorSignals = append(o.r.AddressorSignals, &userRAddressorSignalsR{ + o: o.f.FromExistingSignal(em), + }) + } + }) +} + +func (m userMods) WithoutAddressorSignals() UserMod { + return UserModFunc(func(ctx context.Context, o *UserTemplate) { + o.r.AddressorSignals = nil + }) +} + +func (m userMods) WithCreatorSignals(number int, related *SignalTemplate) UserMod { + return UserModFunc(func(ctx context.Context, o *UserTemplate) { + o.r.CreatorSignals = []*userRCreatorSignalsR{{ + number: number, + o: related, + }} + }) +} + +func (m userMods) WithNewCreatorSignals(number int, mods ...SignalMod) UserMod { + return UserModFunc(func(ctx context.Context, o *UserTemplate) { + related := o.f.NewSignalWithContext(ctx, mods...) + m.WithCreatorSignals(number, related).Apply(ctx, o) + }) +} + +func (m userMods) AddCreatorSignals(number int, related *SignalTemplate) UserMod { + return UserModFunc(func(ctx context.Context, o *UserTemplate) { + o.r.CreatorSignals = append(o.r.CreatorSignals, &userRCreatorSignalsR{ + number: number, + o: related, + }) + }) +} + +func (m userMods) AddNewCreatorSignals(number int, mods ...SignalMod) UserMod { + return UserModFunc(func(ctx context.Context, o *UserTemplate) { + related := o.f.NewSignalWithContext(ctx, mods...) + m.AddCreatorSignals(number, related).Apply(ctx, o) + }) +} + +func (m userMods) AddExistingCreatorSignals(existingModels ...*models.Signal) UserMod { + return UserModFunc(func(ctx context.Context, o *UserTemplate) { + for _, em := range existingModels { + o.r.CreatorSignals = append(o.r.CreatorSignals, &userRCreatorSignalsR{ + o: o.f.FromExistingSignal(em), + }) + } + }) +} + +func (m userMods) WithoutCreatorSignals() UserMod { + return UserModFunc(func(ctx context.Context, o *UserTemplate) { + o.r.CreatorSignals = nil + }) +} + func (m userMods) WithCreatorSites(number int, related *SiteTemplate) UserMod { return UserModFunc(func(ctx context.Context, o *UserTemplate) { o.r.CreatorSites = []*userRCreatorSitesR{{ diff --git a/db/migrations/00080_signal.sql b/db/migrations/00080_signal.sql new file mode 100644 index 00000000..ece3e291 --- /dev/null +++ b/db/migrations/00080_signal.sql @@ -0,0 +1,37 @@ +-- +goose Up +CREATE TYPE SignalType AS ENUM ( + 'flyover.pool', + 'plan.followup', + 'publicreport.water', + 'publicreport.nuisance', + 'residual.exiring', + 'surveillance.observation', + 'trap.spike' +); +CREATE TYPE MosquitoSpecies AS ENUM ( + 'aedes aegypti', + 'aedes albopictus', + 'culex pipiens', + 'culex tarsalis' +); +CREATE TABLE signal ( + addressed TIMESTAMP WITHOUT TIME ZONE, + addressor INTEGER REFERENCES user_(id), + created TIMESTAMP WITHOUT TIME ZONE NOT NULL, + creator INTEGER NOT NULL REFERENCES user_(id), + id SERIAL NOT NULL, + organization_id INTEGER NOT NULL REFERENCES organization(id), + species MosquitoSpecies, + title TEXT NOT NULL, + type_ SignalType NOT NULL, + PRIMARY KEY(id) +); +CREATE TABLE signal_pool ( + pool_id INTEGER NOT NULL REFERENCES pool(id), + signal_id INTEGER NOT NULL REFERENCES signal(id) +); +-- +goose Down +DROP TABLE signal_pool; +DROP TABLE signal; +DROP TYPE MosquitoSpecies; +DROP TYPE SignalType; diff --git a/db/models/bob_counts.bob.go b/db/models/bob_counts.bob.go index 0acf1167..a8382b34 100644 --- a/db/models/bob_counts.bob.go +++ b/db/models/bob_counts.bob.go @@ -38,10 +38,12 @@ type preloadCounts struct { NoteImage noteImageCountPreloader Organization organizationCountPreloader Parcel parcelCountPreloader + Pool poolCountPreloader PublicreportImage publicreportImageCountPreloader PublicreportNuisance publicreportNuisanceCountPreloader PublicreportPool publicreportPoolCountPreloader PublicreportQuick publicreportQuickCountPreloader + Signal signalCountPreloader Site siteCountPreloader User userCountPreloader } @@ -65,10 +67,12 @@ func getPreloadCount() preloadCounts { NoteImage: buildNoteImageCountPreloader(), Organization: buildOrganizationCountPreloader(), Parcel: buildParcelCountPreloader(), + Pool: buildPoolCountPreloader(), PublicreportImage: buildPublicreportImageCountPreloader(), PublicreportNuisance: buildPublicreportNuisanceCountPreloader(), PublicreportPool: buildPublicreportPoolCountPreloader(), PublicreportQuick: buildPublicreportQuickCountPreloader(), + Signal: buildSignalCountPreloader(), Site: buildSiteCountPreloader(), User: buildUserCountPreloader(), } @@ -92,10 +96,12 @@ type thenLoadCounts[Q orm.Loadable] struct { NoteImage noteImageCountThenLoader[Q] Organization organizationCountThenLoader[Q] Parcel parcelCountThenLoader[Q] + Pool poolCountThenLoader[Q] PublicreportImage publicreportImageCountThenLoader[Q] PublicreportNuisance publicreportNuisanceCountThenLoader[Q] PublicreportPool publicreportPoolCountThenLoader[Q] PublicreportQuick publicreportQuickCountThenLoader[Q] + Signal signalCountThenLoader[Q] Site siteCountThenLoader[Q] User userCountThenLoader[Q] } @@ -119,10 +125,12 @@ func getThenLoadCount[Q orm.Loadable]() thenLoadCounts[Q] { NoteImage: buildNoteImageCountThenLoader[Q](), Organization: buildOrganizationCountThenLoader[Q](), Parcel: buildParcelCountThenLoader[Q](), + Pool: buildPoolCountThenLoader[Q](), PublicreportImage: buildPublicreportImageCountThenLoader[Q](), PublicreportNuisance: buildPublicreportNuisanceCountThenLoader[Q](), PublicreportPool: buildPublicreportPoolCountThenLoader[Q](), PublicreportQuick: buildPublicreportQuickCountThenLoader[Q](), + Signal: buildSignalCountThenLoader[Q](), Site: buildSiteCountThenLoader[Q](), User: buildUserCountThenLoader[Q](), } diff --git a/db/models/bob_joins.bob.go b/db/models/bob_joins.bob.go index d2e3bbf2..19138466 100644 --- a/db/models/bob_joins.bob.go +++ b/db/models/bob_joins.bob.go @@ -113,6 +113,8 @@ type joins[Q dialect.Joinable] struct { PublicreportSubscribeEmails joinSet[publicreportSubscribeEmailJoins[Q]] PublicreportSubscribePhones joinSet[publicreportSubscribePhoneJoins[Q]] Residents joinSet[residentJoins[Q]] + Signals joinSet[signalJoins[Q]] + SignalPools joinSet[signalPoolJoins[Q]] Sites joinSet[siteJoins[Q]] Users joinSet[userJoins[Q]] } @@ -208,6 +210,8 @@ func getJoins[Q dialect.Joinable]() joins[Q] { PublicreportSubscribeEmails: buildJoinSet[publicreportSubscribeEmailJoins[Q]](PublicreportSubscribeEmails.Columns, buildPublicreportSubscribeEmailJoins), PublicreportSubscribePhones: buildJoinSet[publicreportSubscribePhoneJoins[Q]](PublicreportSubscribePhones.Columns, buildPublicreportSubscribePhoneJoins), Residents: buildJoinSet[residentJoins[Q]](Residents.Columns, buildResidentJoins), + Signals: buildJoinSet[signalJoins[Q]](Signals.Columns, buildSignalJoins), + SignalPools: buildJoinSet[signalPoolJoins[Q]](SignalPools.Columns, buildSignalPoolJoins), Sites: buildJoinSet[siteJoins[Q]](Sites.Columns, buildSiteJoins), Users: buildJoinSet[userJoins[Q]](Users.Columns, buildUserJoins), } diff --git a/db/models/bob_loaders.bob.go b/db/models/bob_loaders.bob.go index 79c1ab3e..402cb32c 100644 --- a/db/models/bob_loaders.bob.go +++ b/db/models/bob_loaders.bob.go @@ -98,6 +98,8 @@ type preloaders struct { PublicreportSubscribeEmail publicreportSubscribeEmailPreloader PublicreportSubscribePhone publicreportSubscribePhonePreloader Resident residentPreloader + Signal signalPreloader + SignalPool signalPoolPreloader Site sitePreloader User userPreloader } @@ -185,6 +187,8 @@ func getPreloaders() preloaders { PublicreportSubscribeEmail: buildPublicreportSubscribeEmailPreloader(), PublicreportSubscribePhone: buildPublicreportSubscribePhonePreloader(), Resident: buildResidentPreloader(), + Signal: buildSignalPreloader(), + SignalPool: buildSignalPoolPreloader(), Site: buildSitePreloader(), User: buildUserPreloader(), } @@ -278,6 +282,8 @@ type thenLoaders[Q orm.Loadable] struct { PublicreportSubscribeEmail publicreportSubscribeEmailThenLoader[Q] PublicreportSubscribePhone publicreportSubscribePhoneThenLoader[Q] Resident residentThenLoader[Q] + Signal signalThenLoader[Q] + SignalPool signalPoolThenLoader[Q] Site siteThenLoader[Q] User userThenLoader[Q] } @@ -365,6 +371,8 @@ func getThenLoaders[Q orm.Loadable]() thenLoaders[Q] { PublicreportSubscribeEmail: buildPublicreportSubscribeEmailThenLoader[Q](), PublicreportSubscribePhone: buildPublicreportSubscribePhoneThenLoader[Q](), Resident: buildResidentThenLoader[Q](), + Signal: buildSignalThenLoader[Q](), + SignalPool: buildSignalPoolThenLoader[Q](), Site: buildSiteThenLoader[Q](), User: buildUserThenLoader[Q](), } diff --git a/db/models/bob_where.bob.go b/db/models/bob_where.bob.go index 2da57038..020719a4 100644 --- a/db/models/bob_where.bob.go +++ b/db/models/bob_where.bob.go @@ -105,6 +105,8 @@ func Where[Q psql.Filterable]() struct { RasterOverviews rasterOverviewWhere[Q] Residents residentWhere[Q] Sessions sessionWhere[Q] + Signals signalWhere[Q] + SignalPools signalPoolWhere[Q] Sites siteWhere[Q] SpatialRefSys spatialRefSyWhere[Q] Users userWhere[Q] @@ -198,6 +200,8 @@ func Where[Q psql.Filterable]() struct { RasterOverviews rasterOverviewWhere[Q] Residents residentWhere[Q] Sessions sessionWhere[Q] + Signals signalWhere[Q] + SignalPools signalPoolWhere[Q] Sites siteWhere[Q] SpatialRefSys spatialRefSyWhere[Q] Users userWhere[Q] @@ -290,6 +294,8 @@ func Where[Q psql.Filterable]() struct { RasterOverviews: buildRasterOverviewWhere[Q](RasterOverviews.Columns), Residents: buildResidentWhere[Q](Residents.Columns), Sessions: buildSessionWhere[Q](Sessions.Columns), + Signals: buildSignalWhere[Q](Signals.Columns), + SignalPools: buildSignalPoolWhere[Q](SignalPools.Columns), Sites: buildSiteWhere[Q](Sites.Columns), SpatialRefSys: buildSpatialRefSyWhere[Q](SpatialRefSys.Columns), Users: buildUserWhere[Q](Users.Columns), diff --git a/db/models/organization.bob.go b/db/models/organization.bob.go index 2e8d436b..ddadc7a9 100644 --- a/db/models/organization.bob.go +++ b/db/models/organization.bob.go @@ -122,6 +122,7 @@ type organizationR struct { Nuisances PublicreportNuisanceSlice // publicreport.nuisance.nuisance_organization_id_fkey PublicreportPool PublicreportPoolSlice // publicreport.pool.pool_organization_id_fkey Quicks PublicreportQuickSlice // publicreport.quick.quick_organization_id_fkey + Signals SignalSlice // signal.signal_organization_id_fkey User UserSlice // user_.user__organization_id_fkey } @@ -1951,6 +1952,30 @@ func (os OrganizationSlice) Quicks(mods ...bob.Mod[*dialect.SelectQuery]) Public )...) } +// Signals starts a query for related objects on signal +func (o *Organization) Signals(mods ...bob.Mod[*dialect.SelectQuery]) SignalsQuery { + return Signals.Query(append(mods, + sm.Where(Signals.Columns.OrganizationID.EQ(psql.Arg(o.ID))), + )...) +} + +func (os OrganizationSlice) Signals(mods ...bob.Mod[*dialect.SelectQuery]) SignalsQuery { + pkID := make(pgtypes.Array[int32], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkID = append(pkID, o.ID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkID), "integer[]")), + )) + + return Signals.Query(append(mods, + sm.Where(psql.Group(Signals.Columns.OrganizationID).OP("IN", PKArgExpr)), + )...) +} + // User starts a query for related objects on user_ func (o *Organization) User(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { return Users.Query(append(mods, @@ -4853,6 +4878,74 @@ func (organization0 *Organization) AttachQuicks(ctx context.Context, exec bob.Ex return nil } +func insertOrganizationSignals0(ctx context.Context, exec bob.Executor, signals1 []*SignalSetter, organization0 *Organization) (SignalSlice, error) { + for i := range signals1 { + signals1[i].OrganizationID = omit.From(organization0.ID) + } + + ret, err := Signals.Insert(bob.ToMods(signals1...)).All(ctx, exec) + if err != nil { + return ret, fmt.Errorf("insertOrganizationSignals0: %w", err) + } + + return ret, nil +} + +func attachOrganizationSignals0(ctx context.Context, exec bob.Executor, count int, signals1 SignalSlice, organization0 *Organization) (SignalSlice, error) { + setter := &SignalSetter{ + OrganizationID: omit.From(organization0.ID), + } + + err := signals1.UpdateAll(ctx, exec, *setter) + if err != nil { + return nil, fmt.Errorf("attachOrganizationSignals0: %w", err) + } + + return signals1, nil +} + +func (organization0 *Organization) InsertSignals(ctx context.Context, exec bob.Executor, related ...*SignalSetter) error { + if len(related) == 0 { + return nil + } + + var err error + + signals1, err := insertOrganizationSignals0(ctx, exec, related, organization0) + if err != nil { + return err + } + + organization0.R.Signals = append(organization0.R.Signals, signals1...) + + for _, rel := range signals1 { + rel.R.Organization = organization0 + } + return nil +} + +func (organization0 *Organization) AttachSignals(ctx context.Context, exec bob.Executor, related ...*Signal) error { + if len(related) == 0 { + return nil + } + + var err error + signals1 := SignalSlice(related) + + _, err = attachOrganizationSignals0(ctx, exec, len(related), signals1, organization0) + if err != nil { + return err + } + + organization0.R.Signals = append(organization0.R.Signals, signals1...) + + for _, rel := range related { + rel.R.Organization = organization0 + } + + return nil +} + func insertOrganizationUser0(ctx context.Context, exec bob.Executor, users1 []*UserSetter, organization0 *Organization) (UserSlice, error) { for i := range users1 { users1[i].OrganizationID = omit.From(organization0.ID) @@ -5595,6 +5688,20 @@ func (o *Organization) Preload(name string, retrieved any) error { o.R.Quicks = rels + for _, rel := range rels { + if rel != nil { + rel.R.Organization = o + } + } + return nil + case "Signals": + rels, ok := retrieved.(SignalSlice) + if !ok { + return fmt.Errorf("organization cannot load %T as %q", retrieved, name) + } + + o.R.Signals = rels + for _, rel := range rels { if rel != nil { rel.R.Organization = o @@ -5700,6 +5807,7 @@ type organizationThenLoader[Q orm.Loadable] struct { Nuisances func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] PublicreportPool func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] Quicks func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + Signals func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] User func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] } @@ -5833,6 +5941,9 @@ func buildOrganizationThenLoader[Q orm.Loadable]() organizationThenLoader[Q] { type QuicksLoadInterface interface { LoadQuicks(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } + type SignalsLoadInterface interface { + LoadSignals(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } type UserLoadInterface interface { LoadUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } @@ -6096,6 +6207,12 @@ func buildOrganizationThenLoader[Q orm.Loadable]() organizationThenLoader[Q] { return retrieved.LoadQuicks(ctx, exec, mods...) }, ), + Signals: thenLoadBuilder[Q]( + "Signals", + func(ctx context.Context, exec bob.Executor, retrieved SignalsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadSignals(ctx, exec, mods...) + }, + ), User: thenLoadBuilder[Q]( "User", func(ctx context.Context, exec bob.Executor, retrieved UserLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { @@ -8765,6 +8882,67 @@ func (os OrganizationSlice) LoadQuicks(ctx context.Context, exec bob.Executor, m return nil } +// LoadSignals loads the organization's Signals into the .R struct +func (o *Organization) LoadSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.Signals = nil + + related, err := o.Signals(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, rel := range related { + rel.R.Organization = o + } + + o.R.Signals = related + return nil +} + +// LoadSignals loads the organization's Signals into the .R struct +func (os OrganizationSlice) LoadSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + signals, err := os.Signals(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + o.R.Signals = nil + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range signals { + + if !(o.ID == rel.OrganizationID) { + continue + } + + rel.R.Organization = o + + o.R.Signals = append(o.R.Signals, rel) + } + } + + return nil +} + // LoadUser loads the organization's User into the .R struct func (o *Organization) LoadUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { if o == nil { @@ -8869,6 +9047,7 @@ type organizationC struct { Nuisances *int64 PublicreportPool *int64 Quicks *int64 + Signals *int64 User *int64 } @@ -8961,6 +9140,8 @@ func (o *Organization) PreloadCount(name string, count int64) error { o.C.PublicreportPool = &count case "Quicks": o.C.Quicks = &count + case "Signals": + o.C.Signals = &count case "User": o.C.User = &count } @@ -9009,6 +9190,7 @@ type organizationCountPreloader struct { Nuisances func(...bob.Mod[*dialect.SelectQuery]) psql.Preloader PublicreportPool func(...bob.Mod[*dialect.SelectQuery]) psql.Preloader Quicks func(...bob.Mod[*dialect.SelectQuery]) psql.Preloader + Signals func(...bob.Mod[*dialect.SelectQuery]) psql.Preloader User func(...bob.Mod[*dialect.SelectQuery]) psql.Preloader } @@ -9717,6 +9899,23 @@ func buildOrganizationCountPreloader() organizationCountPreloader { return psql.Group(psql.Select(subqueryMods...).Expression) }) }, + Signals: func(mods ...bob.Mod[*dialect.SelectQuery]) psql.Preloader { + return countPreloader[*Organization]("Signals", func(parent string) bob.Expression { + // Build a correlated subquery: (SELECT COUNT(*) FROM related WHERE fk = parent.pk) + if parent == "" { + parent = Organizations.Alias() + } + + subqueryMods := []bob.Mod[*dialect.SelectQuery]{ + sm.Columns(psql.Raw("count(*)")), + + sm.From(Signals.Name()), + sm.Where(psql.Quote(Signals.Alias(), "organization_id").EQ(psql.Quote(parent, "id"))), + } + subqueryMods = append(subqueryMods, mods...) + return psql.Group(psql.Select(subqueryMods...).Expression) + }) + }, User: func(mods ...bob.Mod[*dialect.SelectQuery]) psql.Preloader { return countPreloader[*Organization]("User", func(parent string) bob.Expression { // Build a correlated subquery: (SELECT COUNT(*) FROM related WHERE fk = parent.pk) @@ -9779,6 +9978,7 @@ type organizationCountThenLoader[Q orm.Loadable] struct { Nuisances func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] PublicreportPool func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] Quicks func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + Signals func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] User func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] } @@ -9906,6 +10106,9 @@ func buildOrganizationCountThenLoader[Q orm.Loadable]() organizationCountThenLoa type QuicksCountInterface interface { LoadCountQuicks(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } + type SignalsCountInterface interface { + LoadCountSignals(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } type UserCountInterface interface { LoadCountUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } @@ -10157,6 +10360,12 @@ func buildOrganizationCountThenLoader[Q orm.Loadable]() organizationCountThenLoa return retrieved.LoadCountQuicks(ctx, exec, mods...) }, ), + Signals: countThenLoadBuilder[Q]( + "Signals", + func(ctx context.Context, exec bob.Executor, retrieved SignalsCountInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadCountSignals(ctx, exec, mods...) + }, + ), User: countThenLoadBuilder[Q]( "User", func(ctx context.Context, exec bob.Executor, retrieved UserCountInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { @@ -11396,6 +11605,36 @@ func (os OrganizationSlice) LoadCountQuicks(ctx context.Context, exec bob.Execut return nil } +// LoadCountSignals loads the count of Signals into the C struct +func (o *Organization) LoadCountSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + count, err := o.Signals(mods...).Count(ctx, exec) + if err != nil { + return err + } + + o.C.Signals = &count + return nil +} + +// LoadCountSignals loads the count of Signals for a slice +func (os OrganizationSlice) LoadCountSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + for _, o := range os { + if err := o.LoadCountSignals(ctx, exec, mods...); err != nil { + return err + } + } + + return nil +} + // LoadCountUser loads the count of User into the C struct func (o *Organization) LoadCountUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { if o == nil { @@ -11471,6 +11710,7 @@ type organizationJoins[Q dialect.Joinable] struct { Nuisances modAs[Q, publicreportNuisanceColumns] PublicreportPool modAs[Q, publicreportPoolColumns] Quicks modAs[Q, publicreportQuickColumns] + Signals modAs[Q, signalColumns] User modAs[Q, userColumns] } @@ -12099,6 +12339,20 @@ func buildOrganizationJoins[Q dialect.Joinable](cols organizationColumns, typ st return mods }, }, + Signals: modAs[Q, signalColumns]{ + c: Signals.Columns, + f: func(to signalColumns) bob.Mod[Q] { + mods := make(mods.QueryMods[Q], 0, 1) + + { + mods = append(mods, dialect.Join[Q](typ, Signals.Name().As(to.Alias())).On( + to.OrganizationID.EQ(cols.ID), + )) + } + + return mods + }, + }, User: modAs[Q, userColumns]{ c: Users.Columns, f: func(to userColumns) bob.Mod[Q] { diff --git a/db/models/pool.bob.go b/db/models/pool.bob.go index 9888aaad..7333eee5 100644 --- a/db/models/pool.bob.go +++ b/db/models/pool.bob.go @@ -33,6 +33,8 @@ type Pool struct { SiteVersion int32 `db:"site_version" ` R poolR `db:"-" ` + + C poolC `db:"-" ` } // PoolSlice is an alias for a slice of pointers to Pool. @@ -47,8 +49,9 @@ type PoolsQuery = *psql.ViewQuery[*Pool, PoolSlice] // poolR is where relationships are stored. type poolR struct { - CreatorUser *User // pool.pool_creator_id_fkey - Site *Site // pool.pool_site_id_site_version_fkey + CreatorUser *User // pool.pool_creator_id_fkey + Site *Site // pool.pool_site_id_site_version_fkey + SignalPools SignalPoolSlice // signal_pool.signal_pool_pool_id_fkey } func buildPoolColumns(alias string) poolColumns { @@ -515,6 +518,30 @@ func (os PoolSlice) Site(mods ...bob.Mod[*dialect.SelectQuery]) SitesQuery { )...) } +// SignalPools starts a query for related objects on signal_pool +func (o *Pool) SignalPools(mods ...bob.Mod[*dialect.SelectQuery]) SignalPoolsQuery { + return SignalPools.Query(append(mods, + sm.Where(SignalPools.Columns.PoolID.EQ(psql.Arg(o.ID))), + )...) +} + +func (os PoolSlice) SignalPools(mods ...bob.Mod[*dialect.SelectQuery]) SignalPoolsQuery { + pkID := make(pgtypes.Array[int32], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkID = append(pkID, o.ID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkID), "integer[]")), + )) + + return SignalPools.Query(append(mods, + sm.Where(psql.Group(SignalPools.Columns.PoolID).OP("IN", PKArgExpr)), + )...) +} + func attachPoolCreatorUser0(ctx context.Context, exec bob.Executor, count int, pool0 *Pool, user1 *User) (*Pool, error) { setter := &PoolSetter{ CreatorID: omit.From(user1.ID), @@ -666,6 +693,20 @@ func (o *Pool) Preload(name string, retrieved any) error { rel.R.Pools = PoolSlice{o} } return nil + case "SignalPools": + rels, ok := retrieved.(SignalPoolSlice) + if !ok { + return fmt.Errorf("pool cannot load %T as %q", retrieved, name) + } + + o.R.SignalPools = rels + + for _, rel := range rels { + if rel != nil { + rel.R.Pool = o + } + } + return nil default: return fmt.Errorf("pool has no relationship %q", name) } @@ -710,6 +751,7 @@ func buildPoolPreloader() poolPreloader { type poolThenLoader[Q orm.Loadable] struct { CreatorUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] Site func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + SignalPools func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] } func buildPoolThenLoader[Q orm.Loadable]() poolThenLoader[Q] { @@ -719,6 +761,9 @@ func buildPoolThenLoader[Q orm.Loadable]() poolThenLoader[Q] { type SiteLoadInterface interface { LoadSite(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } + type SignalPoolsLoadInterface interface { + LoadSignalPools(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } return poolThenLoader[Q]{ CreatorUser: thenLoadBuilder[Q]( @@ -733,6 +778,12 @@ func buildPoolThenLoader[Q orm.Loadable]() poolThenLoader[Q] { return retrieved.LoadSite(ctx, exec, mods...) }, ), + SignalPools: thenLoadBuilder[Q]( + "SignalPools", + func(ctx context.Context, exec bob.Executor, retrieved SignalPoolsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadSignalPools(ctx, exec, mods...) + }, + ), } } @@ -844,10 +895,165 @@ func (os PoolSlice) LoadSite(ctx context.Context, exec bob.Executor, mods ...bob return nil } +// LoadSignalPools loads the pool's SignalPools into the .R struct +func (o *Pool) LoadSignalPools(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.SignalPools = nil + + related, err := o.SignalPools(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, rel := range related { + rel.R.Pool = o + } + + o.R.SignalPools = related + return nil +} + +// LoadSignalPools loads the pool's SignalPools into the .R struct +func (os PoolSlice) LoadSignalPools(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + signalPools, err := os.SignalPools(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + o.R.SignalPools = nil + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range signalPools { + + if !(o.ID == rel.PoolID) { + continue + } + + rel.R.Pool = o + + o.R.SignalPools = append(o.R.SignalPools, rel) + } + } + + return nil +} + +// poolC is where relationship counts are stored. +type poolC struct { + SignalPools *int64 +} + +// PreloadCount sets a count in the C struct by name +func (o *Pool) PreloadCount(name string, count int64) error { + if o == nil { + return nil + } + + switch name { + case "SignalPools": + o.C.SignalPools = &count + } + return nil +} + +type poolCountPreloader struct { + SignalPools func(...bob.Mod[*dialect.SelectQuery]) psql.Preloader +} + +func buildPoolCountPreloader() poolCountPreloader { + return poolCountPreloader{ + SignalPools: func(mods ...bob.Mod[*dialect.SelectQuery]) psql.Preloader { + return countPreloader[*Pool]("SignalPools", func(parent string) bob.Expression { + // Build a correlated subquery: (SELECT COUNT(*) FROM related WHERE fk = parent.pk) + if parent == "" { + parent = Pools.Alias() + } + + subqueryMods := []bob.Mod[*dialect.SelectQuery]{ + sm.Columns(psql.Raw("count(*)")), + + sm.From(SignalPools.Name()), + sm.Where(psql.Quote(SignalPools.Alias(), "pool_id").EQ(psql.Quote(parent, "id"))), + } + subqueryMods = append(subqueryMods, mods...) + return psql.Group(psql.Select(subqueryMods...).Expression) + }) + }, + } +} + +type poolCountThenLoader[Q orm.Loadable] struct { + SignalPools func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] +} + +func buildPoolCountThenLoader[Q orm.Loadable]() poolCountThenLoader[Q] { + type SignalPoolsCountInterface interface { + LoadCountSignalPools(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + + return poolCountThenLoader[Q]{ + SignalPools: countThenLoadBuilder[Q]( + "SignalPools", + func(ctx context.Context, exec bob.Executor, retrieved SignalPoolsCountInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadCountSignalPools(ctx, exec, mods...) + }, + ), + } +} + +// LoadCountSignalPools loads the count of SignalPools into the C struct +func (o *Pool) LoadCountSignalPools(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + count, err := o.SignalPools(mods...).Count(ctx, exec) + if err != nil { + return err + } + + o.C.SignalPools = &count + return nil +} + +// LoadCountSignalPools loads the count of SignalPools for a slice +func (os PoolSlice) LoadCountSignalPools(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + for _, o := range os { + if err := o.LoadCountSignalPools(ctx, exec, mods...); err != nil { + return err + } + } + + return nil +} + type poolJoins[Q dialect.Joinable] struct { typ string CreatorUser modAs[Q, userColumns] Site modAs[Q, siteColumns] + SignalPools modAs[Q, signalPoolColumns] } func (j poolJoins[Q]) aliasedAs(alias string) poolJoins[Q] { @@ -882,6 +1088,20 @@ func buildPoolJoins[Q dialect.Joinable](cols poolColumns, typ string) poolJoins[ )) } + return mods + }, + }, + SignalPools: modAs[Q, signalPoolColumns]{ + c: SignalPools.Columns, + f: func(to signalPoolColumns) bob.Mod[Q] { + mods := make(mods.QueryMods[Q], 0, 1) + + { + mods = append(mods, dialect.Join[Q](typ, SignalPools.Name().As(to.Alias())).On( + to.PoolID.EQ(cols.ID), + )) + } + return mods }, }, diff --git a/db/models/signal.bob.go b/db/models/signal.bob.go new file mode 100644 index 00000000..4fa502a1 --- /dev/null +++ b/db/models/signal.bob.go @@ -0,0 +1,1356 @@ +// Code generated by BobGen psql v0.42.5. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package models + +import ( + "context" + "fmt" + "io" + "time" + + "github.com/Gleipnir-Technology/bob" + "github.com/Gleipnir-Technology/bob/dialect/psql" + "github.com/Gleipnir-Technology/bob/dialect/psql/dialect" + "github.com/Gleipnir-Technology/bob/dialect/psql/dm" + "github.com/Gleipnir-Technology/bob/dialect/psql/sm" + "github.com/Gleipnir-Technology/bob/dialect/psql/um" + "github.com/Gleipnir-Technology/bob/expr" + "github.com/Gleipnir-Technology/bob/mods" + "github.com/Gleipnir-Technology/bob/orm" + "github.com/Gleipnir-Technology/bob/types/pgtypes" + enums "github.com/Gleipnir-Technology/nidus-sync/db/enums" + "github.com/aarondl/opt/null" + "github.com/aarondl/opt/omit" + "github.com/aarondl/opt/omitnull" +) + +// Signal is an object representing the database table. +type Signal struct { + Addressed null.Val[time.Time] `db:"addressed" ` + Addressor null.Val[int32] `db:"addressor" ` + Created time.Time `db:"created" ` + Creator int32 `db:"creator" ` + ID int32 `db:"id,pk" ` + OrganizationID int32 `db:"organization_id" ` + Species null.Val[enums.Mosquitospecies] `db:"species" ` + Title string `db:"title" ` + Type enums.Signaltype `db:"type_" ` + + R signalR `db:"-" ` + + C signalC `db:"-" ` +} + +// SignalSlice is an alias for a slice of pointers to Signal. +// This should almost always be used instead of []*Signal. +type SignalSlice []*Signal + +// Signals contains methods to work with the signal table +var Signals = psql.NewTablex[*Signal, SignalSlice, *SignalSetter]("", "signal", buildSignalColumns("signal")) + +// SignalsQuery is a query on the signal table +type SignalsQuery = *psql.ViewQuery[*Signal, SignalSlice] + +// signalR is where relationships are stored. +type signalR struct { + AddressorUser *User // signal.signal_addressor_fkey + CreatorUser *User // signal.signal_creator_fkey + Organization *Organization // signal.signal_organization_id_fkey + SignalPools SignalPoolSlice // signal_pool.signal_pool_signal_id_fkey +} + +func buildSignalColumns(alias string) signalColumns { + return signalColumns{ + ColumnsExpr: expr.NewColumnsExpr( + "addressed", "addressor", "created", "creator", "id", "organization_id", "species", "title", "type_", + ).WithParent("signal"), + tableAlias: alias, + Addressed: psql.Quote(alias, "addressed"), + Addressor: psql.Quote(alias, "addressor"), + Created: psql.Quote(alias, "created"), + Creator: psql.Quote(alias, "creator"), + ID: psql.Quote(alias, "id"), + OrganizationID: psql.Quote(alias, "organization_id"), + Species: psql.Quote(alias, "species"), + Title: psql.Quote(alias, "title"), + Type: psql.Quote(alias, "type_"), + } +} + +type signalColumns struct { + expr.ColumnsExpr + tableAlias string + Addressed psql.Expression + Addressor psql.Expression + Created psql.Expression + Creator psql.Expression + ID psql.Expression + OrganizationID psql.Expression + Species psql.Expression + Title psql.Expression + Type psql.Expression +} + +func (c signalColumns) Alias() string { + return c.tableAlias +} + +func (signalColumns) AliasedAs(alias string) signalColumns { + return buildSignalColumns(alias) +} + +// SignalSetter is used for insert/upsert/update operations +// All values are optional, and do not have to be set +// Generated columns are not included +type SignalSetter struct { + Addressed omitnull.Val[time.Time] `db:"addressed" ` + Addressor omitnull.Val[int32] `db:"addressor" ` + Created omit.Val[time.Time] `db:"created" ` + Creator omit.Val[int32] `db:"creator" ` + ID omit.Val[int32] `db:"id,pk" ` + OrganizationID omit.Val[int32] `db:"organization_id" ` + Species omitnull.Val[enums.Mosquitospecies] `db:"species" ` + Title omit.Val[string] `db:"title" ` + Type omit.Val[enums.Signaltype] `db:"type_" ` +} + +func (s SignalSetter) SetColumns() []string { + vals := make([]string, 0, 9) + if !s.Addressed.IsUnset() { + vals = append(vals, "addressed") + } + if !s.Addressor.IsUnset() { + vals = append(vals, "addressor") + } + if s.Created.IsValue() { + vals = append(vals, "created") + } + if s.Creator.IsValue() { + vals = append(vals, "creator") + } + if s.ID.IsValue() { + vals = append(vals, "id") + } + if s.OrganizationID.IsValue() { + vals = append(vals, "organization_id") + } + if !s.Species.IsUnset() { + vals = append(vals, "species") + } + if s.Title.IsValue() { + vals = append(vals, "title") + } + if s.Type.IsValue() { + vals = append(vals, "type_") + } + return vals +} + +func (s SignalSetter) Overwrite(t *Signal) { + if !s.Addressed.IsUnset() { + t.Addressed = s.Addressed.MustGetNull() + } + if !s.Addressor.IsUnset() { + t.Addressor = s.Addressor.MustGetNull() + } + if s.Created.IsValue() { + t.Created = s.Created.MustGet() + } + if s.Creator.IsValue() { + t.Creator = s.Creator.MustGet() + } + if s.ID.IsValue() { + t.ID = s.ID.MustGet() + } + if s.OrganizationID.IsValue() { + t.OrganizationID = s.OrganizationID.MustGet() + } + if !s.Species.IsUnset() { + t.Species = s.Species.MustGetNull() + } + if s.Title.IsValue() { + t.Title = s.Title.MustGet() + } + if s.Type.IsValue() { + t.Type = s.Type.MustGet() + } +} + +func (s *SignalSetter) Apply(q *dialect.InsertQuery) { + q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) { + return Signals.BeforeInsertHooks.RunHooks(ctx, exec, s) + }) + + q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) { + vals := make([]bob.Expression, 9) + if !s.Addressed.IsUnset() { + vals[0] = psql.Arg(s.Addressed.MustGetNull()) + } else { + vals[0] = psql.Raw("DEFAULT") + } + + if !s.Addressor.IsUnset() { + vals[1] = psql.Arg(s.Addressor.MustGetNull()) + } else { + vals[1] = psql.Raw("DEFAULT") + } + + if s.Created.IsValue() { + vals[2] = psql.Arg(s.Created.MustGet()) + } else { + vals[2] = psql.Raw("DEFAULT") + } + + if s.Creator.IsValue() { + vals[3] = psql.Arg(s.Creator.MustGet()) + } else { + vals[3] = psql.Raw("DEFAULT") + } + + if s.ID.IsValue() { + vals[4] = psql.Arg(s.ID.MustGet()) + } else { + vals[4] = psql.Raw("DEFAULT") + } + + if s.OrganizationID.IsValue() { + vals[5] = psql.Arg(s.OrganizationID.MustGet()) + } else { + vals[5] = psql.Raw("DEFAULT") + } + + if !s.Species.IsUnset() { + vals[6] = psql.Arg(s.Species.MustGetNull()) + } else { + vals[6] = psql.Raw("DEFAULT") + } + + if s.Title.IsValue() { + vals[7] = psql.Arg(s.Title.MustGet()) + } else { + vals[7] = psql.Raw("DEFAULT") + } + + if s.Type.IsValue() { + vals[8] = psql.Arg(s.Type.MustGet()) + } else { + vals[8] = psql.Raw("DEFAULT") + } + + return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "") + })) +} + +func (s SignalSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] { + return um.Set(s.Expressions()...) +} + +func (s SignalSetter) Expressions(prefix ...string) []bob.Expression { + exprs := make([]bob.Expression, 0, 9) + + if !s.Addressed.IsUnset() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "addressed")...), + psql.Arg(s.Addressed), + }}) + } + + if !s.Addressor.IsUnset() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "addressor")...), + psql.Arg(s.Addressor), + }}) + } + + if s.Created.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "created")...), + psql.Arg(s.Created), + }}) + } + + if s.Creator.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "creator")...), + psql.Arg(s.Creator), + }}) + } + + if s.ID.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "id")...), + psql.Arg(s.ID), + }}) + } + + if s.OrganizationID.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "organization_id")...), + psql.Arg(s.OrganizationID), + }}) + } + + if !s.Species.IsUnset() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "species")...), + psql.Arg(s.Species), + }}) + } + + if s.Title.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "title")...), + psql.Arg(s.Title), + }}) + } + + if s.Type.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "type_")...), + psql.Arg(s.Type), + }}) + } + + return exprs +} + +// FindSignal retrieves a single record by primary key +// If cols is empty Find will return all columns. +func FindSignal(ctx context.Context, exec bob.Executor, IDPK int32, cols ...string) (*Signal, error) { + if len(cols) == 0 { + return Signals.Query( + sm.Where(Signals.Columns.ID.EQ(psql.Arg(IDPK))), + ).One(ctx, exec) + } + + return Signals.Query( + sm.Where(Signals.Columns.ID.EQ(psql.Arg(IDPK))), + sm.Columns(Signals.Columns.Only(cols...)), + ).One(ctx, exec) +} + +// SignalExists checks the presence of a single record by primary key +func SignalExists(ctx context.Context, exec bob.Executor, IDPK int32) (bool, error) { + return Signals.Query( + sm.Where(Signals.Columns.ID.EQ(psql.Arg(IDPK))), + ).Exists(ctx, exec) +} + +// AfterQueryHook is called after Signal is retrieved from the database +func (o *Signal) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error { + var err error + + switch queryType { + case bob.QueryTypeSelect: + ctx, err = Signals.AfterSelectHooks.RunHooks(ctx, exec, SignalSlice{o}) + case bob.QueryTypeInsert: + ctx, err = Signals.AfterInsertHooks.RunHooks(ctx, exec, SignalSlice{o}) + case bob.QueryTypeUpdate: + ctx, err = Signals.AfterUpdateHooks.RunHooks(ctx, exec, SignalSlice{o}) + case bob.QueryTypeDelete: + ctx, err = Signals.AfterDeleteHooks.RunHooks(ctx, exec, SignalSlice{o}) + } + + return err +} + +// primaryKeyVals returns the primary key values of the Signal +func (o *Signal) primaryKeyVals() bob.Expression { + return psql.Arg(o.ID) +} + +func (o *Signal) pkEQ() dialect.Expression { + return psql.Quote("signal", "id").EQ(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) { + return o.primaryKeyVals().WriteSQL(ctx, w, d, start) + })) +} + +// Update uses an executor to update the Signal +func (o *Signal) Update(ctx context.Context, exec bob.Executor, s *SignalSetter) error { + v, err := Signals.Update(s.UpdateMod(), um.Where(o.pkEQ())).One(ctx, exec) + if err != nil { + return err + } + + o.R = v.R + *o = *v + + return nil +} + +// Delete deletes a single Signal record with an executor +func (o *Signal) Delete(ctx context.Context, exec bob.Executor) error { + _, err := Signals.Delete(dm.Where(o.pkEQ())).Exec(ctx, exec) + return err +} + +// Reload refreshes the Signal using the executor +func (o *Signal) Reload(ctx context.Context, exec bob.Executor) error { + o2, err := Signals.Query( + sm.Where(Signals.Columns.ID.EQ(psql.Arg(o.ID))), + ).One(ctx, exec) + if err != nil { + return err + } + o2.R = o.R + *o = *o2 + + return nil +} + +// AfterQueryHook is called after SignalSlice is retrieved from the database +func (o SignalSlice) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error { + var err error + + switch queryType { + case bob.QueryTypeSelect: + ctx, err = Signals.AfterSelectHooks.RunHooks(ctx, exec, o) + case bob.QueryTypeInsert: + ctx, err = Signals.AfterInsertHooks.RunHooks(ctx, exec, o) + case bob.QueryTypeUpdate: + ctx, err = Signals.AfterUpdateHooks.RunHooks(ctx, exec, o) + case bob.QueryTypeDelete: + ctx, err = Signals.AfterDeleteHooks.RunHooks(ctx, exec, o) + } + + return err +} + +func (o SignalSlice) pkIN() dialect.Expression { + if len(o) == 0 { + return psql.Raw("NULL") + } + + return psql.Quote("signal", "id").In(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) { + pkPairs := make([]bob.Expression, len(o)) + for i, row := range o { + pkPairs[i] = row.primaryKeyVals() + } + return bob.ExpressSlice(ctx, w, d, start, pkPairs, "", ", ", "") + })) +} + +// copyMatchingRows finds models in the given slice that have the same primary key +// then it first copies the existing relationships from the old model to the new model +// and then replaces the old model in the slice with the new model +func (o SignalSlice) copyMatchingRows(from ...*Signal) { + for i, old := range o { + for _, new := range from { + if new.ID != old.ID { + continue + } + new.R = old.R + o[i] = new + break + } + } +} + +// UpdateMod modifies an update query with "WHERE primary_key IN (o...)" +func (o SignalSlice) UpdateMod() bob.Mod[*dialect.UpdateQuery] { + return bob.ModFunc[*dialect.UpdateQuery](func(q *dialect.UpdateQuery) { + q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) { + return Signals.BeforeUpdateHooks.RunHooks(ctx, exec, o) + }) + + q.AppendLoader(bob.LoaderFunc(func(ctx context.Context, exec bob.Executor, retrieved any) error { + var err error + switch retrieved := retrieved.(type) { + case *Signal: + o.copyMatchingRows(retrieved) + case []*Signal: + o.copyMatchingRows(retrieved...) + case SignalSlice: + o.copyMatchingRows(retrieved...) + default: + // If the retrieved value is not a Signal or a slice of Signal + // then run the AfterUpdateHooks on the slice + _, err = Signals.AfterUpdateHooks.RunHooks(ctx, exec, o) + } + + return err + })) + + q.AppendWhere(o.pkIN()) + }) +} + +// DeleteMod modifies an delete query with "WHERE primary_key IN (o...)" +func (o SignalSlice) DeleteMod() bob.Mod[*dialect.DeleteQuery] { + return bob.ModFunc[*dialect.DeleteQuery](func(q *dialect.DeleteQuery) { + q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) { + return Signals.BeforeDeleteHooks.RunHooks(ctx, exec, o) + }) + + q.AppendLoader(bob.LoaderFunc(func(ctx context.Context, exec bob.Executor, retrieved any) error { + var err error + switch retrieved := retrieved.(type) { + case *Signal: + o.copyMatchingRows(retrieved) + case []*Signal: + o.copyMatchingRows(retrieved...) + case SignalSlice: + o.copyMatchingRows(retrieved...) + default: + // If the retrieved value is not a Signal or a slice of Signal + // then run the AfterDeleteHooks on the slice + _, err = Signals.AfterDeleteHooks.RunHooks(ctx, exec, o) + } + + return err + })) + + q.AppendWhere(o.pkIN()) + }) +} + +func (o SignalSlice) UpdateAll(ctx context.Context, exec bob.Executor, vals SignalSetter) error { + if len(o) == 0 { + return nil + } + + _, err := Signals.Update(vals.UpdateMod(), o.UpdateMod()).All(ctx, exec) + return err +} + +func (o SignalSlice) DeleteAll(ctx context.Context, exec bob.Executor) error { + if len(o) == 0 { + return nil + } + + _, err := Signals.Delete(o.DeleteMod()).Exec(ctx, exec) + return err +} + +func (o SignalSlice) ReloadAll(ctx context.Context, exec bob.Executor) error { + if len(o) == 0 { + return nil + } + + o2, err := Signals.Query(sm.Where(o.pkIN())).All(ctx, exec) + if err != nil { + return err + } + + o.copyMatchingRows(o2...) + + return nil +} + +// AddressorUser starts a query for related objects on user_ +func (o *Signal) AddressorUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { + return Users.Query(append(mods, + sm.Where(Users.Columns.ID.EQ(psql.Arg(o.Addressor))), + )...) +} + +func (os SignalSlice) AddressorUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { + pkAddressor := make(pgtypes.Array[null.Val[int32]], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkAddressor = append(pkAddressor, o.Addressor) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkAddressor), "integer[]")), + )) + + return Users.Query(append(mods, + sm.Where(psql.Group(Users.Columns.ID).OP("IN", PKArgExpr)), + )...) +} + +// CreatorUser starts a query for related objects on user_ +func (o *Signal) CreatorUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { + return Users.Query(append(mods, + sm.Where(Users.Columns.ID.EQ(psql.Arg(o.Creator))), + )...) +} + +func (os SignalSlice) CreatorUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { + pkCreator := make(pgtypes.Array[int32], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkCreator = append(pkCreator, o.Creator) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkCreator), "integer[]")), + )) + + return Users.Query(append(mods, + sm.Where(psql.Group(Users.Columns.ID).OP("IN", PKArgExpr)), + )...) +} + +// Organization starts a query for related objects on organization +func (o *Signal) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery { + return Organizations.Query(append(mods, + sm.Where(Organizations.Columns.ID.EQ(psql.Arg(o.OrganizationID))), + )...) +} + +func (os SignalSlice) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery { + pkOrganizationID := make(pgtypes.Array[int32], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkOrganizationID = append(pkOrganizationID, o.OrganizationID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkOrganizationID), "integer[]")), + )) + + return Organizations.Query(append(mods, + sm.Where(psql.Group(Organizations.Columns.ID).OP("IN", PKArgExpr)), + )...) +} + +// SignalPools starts a query for related objects on signal_pool +func (o *Signal) SignalPools(mods ...bob.Mod[*dialect.SelectQuery]) SignalPoolsQuery { + return SignalPools.Query(append(mods, + sm.Where(SignalPools.Columns.SignalID.EQ(psql.Arg(o.ID))), + )...) +} + +func (os SignalSlice) SignalPools(mods ...bob.Mod[*dialect.SelectQuery]) SignalPoolsQuery { + pkID := make(pgtypes.Array[int32], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkID = append(pkID, o.ID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkID), "integer[]")), + )) + + return SignalPools.Query(append(mods, + sm.Where(psql.Group(SignalPools.Columns.SignalID).OP("IN", PKArgExpr)), + )...) +} + +func attachSignalAddressorUser0(ctx context.Context, exec bob.Executor, count int, signal0 *Signal, user1 *User) (*Signal, error) { + setter := &SignalSetter{ + Addressor: omitnull.From(user1.ID), + } + + err := signal0.Update(ctx, exec, setter) + if err != nil { + return nil, fmt.Errorf("attachSignalAddressorUser0: %w", err) + } + + return signal0, nil +} + +func (signal0 *Signal) InsertAddressorUser(ctx context.Context, exec bob.Executor, related *UserSetter) error { + var err error + + user1, err := Users.Insert(related).One(ctx, exec) + if err != nil { + return fmt.Errorf("inserting related objects: %w", err) + } + + _, err = attachSignalAddressorUser0(ctx, exec, 1, signal0, user1) + if err != nil { + return err + } + + signal0.R.AddressorUser = user1 + + user1.R.AddressorSignals = append(user1.R.AddressorSignals, signal0) + + return nil +} + +func (signal0 *Signal) AttachAddressorUser(ctx context.Context, exec bob.Executor, user1 *User) error { + var err error + + _, err = attachSignalAddressorUser0(ctx, exec, 1, signal0, user1) + if err != nil { + return err + } + + signal0.R.AddressorUser = user1 + + user1.R.AddressorSignals = append(user1.R.AddressorSignals, signal0) + + return nil +} + +func attachSignalCreatorUser0(ctx context.Context, exec bob.Executor, count int, signal0 *Signal, user1 *User) (*Signal, error) { + setter := &SignalSetter{ + Creator: omit.From(user1.ID), + } + + err := signal0.Update(ctx, exec, setter) + if err != nil { + return nil, fmt.Errorf("attachSignalCreatorUser0: %w", err) + } + + return signal0, nil +} + +func (signal0 *Signal) InsertCreatorUser(ctx context.Context, exec bob.Executor, related *UserSetter) error { + var err error + + user1, err := Users.Insert(related).One(ctx, exec) + if err != nil { + return fmt.Errorf("inserting related objects: %w", err) + } + + _, err = attachSignalCreatorUser0(ctx, exec, 1, signal0, user1) + if err != nil { + return err + } + + signal0.R.CreatorUser = user1 + + user1.R.CreatorSignals = append(user1.R.CreatorSignals, signal0) + + return nil +} + +func (signal0 *Signal) AttachCreatorUser(ctx context.Context, exec bob.Executor, user1 *User) error { + var err error + + _, err = attachSignalCreatorUser0(ctx, exec, 1, signal0, user1) + if err != nil { + return err + } + + signal0.R.CreatorUser = user1 + + user1.R.CreatorSignals = append(user1.R.CreatorSignals, signal0) + + return nil +} + +func attachSignalOrganization0(ctx context.Context, exec bob.Executor, count int, signal0 *Signal, organization1 *Organization) (*Signal, error) { + setter := &SignalSetter{ + OrganizationID: omit.From(organization1.ID), + } + + err := signal0.Update(ctx, exec, setter) + if err != nil { + return nil, fmt.Errorf("attachSignalOrganization0: %w", err) + } + + return signal0, nil +} + +func (signal0 *Signal) InsertOrganization(ctx context.Context, exec bob.Executor, related *OrganizationSetter) error { + var err error + + organization1, err := Organizations.Insert(related).One(ctx, exec) + if err != nil { + return fmt.Errorf("inserting related objects: %w", err) + } + + _, err = attachSignalOrganization0(ctx, exec, 1, signal0, organization1) + if err != nil { + return err + } + + signal0.R.Organization = organization1 + + organization1.R.Signals = append(organization1.R.Signals, signal0) + + return nil +} + +func (signal0 *Signal) AttachOrganization(ctx context.Context, exec bob.Executor, organization1 *Organization) error { + var err error + + _, err = attachSignalOrganization0(ctx, exec, 1, signal0, organization1) + if err != nil { + return err + } + + signal0.R.Organization = organization1 + + organization1.R.Signals = append(organization1.R.Signals, signal0) + + return nil +} + +type signalWhere[Q psql.Filterable] struct { + Addressed psql.WhereNullMod[Q, time.Time] + Addressor psql.WhereNullMod[Q, int32] + Created psql.WhereMod[Q, time.Time] + Creator psql.WhereMod[Q, int32] + ID psql.WhereMod[Q, int32] + OrganizationID psql.WhereMod[Q, int32] + Species psql.WhereNullMod[Q, enums.Mosquitospecies] + Title psql.WhereMod[Q, string] + Type psql.WhereMod[Q, enums.Signaltype] +} + +func (signalWhere[Q]) AliasedAs(alias string) signalWhere[Q] { + return buildSignalWhere[Q](buildSignalColumns(alias)) +} + +func buildSignalWhere[Q psql.Filterable](cols signalColumns) signalWhere[Q] { + return signalWhere[Q]{ + Addressed: psql.WhereNull[Q, time.Time](cols.Addressed), + Addressor: psql.WhereNull[Q, int32](cols.Addressor), + Created: psql.Where[Q, time.Time](cols.Created), + Creator: psql.Where[Q, int32](cols.Creator), + ID: psql.Where[Q, int32](cols.ID), + OrganizationID: psql.Where[Q, int32](cols.OrganizationID), + Species: psql.WhereNull[Q, enums.Mosquitospecies](cols.Species), + Title: psql.Where[Q, string](cols.Title), + Type: psql.Where[Q, enums.Signaltype](cols.Type), + } +} + +func (o *Signal) Preload(name string, retrieved any) error { + if o == nil { + return nil + } + + switch name { + case "AddressorUser": + rel, ok := retrieved.(*User) + if !ok { + return fmt.Errorf("signal cannot load %T as %q", retrieved, name) + } + + o.R.AddressorUser = rel + + if rel != nil { + rel.R.AddressorSignals = SignalSlice{o} + } + return nil + case "CreatorUser": + rel, ok := retrieved.(*User) + if !ok { + return fmt.Errorf("signal cannot load %T as %q", retrieved, name) + } + + o.R.CreatorUser = rel + + if rel != nil { + rel.R.CreatorSignals = SignalSlice{o} + } + return nil + case "Organization": + rel, ok := retrieved.(*Organization) + if !ok { + return fmt.Errorf("signal cannot load %T as %q", retrieved, name) + } + + o.R.Organization = rel + + if rel != nil { + rel.R.Signals = SignalSlice{o} + } + return nil + case "SignalPools": + rels, ok := retrieved.(SignalPoolSlice) + if !ok { + return fmt.Errorf("signal cannot load %T as %q", retrieved, name) + } + + o.R.SignalPools = rels + + for _, rel := range rels { + if rel != nil { + rel.R.Signal = o + } + } + return nil + default: + return fmt.Errorf("signal has no relationship %q", name) + } +} + +type signalPreloader struct { + AddressorUser func(...psql.PreloadOption) psql.Preloader + CreatorUser func(...psql.PreloadOption) psql.Preloader + Organization func(...psql.PreloadOption) psql.Preloader +} + +func buildSignalPreloader() signalPreloader { + return signalPreloader{ + AddressorUser: func(opts ...psql.PreloadOption) psql.Preloader { + return psql.Preload[*User, UserSlice](psql.PreloadRel{ + Name: "AddressorUser", + Sides: []psql.PreloadSide{ + { + From: Signals, + To: Users, + FromColumns: []string{"addressor"}, + ToColumns: []string{"id"}, + }, + }, + }, Users.Columns.Names(), opts...) + }, + CreatorUser: func(opts ...psql.PreloadOption) psql.Preloader { + return psql.Preload[*User, UserSlice](psql.PreloadRel{ + Name: "CreatorUser", + Sides: []psql.PreloadSide{ + { + From: Signals, + To: Users, + FromColumns: []string{"creator"}, + ToColumns: []string{"id"}, + }, + }, + }, Users.Columns.Names(), opts...) + }, + Organization: func(opts ...psql.PreloadOption) psql.Preloader { + return psql.Preload[*Organization, OrganizationSlice](psql.PreloadRel{ + Name: "Organization", + Sides: []psql.PreloadSide{ + { + From: Signals, + To: Organizations, + FromColumns: []string{"organization_id"}, + ToColumns: []string{"id"}, + }, + }, + }, Organizations.Columns.Names(), opts...) + }, + } +} + +type signalThenLoader[Q orm.Loadable] struct { + AddressorUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + Organization func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + SignalPools func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] +} + +func buildSignalThenLoader[Q orm.Loadable]() signalThenLoader[Q] { + type AddressorUserLoadInterface interface { + LoadAddressorUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + type CreatorUserLoadInterface interface { + LoadCreatorUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + type OrganizationLoadInterface interface { + LoadOrganization(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + type SignalPoolsLoadInterface interface { + LoadSignalPools(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + + return signalThenLoader[Q]{ + AddressorUser: thenLoadBuilder[Q]( + "AddressorUser", + func(ctx context.Context, exec bob.Executor, retrieved AddressorUserLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadAddressorUser(ctx, exec, mods...) + }, + ), + CreatorUser: thenLoadBuilder[Q]( + "CreatorUser", + func(ctx context.Context, exec bob.Executor, retrieved CreatorUserLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadCreatorUser(ctx, exec, mods...) + }, + ), + Organization: thenLoadBuilder[Q]( + "Organization", + func(ctx context.Context, exec bob.Executor, retrieved OrganizationLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadOrganization(ctx, exec, mods...) + }, + ), + SignalPools: thenLoadBuilder[Q]( + "SignalPools", + func(ctx context.Context, exec bob.Executor, retrieved SignalPoolsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadSignalPools(ctx, exec, mods...) + }, + ), + } +} + +// LoadAddressorUser loads the signal's AddressorUser into the .R struct +func (o *Signal) LoadAddressorUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.AddressorUser = nil + + related, err := o.AddressorUser(mods...).One(ctx, exec) + if err != nil { + return err + } + + related.R.AddressorSignals = SignalSlice{o} + + o.R.AddressorUser = related + return nil +} + +// LoadAddressorUser loads the signal's AddressorUser into the .R struct +func (os SignalSlice) LoadAddressorUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + users, err := os.AddressorUser(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range users { + if !o.Addressor.IsValue() { + continue + } + + if !(o.Addressor.IsValue() && o.Addressor.MustGet() == rel.ID) { + continue + } + + rel.R.AddressorSignals = append(rel.R.AddressorSignals, o) + + o.R.AddressorUser = rel + break + } + } + + return nil +} + +// LoadCreatorUser loads the signal's CreatorUser into the .R struct +func (o *Signal) LoadCreatorUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.CreatorUser = nil + + related, err := o.CreatorUser(mods...).One(ctx, exec) + if err != nil { + return err + } + + related.R.CreatorSignals = SignalSlice{o} + + o.R.CreatorUser = related + return nil +} + +// LoadCreatorUser loads the signal's CreatorUser into the .R struct +func (os SignalSlice) LoadCreatorUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + users, err := os.CreatorUser(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range users { + + if !(o.Creator == rel.ID) { + continue + } + + rel.R.CreatorSignals = append(rel.R.CreatorSignals, o) + + o.R.CreatorUser = rel + break + } + } + + return nil +} + +// LoadOrganization loads the signal's Organization into the .R struct +func (o *Signal) LoadOrganization(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.Organization = nil + + related, err := o.Organization(mods...).One(ctx, exec) + if err != nil { + return err + } + + related.R.Signals = SignalSlice{o} + + o.R.Organization = related + return nil +} + +// LoadOrganization loads the signal's Organization into the .R struct +func (os SignalSlice) LoadOrganization(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + organizations, err := os.Organization(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range organizations { + + if !(o.OrganizationID == rel.ID) { + continue + } + + rel.R.Signals = append(rel.R.Signals, o) + + o.R.Organization = rel + break + } + } + + return nil +} + +// LoadSignalPools loads the signal's SignalPools into the .R struct +func (o *Signal) LoadSignalPools(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.SignalPools = nil + + related, err := o.SignalPools(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, rel := range related { + rel.R.Signal = o + } + + o.R.SignalPools = related + return nil +} + +// LoadSignalPools loads the signal's SignalPools into the .R struct +func (os SignalSlice) LoadSignalPools(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + signalPools, err := os.SignalPools(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + o.R.SignalPools = nil + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range signalPools { + + if !(o.ID == rel.SignalID) { + continue + } + + rel.R.Signal = o + + o.R.SignalPools = append(o.R.SignalPools, rel) + } + } + + return nil +} + +// signalC is where relationship counts are stored. +type signalC struct { + SignalPools *int64 +} + +// PreloadCount sets a count in the C struct by name +func (o *Signal) PreloadCount(name string, count int64) error { + if o == nil { + return nil + } + + switch name { + case "SignalPools": + o.C.SignalPools = &count + } + return nil +} + +type signalCountPreloader struct { + SignalPools func(...bob.Mod[*dialect.SelectQuery]) psql.Preloader +} + +func buildSignalCountPreloader() signalCountPreloader { + return signalCountPreloader{ + SignalPools: func(mods ...bob.Mod[*dialect.SelectQuery]) psql.Preloader { + return countPreloader[*Signal]("SignalPools", func(parent string) bob.Expression { + // Build a correlated subquery: (SELECT COUNT(*) FROM related WHERE fk = parent.pk) + if parent == "" { + parent = Signals.Alias() + } + + subqueryMods := []bob.Mod[*dialect.SelectQuery]{ + sm.Columns(psql.Raw("count(*)")), + + sm.From(SignalPools.Name()), + sm.Where(psql.Quote(SignalPools.Alias(), "signal_id").EQ(psql.Quote(parent, "id"))), + } + subqueryMods = append(subqueryMods, mods...) + return psql.Group(psql.Select(subqueryMods...).Expression) + }) + }, + } +} + +type signalCountThenLoader[Q orm.Loadable] struct { + SignalPools func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] +} + +func buildSignalCountThenLoader[Q orm.Loadable]() signalCountThenLoader[Q] { + type SignalPoolsCountInterface interface { + LoadCountSignalPools(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + + return signalCountThenLoader[Q]{ + SignalPools: countThenLoadBuilder[Q]( + "SignalPools", + func(ctx context.Context, exec bob.Executor, retrieved SignalPoolsCountInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadCountSignalPools(ctx, exec, mods...) + }, + ), + } +} + +// LoadCountSignalPools loads the count of SignalPools into the C struct +func (o *Signal) LoadCountSignalPools(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + count, err := o.SignalPools(mods...).Count(ctx, exec) + if err != nil { + return err + } + + o.C.SignalPools = &count + return nil +} + +// LoadCountSignalPools loads the count of SignalPools for a slice +func (os SignalSlice) LoadCountSignalPools(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + for _, o := range os { + if err := o.LoadCountSignalPools(ctx, exec, mods...); err != nil { + return err + } + } + + return nil +} + +type signalJoins[Q dialect.Joinable] struct { + typ string + AddressorUser modAs[Q, userColumns] + CreatorUser modAs[Q, userColumns] + Organization modAs[Q, organizationColumns] + SignalPools modAs[Q, signalPoolColumns] +} + +func (j signalJoins[Q]) aliasedAs(alias string) signalJoins[Q] { + return buildSignalJoins[Q](buildSignalColumns(alias), j.typ) +} + +func buildSignalJoins[Q dialect.Joinable](cols signalColumns, typ string) signalJoins[Q] { + return signalJoins[Q]{ + typ: typ, + AddressorUser: modAs[Q, userColumns]{ + c: Users.Columns, + f: func(to userColumns) bob.Mod[Q] { + mods := make(mods.QueryMods[Q], 0, 1) + + { + mods = append(mods, dialect.Join[Q](typ, Users.Name().As(to.Alias())).On( + to.ID.EQ(cols.Addressor), + )) + } + + return mods + }, + }, + CreatorUser: modAs[Q, userColumns]{ + c: Users.Columns, + f: func(to userColumns) bob.Mod[Q] { + mods := make(mods.QueryMods[Q], 0, 1) + + { + mods = append(mods, dialect.Join[Q](typ, Users.Name().As(to.Alias())).On( + to.ID.EQ(cols.Creator), + )) + } + + return mods + }, + }, + Organization: modAs[Q, organizationColumns]{ + c: Organizations.Columns, + f: func(to organizationColumns) bob.Mod[Q] { + mods := make(mods.QueryMods[Q], 0, 1) + + { + mods = append(mods, dialect.Join[Q](typ, Organizations.Name().As(to.Alias())).On( + to.ID.EQ(cols.OrganizationID), + )) + } + + return mods + }, + }, + SignalPools: modAs[Q, signalPoolColumns]{ + c: SignalPools.Columns, + f: func(to signalPoolColumns) bob.Mod[Q] { + mods := make(mods.QueryMods[Q], 0, 1) + + { + mods = append(mods, dialect.Join[Q](typ, SignalPools.Name().As(to.Alias())).On( + to.SignalID.EQ(cols.ID), + )) + } + + return mods + }, + }, + } +} diff --git a/db/models/signal_pool.bob.go b/db/models/signal_pool.bob.go new file mode 100644 index 00000000..a13d2271 --- /dev/null +++ b/db/models/signal_pool.bob.go @@ -0,0 +1,478 @@ +// Code generated by BobGen psql v0.42.5. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package models + +import ( + "context" + "fmt" + "io" + + "github.com/Gleipnir-Technology/bob" + "github.com/Gleipnir-Technology/bob/dialect/psql" + "github.com/Gleipnir-Technology/bob/dialect/psql/dialect" + "github.com/Gleipnir-Technology/bob/dialect/psql/sm" + "github.com/Gleipnir-Technology/bob/dialect/psql/um" + "github.com/Gleipnir-Technology/bob/expr" + "github.com/Gleipnir-Technology/bob/mods" + "github.com/Gleipnir-Technology/bob/orm" + "github.com/Gleipnir-Technology/bob/types/pgtypes" + "github.com/aarondl/opt/omit" +) + +// SignalPool is an object representing the database table. +type SignalPool struct { + PoolID int32 `db:"pool_id" ` + SignalID int32 `db:"signal_id" ` + + R signalPoolR `db:"-" ` +} + +// SignalPoolSlice is an alias for a slice of pointers to SignalPool. +// This should almost always be used instead of []*SignalPool. +type SignalPoolSlice []*SignalPool + +// SignalPools contains methods to work with the signal_pool view +var SignalPools = psql.NewViewx[*SignalPool, SignalPoolSlice]("", "signal_pool", buildSignalPoolColumns("signal_pool")) + +// SignalPoolsQuery is a query on the signal_pool view +type SignalPoolsQuery = *psql.ViewQuery[*SignalPool, SignalPoolSlice] + +// signalPoolR is where relationships are stored. +type signalPoolR struct { + Pool *Pool // signal_pool.signal_pool_pool_id_fkey + Signal *Signal // signal_pool.signal_pool_signal_id_fkey +} + +func buildSignalPoolColumns(alias string) signalPoolColumns { + return signalPoolColumns{ + ColumnsExpr: expr.NewColumnsExpr( + "pool_id", "signal_id", + ).WithParent("signal_pool"), + tableAlias: alias, + PoolID: psql.Quote(alias, "pool_id"), + SignalID: psql.Quote(alias, "signal_id"), + } +} + +type signalPoolColumns struct { + expr.ColumnsExpr + tableAlias string + PoolID psql.Expression + SignalID psql.Expression +} + +func (c signalPoolColumns) Alias() string { + return c.tableAlias +} + +func (signalPoolColumns) AliasedAs(alias string) signalPoolColumns { + return buildSignalPoolColumns(alias) +} + +// SignalPoolSetter is used for insert/upsert/update operations +// All values are optional, and do not have to be set +// Generated columns are not included +type SignalPoolSetter struct { + PoolID omit.Val[int32] `db:"pool_id" ` + SignalID omit.Val[int32] `db:"signal_id" ` +} + +func (s SignalPoolSetter) SetColumns() []string { + vals := make([]string, 0, 2) + if s.PoolID.IsValue() { + vals = append(vals, "pool_id") + } + if s.SignalID.IsValue() { + vals = append(vals, "signal_id") + } + return vals +} + +func (s SignalPoolSetter) Overwrite(t *SignalPool) { + if s.PoolID.IsValue() { + t.PoolID = s.PoolID.MustGet() + } + if s.SignalID.IsValue() { + t.SignalID = s.SignalID.MustGet() + } +} + +func (s *SignalPoolSetter) Apply(q *dialect.InsertQuery) { + q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) { + vals := make([]bob.Expression, 2) + if s.PoolID.IsValue() { + vals[0] = psql.Arg(s.PoolID.MustGet()) + } else { + vals[0] = psql.Raw("DEFAULT") + } + + if s.SignalID.IsValue() { + vals[1] = psql.Arg(s.SignalID.MustGet()) + } else { + vals[1] = psql.Raw("DEFAULT") + } + + return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "") + })) +} + +func (s SignalPoolSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] { + return um.Set(s.Expressions()...) +} + +func (s SignalPoolSetter) Expressions(prefix ...string) []bob.Expression { + exprs := make([]bob.Expression, 0, 2) + + if s.PoolID.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "pool_id")...), + psql.Arg(s.PoolID), + }}) + } + + if s.SignalID.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "signal_id")...), + psql.Arg(s.SignalID), + }}) + } + + return exprs +} + +// AfterQueryHook is called after SignalPool is retrieved from the database +func (o *SignalPool) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error { + var err error + + switch queryType { + case bob.QueryTypeSelect: + ctx, err = SignalPools.AfterSelectHooks.RunHooks(ctx, exec, SignalPoolSlice{o}) + } + + return err +} + +// AfterQueryHook is called after SignalPoolSlice is retrieved from the database +func (o SignalPoolSlice) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error { + var err error + + switch queryType { + case bob.QueryTypeSelect: + ctx, err = SignalPools.AfterSelectHooks.RunHooks(ctx, exec, o) + } + + return err +} + +// Pool starts a query for related objects on pool +func (o *SignalPool) Pool(mods ...bob.Mod[*dialect.SelectQuery]) PoolsQuery { + return Pools.Query(append(mods, + sm.Where(Pools.Columns.ID.EQ(psql.Arg(o.PoolID))), + )...) +} + +func (os SignalPoolSlice) Pool(mods ...bob.Mod[*dialect.SelectQuery]) PoolsQuery { + pkPoolID := make(pgtypes.Array[int32], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkPoolID = append(pkPoolID, o.PoolID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkPoolID), "integer[]")), + )) + + return Pools.Query(append(mods, + sm.Where(psql.Group(Pools.Columns.ID).OP("IN", PKArgExpr)), + )...) +} + +// Signal starts a query for related objects on signal +func (o *SignalPool) Signal(mods ...bob.Mod[*dialect.SelectQuery]) SignalsQuery { + return Signals.Query(append(mods, + sm.Where(Signals.Columns.ID.EQ(psql.Arg(o.SignalID))), + )...) +} + +func (os SignalPoolSlice) Signal(mods ...bob.Mod[*dialect.SelectQuery]) SignalsQuery { + pkSignalID := make(pgtypes.Array[int32], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkSignalID = append(pkSignalID, o.SignalID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkSignalID), "integer[]")), + )) + + return Signals.Query(append(mods, + sm.Where(psql.Group(Signals.Columns.ID).OP("IN", PKArgExpr)), + )...) +} + +type signalPoolWhere[Q psql.Filterable] struct { + PoolID psql.WhereMod[Q, int32] + SignalID psql.WhereMod[Q, int32] +} + +func (signalPoolWhere[Q]) AliasedAs(alias string) signalPoolWhere[Q] { + return buildSignalPoolWhere[Q](buildSignalPoolColumns(alias)) +} + +func buildSignalPoolWhere[Q psql.Filterable](cols signalPoolColumns) signalPoolWhere[Q] { + return signalPoolWhere[Q]{ + PoolID: psql.Where[Q, int32](cols.PoolID), + SignalID: psql.Where[Q, int32](cols.SignalID), + } +} + +func (o *SignalPool) Preload(name string, retrieved any) error { + if o == nil { + return nil + } + + switch name { + case "Pool": + rel, ok := retrieved.(*Pool) + if !ok { + return fmt.Errorf("signalPool cannot load %T as %q", retrieved, name) + } + + o.R.Pool = rel + + if rel != nil { + rel.R.SignalPools = SignalPoolSlice{o} + } + return nil + case "Signal": + rel, ok := retrieved.(*Signal) + if !ok { + return fmt.Errorf("signalPool cannot load %T as %q", retrieved, name) + } + + o.R.Signal = rel + + if rel != nil { + rel.R.SignalPools = SignalPoolSlice{o} + } + return nil + default: + return fmt.Errorf("signalPool has no relationship %q", name) + } +} + +type signalPoolPreloader struct { + Pool func(...psql.PreloadOption) psql.Preloader + Signal func(...psql.PreloadOption) psql.Preloader +} + +func buildSignalPoolPreloader() signalPoolPreloader { + return signalPoolPreloader{ + Pool: func(opts ...psql.PreloadOption) psql.Preloader { + return psql.Preload[*Pool, PoolSlice](psql.PreloadRel{ + Name: "Pool", + Sides: []psql.PreloadSide{ + { + From: SignalPools, + To: Pools, + FromColumns: []string{"pool_id"}, + ToColumns: []string{"id"}, + }, + }, + }, Pools.Columns.Names(), opts...) + }, + Signal: func(opts ...psql.PreloadOption) psql.Preloader { + return psql.Preload[*Signal, SignalSlice](psql.PreloadRel{ + Name: "Signal", + Sides: []psql.PreloadSide{ + { + From: SignalPools, + To: Signals, + FromColumns: []string{"signal_id"}, + ToColumns: []string{"id"}, + }, + }, + }, Signals.Columns.Names(), opts...) + }, + } +} + +type signalPoolThenLoader[Q orm.Loadable] struct { + Pool func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + Signal func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] +} + +func buildSignalPoolThenLoader[Q orm.Loadable]() signalPoolThenLoader[Q] { + type PoolLoadInterface interface { + LoadPool(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + type SignalLoadInterface interface { + LoadSignal(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + + return signalPoolThenLoader[Q]{ + Pool: thenLoadBuilder[Q]( + "Pool", + func(ctx context.Context, exec bob.Executor, retrieved PoolLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadPool(ctx, exec, mods...) + }, + ), + Signal: thenLoadBuilder[Q]( + "Signal", + func(ctx context.Context, exec bob.Executor, retrieved SignalLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadSignal(ctx, exec, mods...) + }, + ), + } +} + +// LoadPool loads the signalPool's Pool into the .R struct +func (o *SignalPool) LoadPool(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.Pool = nil + + related, err := o.Pool(mods...).One(ctx, exec) + if err != nil { + return err + } + + related.R.SignalPools = SignalPoolSlice{o} + + o.R.Pool = related + return nil +} + +// LoadPool loads the signalPool's Pool into the .R struct +func (os SignalPoolSlice) LoadPool(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + pools, err := os.Pool(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range pools { + + if !(o.PoolID == rel.ID) { + continue + } + + rel.R.SignalPools = append(rel.R.SignalPools, o) + + o.R.Pool = rel + break + } + } + + return nil +} + +// LoadSignal loads the signalPool's Signal into the .R struct +func (o *SignalPool) LoadSignal(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.Signal = nil + + related, err := o.Signal(mods...).One(ctx, exec) + if err != nil { + return err + } + + related.R.SignalPools = SignalPoolSlice{o} + + o.R.Signal = related + return nil +} + +// LoadSignal loads the signalPool's Signal into the .R struct +func (os SignalPoolSlice) LoadSignal(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + signals, err := os.Signal(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range signals { + + if !(o.SignalID == rel.ID) { + continue + } + + rel.R.SignalPools = append(rel.R.SignalPools, o) + + o.R.Signal = rel + break + } + } + + return nil +} + +type signalPoolJoins[Q dialect.Joinable] struct { + typ string + Pool modAs[Q, poolColumns] + Signal modAs[Q, signalColumns] +} + +func (j signalPoolJoins[Q]) aliasedAs(alias string) signalPoolJoins[Q] { + return buildSignalPoolJoins[Q](buildSignalPoolColumns(alias), j.typ) +} + +func buildSignalPoolJoins[Q dialect.Joinable](cols signalPoolColumns, typ string) signalPoolJoins[Q] { + return signalPoolJoins[Q]{ + typ: typ, + Pool: modAs[Q, poolColumns]{ + c: Pools.Columns, + f: func(to poolColumns) bob.Mod[Q] { + mods := make(mods.QueryMods[Q], 0, 1) + + { + mods = append(mods, dialect.Join[Q](typ, Pools.Name().As(to.Alias())).On( + to.ID.EQ(cols.PoolID), + )) + } + + return mods + }, + }, + Signal: modAs[Q, signalColumns]{ + c: Signals.Columns, + f: func(to signalColumns) bob.Mod[Q] { + mods := make(mods.QueryMods[Q], 0, 1) + + { + mods = append(mods, dialect.Join[Q](typ, Signals.Name().As(to.Alias())).On( + to.ID.EQ(cols.SignalID), + )) + } + + return mods + }, + }, + } +} diff --git a/db/models/user_.bob.go b/db/models/user_.bob.go index bc742c07..40e9a697 100644 --- a/db/models/user_.bob.go +++ b/db/models/user_.bob.go @@ -70,6 +70,8 @@ type userR struct { UserNotifications NotificationSlice // notification.notification_user_id_fkey CreatorPools PoolSlice // pool.pool_creator_id_fkey CreatorResidents ResidentSlice // resident.resident_creator_fkey + AddressorSignals SignalSlice // signal.signal_addressor_fkey + CreatorSignals SignalSlice // signal.signal_creator_fkey CreatorSites SiteSlice // site.site_creator_id_fkey Organization *Organization // user_.user__organization_id_fkey } @@ -928,6 +930,54 @@ func (os UserSlice) CreatorResidents(mods ...bob.Mod[*dialect.SelectQuery]) Resi )...) } +// AddressorSignals starts a query for related objects on signal +func (o *User) AddressorSignals(mods ...bob.Mod[*dialect.SelectQuery]) SignalsQuery { + return Signals.Query(append(mods, + sm.Where(Signals.Columns.Addressor.EQ(psql.Arg(o.ID))), + )...) +} + +func (os UserSlice) AddressorSignals(mods ...bob.Mod[*dialect.SelectQuery]) SignalsQuery { + pkID := make(pgtypes.Array[int32], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkID = append(pkID, o.ID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkID), "integer[]")), + )) + + return Signals.Query(append(mods, + sm.Where(psql.Group(Signals.Columns.Addressor).OP("IN", PKArgExpr)), + )...) +} + +// CreatorSignals starts a query for related objects on signal +func (o *User) CreatorSignals(mods ...bob.Mod[*dialect.SelectQuery]) SignalsQuery { + return Signals.Query(append(mods, + sm.Where(Signals.Columns.Creator.EQ(psql.Arg(o.ID))), + )...) +} + +func (os UserSlice) CreatorSignals(mods ...bob.Mod[*dialect.SelectQuery]) SignalsQuery { + pkID := make(pgtypes.Array[int32], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkID = append(pkID, o.ID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkID), "integer[]")), + )) + + return Signals.Query(append(mods, + sm.Where(psql.Group(Signals.Columns.Creator).OP("IN", PKArgExpr)), + )...) +} + // CreatorSites starts a query for related objects on site func (o *User) CreatorSites(mods ...bob.Mod[*dialect.SelectQuery]) SitesQuery { return Sites.Query(append(mods, @@ -1792,6 +1842,142 @@ func (user0 *User) AttachCreatorResidents(ctx context.Context, exec bob.Executor return nil } +func insertUserAddressorSignals0(ctx context.Context, exec bob.Executor, signals1 []*SignalSetter, user0 *User) (SignalSlice, error) { + for i := range signals1 { + signals1[i].Addressor = omitnull.From(user0.ID) + } + + ret, err := Signals.Insert(bob.ToMods(signals1...)).All(ctx, exec) + if err != nil { + return ret, fmt.Errorf("insertUserAddressorSignals0: %w", err) + } + + return ret, nil +} + +func attachUserAddressorSignals0(ctx context.Context, exec bob.Executor, count int, signals1 SignalSlice, user0 *User) (SignalSlice, error) { + setter := &SignalSetter{ + Addressor: omitnull.From(user0.ID), + } + + err := signals1.UpdateAll(ctx, exec, *setter) + if err != nil { + return nil, fmt.Errorf("attachUserAddressorSignals0: %w", err) + } + + return signals1, nil +} + +func (user0 *User) InsertAddressorSignals(ctx context.Context, exec bob.Executor, related ...*SignalSetter) error { + if len(related) == 0 { + return nil + } + + var err error + + signals1, err := insertUserAddressorSignals0(ctx, exec, related, user0) + if err != nil { + return err + } + + user0.R.AddressorSignals = append(user0.R.AddressorSignals, signals1...) + + for _, rel := range signals1 { + rel.R.AddressorUser = user0 + } + return nil +} + +func (user0 *User) AttachAddressorSignals(ctx context.Context, exec bob.Executor, related ...*Signal) error { + if len(related) == 0 { + return nil + } + + var err error + signals1 := SignalSlice(related) + + _, err = attachUserAddressorSignals0(ctx, exec, len(related), signals1, user0) + if err != nil { + return err + } + + user0.R.AddressorSignals = append(user0.R.AddressorSignals, signals1...) + + for _, rel := range related { + rel.R.AddressorUser = user0 + } + + return nil +} + +func insertUserCreatorSignals0(ctx context.Context, exec bob.Executor, signals1 []*SignalSetter, user0 *User) (SignalSlice, error) { + for i := range signals1 { + signals1[i].Creator = omit.From(user0.ID) + } + + ret, err := Signals.Insert(bob.ToMods(signals1...)).All(ctx, exec) + if err != nil { + return ret, fmt.Errorf("insertUserCreatorSignals0: %w", err) + } + + return ret, nil +} + +func attachUserCreatorSignals0(ctx context.Context, exec bob.Executor, count int, signals1 SignalSlice, user0 *User) (SignalSlice, error) { + setter := &SignalSetter{ + Creator: omit.From(user0.ID), + } + + err := signals1.UpdateAll(ctx, exec, *setter) + if err != nil { + return nil, fmt.Errorf("attachUserCreatorSignals0: %w", err) + } + + return signals1, nil +} + +func (user0 *User) InsertCreatorSignals(ctx context.Context, exec bob.Executor, related ...*SignalSetter) error { + if len(related) == 0 { + return nil + } + + var err error + + signals1, err := insertUserCreatorSignals0(ctx, exec, related, user0) + if err != nil { + return err + } + + user0.R.CreatorSignals = append(user0.R.CreatorSignals, signals1...) + + for _, rel := range signals1 { + rel.R.CreatorUser = user0 + } + return nil +} + +func (user0 *User) AttachCreatorSignals(ctx context.Context, exec bob.Executor, related ...*Signal) error { + if len(related) == 0 { + return nil + } + + var err error + signals1 := SignalSlice(related) + + _, err = attachUserCreatorSignals0(ctx, exec, len(related), signals1, user0) + if err != nil { + return err + } + + user0.R.CreatorSignals = append(user0.R.CreatorSignals, signals1...) + + for _, rel := range related { + rel.R.CreatorUser = user0 + } + + return nil +} + func insertUserCreatorSites0(ctx context.Context, exec bob.Executor, sites1 []*SiteSetter, user0 *User) (SiteSlice, error) { for i := range sites1 { sites1[i].CreatorID = omit.From(user0.ID) @@ -2114,6 +2300,34 @@ func (o *User) Preload(name string, retrieved any) error { o.R.CreatorResidents = rels + for _, rel := range rels { + if rel != nil { + rel.R.CreatorUser = o + } + } + return nil + case "AddressorSignals": + rels, ok := retrieved.(SignalSlice) + if !ok { + return fmt.Errorf("user cannot load %T as %q", retrieved, name) + } + + o.R.AddressorSignals = rels + + for _, rel := range rels { + if rel != nil { + rel.R.AddressorUser = o + } + } + return nil + case "CreatorSignals": + rels, ok := retrieved.(SignalSlice) + if !ok { + return fmt.Errorf("user cannot load %T as %q", retrieved, name) + } + + o.R.CreatorSignals = rels + for _, rel := range rels { if rel != nil { rel.R.CreatorUser = o @@ -2186,6 +2400,8 @@ type userThenLoader[Q orm.Loadable] struct { UserNotifications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] CreatorPools func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] CreatorResidents func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + AddressorSignals func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorSignals func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] CreatorSites func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] Organization func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] } @@ -2227,6 +2443,12 @@ func buildUserThenLoader[Q orm.Loadable]() userThenLoader[Q] { type CreatorResidentsLoadInterface interface { LoadCreatorResidents(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } + type AddressorSignalsLoadInterface interface { + LoadAddressorSignals(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + type CreatorSignalsLoadInterface interface { + LoadCreatorSignals(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } type CreatorSitesLoadInterface interface { LoadCreatorSites(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } @@ -2307,6 +2529,18 @@ func buildUserThenLoader[Q orm.Loadable]() userThenLoader[Q] { return retrieved.LoadCreatorResidents(ctx, exec, mods...) }, ), + AddressorSignals: thenLoadBuilder[Q]( + "AddressorSignals", + func(ctx context.Context, exec bob.Executor, retrieved AddressorSignalsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadAddressorSignals(ctx, exec, mods...) + }, + ), + CreatorSignals: thenLoadBuilder[Q]( + "CreatorSignals", + func(ctx context.Context, exec bob.Executor, retrieved CreatorSignalsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadCreatorSignals(ctx, exec, mods...) + }, + ), CreatorSites: thenLoadBuilder[Q]( "CreatorSites", func(ctx context.Context, exec bob.Executor, retrieved CreatorSitesLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { @@ -3060,6 +3294,131 @@ func (os UserSlice) LoadCreatorResidents(ctx context.Context, exec bob.Executor, return nil } +// LoadAddressorSignals loads the user's AddressorSignals into the .R struct +func (o *User) LoadAddressorSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.AddressorSignals = nil + + related, err := o.AddressorSignals(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, rel := range related { + rel.R.AddressorUser = o + } + + o.R.AddressorSignals = related + return nil +} + +// LoadAddressorSignals loads the user's AddressorSignals into the .R struct +func (os UserSlice) LoadAddressorSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + signals, err := os.AddressorSignals(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + o.R.AddressorSignals = nil + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range signals { + + if !rel.Addressor.IsValue() { + continue + } + if !(rel.Addressor.IsValue() && o.ID == rel.Addressor.MustGet()) { + continue + } + + rel.R.AddressorUser = o + + o.R.AddressorSignals = append(o.R.AddressorSignals, rel) + } + } + + return nil +} + +// LoadCreatorSignals loads the user's CreatorSignals into the .R struct +func (o *User) LoadCreatorSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.CreatorSignals = nil + + related, err := o.CreatorSignals(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, rel := range related { + rel.R.CreatorUser = o + } + + o.R.CreatorSignals = related + return nil +} + +// LoadCreatorSignals loads the user's CreatorSignals into the .R struct +func (os UserSlice) LoadCreatorSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + signals, err := os.CreatorSignals(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + o.R.CreatorSignals = nil + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range signals { + + if !(o.ID == rel.Creator) { + continue + } + + rel.R.CreatorUser = o + + o.R.CreatorSignals = append(o.R.CreatorSignals, rel) + } + } + + return nil +} + // LoadCreatorSites loads the user's CreatorSites into the .R struct func (o *User) LoadCreatorSites(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { if o == nil { @@ -3187,6 +3546,8 @@ type userC struct { UserNotifications *int64 CreatorPools *int64 CreatorResidents *int64 + AddressorSignals *int64 + CreatorSignals *int64 CreatorSites *int64 } @@ -3221,6 +3582,10 @@ func (o *User) PreloadCount(name string, count int64) error { o.C.CreatorPools = &count case "CreatorResidents": o.C.CreatorResidents = &count + case "AddressorSignals": + o.C.AddressorSignals = &count + case "CreatorSignals": + o.C.CreatorSignals = &count case "CreatorSites": o.C.CreatorSites = &count } @@ -3240,6 +3605,8 @@ type userCountPreloader struct { UserNotifications func(...bob.Mod[*dialect.SelectQuery]) psql.Preloader CreatorPools func(...bob.Mod[*dialect.SelectQuery]) psql.Preloader CreatorResidents func(...bob.Mod[*dialect.SelectQuery]) psql.Preloader + AddressorSignals func(...bob.Mod[*dialect.SelectQuery]) psql.Preloader + CreatorSignals func(...bob.Mod[*dialect.SelectQuery]) psql.Preloader CreatorSites func(...bob.Mod[*dialect.SelectQuery]) psql.Preloader } @@ -3449,6 +3816,40 @@ func buildUserCountPreloader() userCountPreloader { return psql.Group(psql.Select(subqueryMods...).Expression) }) }, + AddressorSignals: func(mods ...bob.Mod[*dialect.SelectQuery]) psql.Preloader { + return countPreloader[*User]("AddressorSignals", func(parent string) bob.Expression { + // Build a correlated subquery: (SELECT COUNT(*) FROM related WHERE fk = parent.pk) + if parent == "" { + parent = Users.Alias() + } + + subqueryMods := []bob.Mod[*dialect.SelectQuery]{ + sm.Columns(psql.Raw("count(*)")), + + sm.From(Signals.Name()), + sm.Where(psql.Quote(Signals.Alias(), "addressor").EQ(psql.Quote(parent, "id"))), + } + subqueryMods = append(subqueryMods, mods...) + return psql.Group(psql.Select(subqueryMods...).Expression) + }) + }, + CreatorSignals: func(mods ...bob.Mod[*dialect.SelectQuery]) psql.Preloader { + return countPreloader[*User]("CreatorSignals", func(parent string) bob.Expression { + // Build a correlated subquery: (SELECT COUNT(*) FROM related WHERE fk = parent.pk) + if parent == "" { + parent = Users.Alias() + } + + subqueryMods := []bob.Mod[*dialect.SelectQuery]{ + sm.Columns(psql.Raw("count(*)")), + + sm.From(Signals.Name()), + sm.Where(psql.Quote(Signals.Alias(), "creator").EQ(psql.Quote(parent, "id"))), + } + subqueryMods = append(subqueryMods, mods...) + return psql.Group(psql.Select(subqueryMods...).Expression) + }) + }, CreatorSites: func(mods ...bob.Mod[*dialect.SelectQuery]) psql.Preloader { return countPreloader[*User]("CreatorSites", func(parent string) bob.Expression { // Build a correlated subquery: (SELECT COUNT(*) FROM related WHERE fk = parent.pk) @@ -3482,6 +3883,8 @@ type userCountThenLoader[Q orm.Loadable] struct { UserNotifications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] CreatorPools func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] CreatorResidents func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + AddressorSignals func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorSignals func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] CreatorSites func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] } @@ -3522,6 +3925,12 @@ func buildUserCountThenLoader[Q orm.Loadable]() userCountThenLoader[Q] { type CreatorResidentsCountInterface interface { LoadCountCreatorResidents(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } + type AddressorSignalsCountInterface interface { + LoadCountAddressorSignals(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + type CreatorSignalsCountInterface interface { + LoadCountCreatorSignals(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } type CreatorSitesCountInterface interface { LoadCountCreatorSites(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } @@ -3599,6 +4008,18 @@ func buildUserCountThenLoader[Q orm.Loadable]() userCountThenLoader[Q] { return retrieved.LoadCountCreatorResidents(ctx, exec, mods...) }, ), + AddressorSignals: countThenLoadBuilder[Q]( + "AddressorSignals", + func(ctx context.Context, exec bob.Executor, retrieved AddressorSignalsCountInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadCountAddressorSignals(ctx, exec, mods...) + }, + ), + CreatorSignals: countThenLoadBuilder[Q]( + "CreatorSignals", + func(ctx context.Context, exec bob.Executor, retrieved CreatorSignalsCountInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadCountCreatorSignals(ctx, exec, mods...) + }, + ), CreatorSites: countThenLoadBuilder[Q]( "CreatorSites", func(ctx context.Context, exec bob.Executor, retrieved CreatorSitesCountInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { @@ -3968,6 +4389,66 @@ func (os UserSlice) LoadCountCreatorResidents(ctx context.Context, exec bob.Exec return nil } +// LoadCountAddressorSignals loads the count of AddressorSignals into the C struct +func (o *User) LoadCountAddressorSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + count, err := o.AddressorSignals(mods...).Count(ctx, exec) + if err != nil { + return err + } + + o.C.AddressorSignals = &count + return nil +} + +// LoadCountAddressorSignals loads the count of AddressorSignals for a slice +func (os UserSlice) LoadCountAddressorSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + for _, o := range os { + if err := o.LoadCountAddressorSignals(ctx, exec, mods...); err != nil { + return err + } + } + + return nil +} + +// LoadCountCreatorSignals loads the count of CreatorSignals into the C struct +func (o *User) LoadCountCreatorSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + count, err := o.CreatorSignals(mods...).Count(ctx, exec) + if err != nil { + return err + } + + o.C.CreatorSignals = &count + return nil +} + +// LoadCountCreatorSignals loads the count of CreatorSignals for a slice +func (os UserSlice) LoadCountCreatorSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + for _, o := range os { + if err := o.LoadCountCreatorSignals(ctx, exec, mods...); err != nil { + return err + } + } + + return nil +} + // LoadCountCreatorSites loads the count of CreatorSites into the C struct func (o *User) LoadCountCreatorSites(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { if o == nil { @@ -4012,6 +4493,8 @@ type userJoins[Q dialect.Joinable] struct { UserNotifications modAs[Q, notificationColumns] CreatorPools modAs[Q, poolColumns] CreatorResidents modAs[Q, residentColumns] + AddressorSignals modAs[Q, signalColumns] + CreatorSignals modAs[Q, signalColumns] CreatorSites modAs[Q, siteColumns] Organization modAs[Q, organizationColumns] } @@ -4191,6 +4674,34 @@ func buildUserJoins[Q dialect.Joinable](cols userColumns, typ string) userJoins[ return mods }, }, + AddressorSignals: modAs[Q, signalColumns]{ + c: Signals.Columns, + f: func(to signalColumns) bob.Mod[Q] { + mods := make(mods.QueryMods[Q], 0, 1) + + { + mods = append(mods, dialect.Join[Q](typ, Signals.Name().As(to.Alias())).On( + to.Addressor.EQ(cols.ID), + )) + } + + return mods + }, + }, + CreatorSignals: modAs[Q, signalColumns]{ + c: Signals.Columns, + f: func(to signalColumns) bob.Mod[Q] { + mods := make(mods.QueryMods[Q], 0, 1) + + { + mods = append(mods, dialect.Join[Q](typ, Signals.Name().As(to.Alias())).On( + to.Creator.EQ(cols.ID), + )) + } + + return mods + }, + }, CreatorSites: modAs[Q, siteColumns]{ c: Sites.Columns, f: func(to siteColumns) bob.Mod[Q] {