From e1bcbf79b1534813bc6f11bec1da5c9325a83be7 Mon Sep 17 00:00:00 2001 From: Eli Ribble Date: Fri, 6 Mar 2026 21:13:32 +0000 Subject: [PATCH] Add tile cache and relationship to organization map layer --- db/bobgen.yaml | 3 +- db/dberrors/tile.cached_image.bob.go | 17 ++ db/dbinfo/organization.bob.go | 24 +- db/dbinfo/tile.cached_image.bob.go | 159 ++++++++++++ db/migrations/00092_tile_cache.sql | 14 + db/models/arcgis.service_map.bob.go | 296 ++++++++++++++++++++- db/models/bob_loaders.bob.go | 4 + db/models/bob_where.bob.go | 3 + db/models/organization.bob.go | 197 +++++++++++++- db/models/tile.cached_image.bob.go | 370 +++++++++++++++++++++++++++ platform/geocode/geocode.go | 4 +- 11 files changed, 1080 insertions(+), 11 deletions(-) create mode 100644 db/dberrors/tile.cached_image.bob.go create mode 100644 db/dbinfo/tile.cached_image.bob.go create mode 100644 db/migrations/00092_tile_cache.sql create mode 100644 db/models/tile.cached_image.bob.go diff --git a/db/bobgen.yaml b/db/bobgen.yaml index c65e2027..eda0546d 100644 --- a/db/bobgen.yaml +++ b/db/bobgen.yaml @@ -20,10 +20,11 @@ psql: schemas: - "arcgis" - "comms" + - "fieldseeker" - "fileupload" - "public" - "publicreport" - - "fieldseeker" + - "tile" shared_schema: "public" queries: - ./sql diff --git a/db/dberrors/tile.cached_image.bob.go b/db/dberrors/tile.cached_image.bob.go new file mode 100644 index 00000000..71befdba --- /dev/null +++ b/db/dberrors/tile.cached_image.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 TileCachedImageErrors = &tileCachedImageErrors{ + ErrUniqueCachedImageArcgisIdXYZKey: &UniqueConstraintError{ + schema: "tile", + table: "cached_image", + columns: []string{"arcgis_id", "x", "y", "z"}, + s: "cached_image_arcgis_id_x_y_z_key", + }, +} + +type tileCachedImageErrors struct { + ErrUniqueCachedImageArcgisIdXYZKey *UniqueConstraintError +} diff --git a/db/dbinfo/organization.bob.go b/db/dbinfo/organization.bob.go index 51a1a352..68f13775 100644 --- a/db/dbinfo/organization.bob.go +++ b/db/dbinfo/organization.bob.go @@ -303,6 +303,15 @@ var Organizations = Table[ Generated: false, AutoIncr: false, }, + ArcgisMapServiceID: column{ + Name: "arcgis_map_service_id", + DBType: "text", + Default: "NULL", + Comment: "", + Nullable: true, + Generated: false, + AutoIncr: false, + }, }, Indexes: organizationIndexes{ OrganizationPkey: index{ @@ -372,6 +381,15 @@ var Organizations = Table[ ForeignTable: "arcgis.account", ForeignColumns: []string{"id"}, }, + OrganizationOrganizationArcgisMapServiceIDFkey: foreignKey{ + constraint: constraint{ + Name: "organization.organization_arcgis_map_service_id_fkey", + Columns: []string{"arcgis_map_service_id"}, + Comment: "", + }, + ForeignTable: "arcgis.service_map", + ForeignColumns: []string{"arcgis_id"}, + }, OrganizationOrganizationFieldseekerServiceFeatureItemIDFkey: foreignKey{ constraint: constraint{ Name: "organization.organization_fieldseeker_service_feature_item_id_fkey", @@ -440,11 +458,12 @@ type organizationColumns struct { OfficeAddressState column ArcgisAccountID column FieldseekerServiceFeatureItemID column + ArcgisMapServiceID column } func (c organizationColumns) AsSlice() []column { return []column{ - c.ID, c.Name, c.ImportDistrictGid, c.Website, c.LogoUUID, c.Slug, c.GeneralManagerName, c.MailingAddressCity, c.MailingAddressPostalCode, c.MailingAddressStreet, c.OfficeAddressCity, c.OfficeAddressPostalCode, c.OfficeAddressStreet, c.ServiceAreaGeometry, c.ServiceAreaSquareMeters, c.ServiceAreaCentroid, c.ServiceAreaExtent, c.OfficeFax, c.OfficePhone, c.ServiceAreaXmin, c.ServiceAreaYmin, c.ServiceAreaXmax, c.ServiceAreaYmax, c.ServiceAreaCentroidGeojson, c.ServiceAreaCentroidX, c.ServiceAreaCentroidY, c.MailingAddressCountry, c.MailingAddressState, c.OfficeAddressCountry, c.OfficeAddressState, c.ArcgisAccountID, c.FieldseekerServiceFeatureItemID, + c.ID, c.Name, c.ImportDistrictGid, c.Website, c.LogoUUID, c.Slug, c.GeneralManagerName, c.MailingAddressCity, c.MailingAddressPostalCode, c.MailingAddressStreet, c.OfficeAddressCity, c.OfficeAddressPostalCode, c.OfficeAddressStreet, c.ServiceAreaGeometry, c.ServiceAreaSquareMeters, c.ServiceAreaCentroid, c.ServiceAreaExtent, c.OfficeFax, c.OfficePhone, c.ServiceAreaXmin, c.ServiceAreaYmin, c.ServiceAreaXmax, c.ServiceAreaYmax, c.ServiceAreaCentroidGeojson, c.ServiceAreaCentroidX, c.ServiceAreaCentroidY, c.MailingAddressCountry, c.MailingAddressState, c.OfficeAddressCountry, c.OfficeAddressState, c.ArcgisAccountID, c.FieldseekerServiceFeatureItemID, c.ArcgisMapServiceID, } } @@ -462,13 +481,14 @@ func (i organizationIndexes) AsSlice() []index { type organizationForeignKeys struct { OrganizationOrganizationArcgisAccountIDFkey foreignKey + OrganizationOrganizationArcgisMapServiceIDFkey foreignKey OrganizationOrganizationFieldseekerServiceFeatureItemIDFkey foreignKey OrganizationOrganizationImportDistrictGidFkey foreignKey } func (f organizationForeignKeys) AsSlice() []foreignKey { return []foreignKey{ - f.OrganizationOrganizationArcgisAccountIDFkey, f.OrganizationOrganizationFieldseekerServiceFeatureItemIDFkey, f.OrganizationOrganizationImportDistrictGidFkey, + f.OrganizationOrganizationArcgisAccountIDFkey, f.OrganizationOrganizationArcgisMapServiceIDFkey, f.OrganizationOrganizationFieldseekerServiceFeatureItemIDFkey, f.OrganizationOrganizationImportDistrictGidFkey, } } diff --git a/db/dbinfo/tile.cached_image.bob.go b/db/dbinfo/tile.cached_image.bob.go new file mode 100644 index 00000000..d064b1de --- /dev/null +++ b/db/dbinfo/tile.cached_image.bob.go @@ -0,0 +1,159 @@ +// 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 TileCachedImages = Table[ + tileCachedImageColumns, + tileCachedImageIndexes, + tileCachedImageForeignKeys, + tileCachedImageUniques, + tileCachedImageChecks, +]{ + Schema: "tile", + Name: "cached_image", + Columns: tileCachedImageColumns{ + ArcgisID: column{ + Name: "arcgis_id", + DBType: "text", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + X: column{ + Name: "x", + DBType: "integer", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + Y: column{ + Name: "y", + DBType: "integer", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + Z: column{ + Name: "z", + DBType: "integer", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + }, + Indexes: tileCachedImageIndexes{ + CachedImageArcgisIDXYZKey: index{ + Type: "btree", + Name: "cached_image_arcgis_id_x_y_z_key", + Columns: []indexColumn{ + { + Name: "arcgis_id", + Desc: null.FromCond(false, true), + IsExpression: false, + }, + { + Name: "x", + Desc: null.FromCond(false, true), + IsExpression: false, + }, + { + Name: "y", + Desc: null.FromCond(false, true), + IsExpression: false, + }, + { + Name: "z", + Desc: null.FromCond(false, true), + IsExpression: false, + }, + }, + Unique: true, + Comment: "", + NullsFirst: []bool{false, false, false, false}, + NullsDistinct: false, + Where: "", + Include: []string{}, + }, + }, + + ForeignKeys: tileCachedImageForeignKeys{ + TileCachedImageCachedImageArcgisIDFkey: foreignKey{ + constraint: constraint{ + Name: "tile.cached_image.cached_image_arcgis_id_fkey", + Columns: []string{"arcgis_id"}, + Comment: "", + }, + ForeignTable: "arcgis.service_map", + ForeignColumns: []string{"arcgis_id"}, + }, + }, + Uniques: tileCachedImageUniques{ + CachedImageArcgisIDXYZKey: constraint{ + Name: "cached_image_arcgis_id_x_y_z_key", + Columns: []string{"arcgis_id", "x", "y", "z"}, + Comment: "", + }, + }, + + Comment: "", +} + +type tileCachedImageColumns struct { + ArcgisID column + X column + Y column + Z column +} + +func (c tileCachedImageColumns) AsSlice() []column { + return []column{ + c.ArcgisID, c.X, c.Y, c.Z, + } +} + +type tileCachedImageIndexes struct { + CachedImageArcgisIDXYZKey index +} + +func (i tileCachedImageIndexes) AsSlice() []index { + return []index{ + i.CachedImageArcgisIDXYZKey, + } +} + +type tileCachedImageForeignKeys struct { + TileCachedImageCachedImageArcgisIDFkey foreignKey +} + +func (f tileCachedImageForeignKeys) AsSlice() []foreignKey { + return []foreignKey{ + f.TileCachedImageCachedImageArcgisIDFkey, + } +} + +type tileCachedImageUniques struct { + CachedImageArcgisIDXYZKey constraint +} + +func (u tileCachedImageUniques) AsSlice() []constraint { + return []constraint{ + u.CachedImageArcgisIDXYZKey, + } +} + +type tileCachedImageChecks struct{} + +func (c tileCachedImageChecks) AsSlice() []check { + return []check{} +} diff --git a/db/migrations/00092_tile_cache.sql b/db/migrations/00092_tile_cache.sql new file mode 100644 index 00000000..7aaf525a --- /dev/null +++ b/db/migrations/00092_tile_cache.sql @@ -0,0 +1,14 @@ +-- +goose Up +CREATE SCHEMA tile; +CREATE TABLE tile.cached_image ( + arcgis_id TEXT NOT NULL REFERENCES arcgis.service_map(arcgis_id), + x INTEGER NOT NULL, + y INTEGER NOT NULL, + z INTEGER NOT NULL, + UNIQUE(arcgis_id, x, y, z) +); +ALTER TABLE organization ADD COLUMN arcgis_map_service_id TEXT REFERENCES arcgis.service_map(arcgis_id); +-- +goose Down +ALTER TABLE organization DROP COLUMN arcgis_map_service_id; +DROP TABLE tile.cached_image; +DROP SCHEMA tile; diff --git a/db/models/arcgis.service_map.bob.go b/db/models/arcgis.service_map.bob.go index 49695249..116aa7b8 100644 --- a/db/models/arcgis.service_map.bob.go +++ b/db/models/arcgis.service_map.bob.go @@ -18,6 +18,7 @@ import ( "github.com/Gleipnir-Technology/bob/orm" "github.com/Gleipnir-Technology/bob/types/pgtypes" "github.com/aarondl/opt/omit" + "github.com/aarondl/opt/omitnull" ) // ArcgisServiceMap is an object representing the database table. @@ -43,7 +44,9 @@ type ArcgisServiceMapsQuery = *psql.ViewQuery[*ArcgisServiceMap, ArcgisServiceMa // arcgisServiceMapR is where relationships are stored. type arcgisServiceMapR struct { - Account *ArcgisAccount // arcgis.service_map.service_map_account_id_fkey + Account *ArcgisAccount // arcgis.service_map.service_map_account_id_fkey + ArcgisMapServiceOrganizations OrganizationSlice // organization.organization_arcgis_map_service_id_fkey + ArcgisCachedImages TileCachedImageSlice // tile.cached_image.cached_image_arcgis_id_fkey } func buildArcgisServiceMapColumns(alias string) arcgisServiceMapColumns { @@ -460,6 +463,54 @@ func (os ArcgisServiceMapSlice) Account(mods ...bob.Mod[*dialect.SelectQuery]) A )...) } +// ArcgisMapServiceOrganizations starts a query for related objects on organization +func (o *ArcgisServiceMap) ArcgisMapServiceOrganizations(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery { + return Organizations.Query(append(mods, + sm.Where(Organizations.Columns.ArcgisMapServiceID.EQ(psql.Arg(o.ArcgisID))), + )...) +} + +func (os ArcgisServiceMapSlice) ArcgisMapServiceOrganizations(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery { + pkArcgisID := make(pgtypes.Array[string], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkArcgisID = append(pkArcgisID, o.ArcgisID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkArcgisID), "text[]")), + )) + + return Organizations.Query(append(mods, + sm.Where(psql.Group(Organizations.Columns.ArcgisMapServiceID).OP("IN", PKArgExpr)), + )...) +} + +// ArcgisCachedImages starts a query for related objects on tile.cached_image +func (o *ArcgisServiceMap) ArcgisCachedImages(mods ...bob.Mod[*dialect.SelectQuery]) TileCachedImagesQuery { + return TileCachedImages.Query(append(mods, + sm.Where(TileCachedImages.Columns.ArcgisID.EQ(psql.Arg(o.ArcgisID))), + )...) +} + +func (os ArcgisServiceMapSlice) ArcgisCachedImages(mods ...bob.Mod[*dialect.SelectQuery]) TileCachedImagesQuery { + pkArcgisID := make(pgtypes.Array[string], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkArcgisID = append(pkArcgisID, o.ArcgisID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkArcgisID), "text[]")), + )) + + return TileCachedImages.Query(append(mods, + sm.Where(psql.Group(TileCachedImages.Columns.ArcgisID).OP("IN", PKArgExpr)), + )...) +} + func attachArcgisServiceMapAccount0(ctx context.Context, exec bob.Executor, count int, arcgisServiceMap0 *ArcgisServiceMap, arcgisAccount1 *ArcgisAccount) (*ArcgisServiceMap, error) { setter := &ArcgisServiceMapSetter{ AccountID: omit.From(arcgisAccount1.ID), @@ -508,6 +559,74 @@ func (arcgisServiceMap0 *ArcgisServiceMap) AttachAccount(ctx context.Context, ex return nil } +func insertArcgisServiceMapArcgisMapServiceOrganizations0(ctx context.Context, exec bob.Executor, organizations1 []*OrganizationSetter, arcgisServiceMap0 *ArcgisServiceMap) (OrganizationSlice, error) { + for i := range organizations1 { + organizations1[i].ArcgisMapServiceID = omitnull.From(arcgisServiceMap0.ArcgisID) + } + + ret, err := Organizations.Insert(bob.ToMods(organizations1...)).All(ctx, exec) + if err != nil { + return ret, fmt.Errorf("insertArcgisServiceMapArcgisMapServiceOrganizations0: %w", err) + } + + return ret, nil +} + +func attachArcgisServiceMapArcgisMapServiceOrganizations0(ctx context.Context, exec bob.Executor, count int, organizations1 OrganizationSlice, arcgisServiceMap0 *ArcgisServiceMap) (OrganizationSlice, error) { + setter := &OrganizationSetter{ + ArcgisMapServiceID: omitnull.From(arcgisServiceMap0.ArcgisID), + } + + err := organizations1.UpdateAll(ctx, exec, *setter) + if err != nil { + return nil, fmt.Errorf("attachArcgisServiceMapArcgisMapServiceOrganizations0: %w", err) + } + + return organizations1, nil +} + +func (arcgisServiceMap0 *ArcgisServiceMap) InsertArcgisMapServiceOrganizations(ctx context.Context, exec bob.Executor, related ...*OrganizationSetter) error { + if len(related) == 0 { + return nil + } + + var err error + + organizations1, err := insertArcgisServiceMapArcgisMapServiceOrganizations0(ctx, exec, related, arcgisServiceMap0) + if err != nil { + return err + } + + arcgisServiceMap0.R.ArcgisMapServiceOrganizations = append(arcgisServiceMap0.R.ArcgisMapServiceOrganizations, organizations1...) + + for _, rel := range organizations1 { + rel.R.ArcgisMapServiceServiceMap = arcgisServiceMap0 + } + return nil +} + +func (arcgisServiceMap0 *ArcgisServiceMap) AttachArcgisMapServiceOrganizations(ctx context.Context, exec bob.Executor, related ...*Organization) error { + if len(related) == 0 { + return nil + } + + var err error + organizations1 := OrganizationSlice(related) + + _, err = attachArcgisServiceMapArcgisMapServiceOrganizations0(ctx, exec, len(related), organizations1, arcgisServiceMap0) + if err != nil { + return err + } + + arcgisServiceMap0.R.ArcgisMapServiceOrganizations = append(arcgisServiceMap0.R.ArcgisMapServiceOrganizations, organizations1...) + + for _, rel := range related { + rel.R.ArcgisMapServiceServiceMap = arcgisServiceMap0 + } + + return nil +} + type arcgisServiceMapWhere[Q psql.Filterable] struct { AccountID psql.WhereMod[Q, string] ArcgisID psql.WhereMod[Q, string] @@ -548,6 +667,34 @@ func (o *ArcgisServiceMap) Preload(name string, retrieved any) error { rel.R.ServiceMaps = ArcgisServiceMapSlice{o} } return nil + case "ArcgisMapServiceOrganizations": + rels, ok := retrieved.(OrganizationSlice) + if !ok { + return fmt.Errorf("arcgisServiceMap cannot load %T as %q", retrieved, name) + } + + o.R.ArcgisMapServiceOrganizations = rels + + for _, rel := range rels { + if rel != nil { + rel.R.ArcgisMapServiceServiceMap = o + } + } + return nil + case "ArcgisCachedImages": + rels, ok := retrieved.(TileCachedImageSlice) + if !ok { + return fmt.Errorf("arcgisServiceMap cannot load %T as %q", retrieved, name) + } + + o.R.ArcgisCachedImages = rels + + for _, rel := range rels { + if rel != nil { + rel.R.ArcgisServiceMap = o + } + } + return nil default: return fmt.Errorf("arcgisServiceMap has no relationship %q", name) } @@ -576,13 +723,21 @@ func buildArcgisServiceMapPreloader() arcgisServiceMapPreloader { } type arcgisServiceMapThenLoader[Q orm.Loadable] struct { - Account func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + Account func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + ArcgisMapServiceOrganizations func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + ArcgisCachedImages func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] } func buildArcgisServiceMapThenLoader[Q orm.Loadable]() arcgisServiceMapThenLoader[Q] { type AccountLoadInterface interface { LoadAccount(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } + type ArcgisMapServiceOrganizationsLoadInterface interface { + LoadArcgisMapServiceOrganizations(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + type ArcgisCachedImagesLoadInterface interface { + LoadArcgisCachedImages(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } return arcgisServiceMapThenLoader[Q]{ Account: thenLoadBuilder[Q]( @@ -591,6 +746,18 @@ func buildArcgisServiceMapThenLoader[Q orm.Loadable]() arcgisServiceMapThenLoade return retrieved.LoadAccount(ctx, exec, mods...) }, ), + ArcgisMapServiceOrganizations: thenLoadBuilder[Q]( + "ArcgisMapServiceOrganizations", + func(ctx context.Context, exec bob.Executor, retrieved ArcgisMapServiceOrganizationsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadArcgisMapServiceOrganizations(ctx, exec, mods...) + }, + ), + ArcgisCachedImages: thenLoadBuilder[Q]( + "ArcgisCachedImages", + func(ctx context.Context, exec bob.Executor, retrieved ArcgisCachedImagesLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadArcgisCachedImages(ctx, exec, mods...) + }, + ), } } @@ -645,3 +812,128 @@ func (os ArcgisServiceMapSlice) LoadAccount(ctx context.Context, exec bob.Execut return nil } + +// LoadArcgisMapServiceOrganizations loads the arcgisServiceMap's ArcgisMapServiceOrganizations into the .R struct +func (o *ArcgisServiceMap) LoadArcgisMapServiceOrganizations(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.ArcgisMapServiceOrganizations = nil + + related, err := o.ArcgisMapServiceOrganizations(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, rel := range related { + rel.R.ArcgisMapServiceServiceMap = o + } + + o.R.ArcgisMapServiceOrganizations = related + return nil +} + +// LoadArcgisMapServiceOrganizations loads the arcgisServiceMap's ArcgisMapServiceOrganizations into the .R struct +func (os ArcgisServiceMapSlice) LoadArcgisMapServiceOrganizations(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + organizations, err := os.ArcgisMapServiceOrganizations(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + o.R.ArcgisMapServiceOrganizations = nil + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range organizations { + + if !rel.ArcgisMapServiceID.IsValue() { + continue + } + if !(rel.ArcgisMapServiceID.IsValue() && o.ArcgisID == rel.ArcgisMapServiceID.MustGet()) { + continue + } + + rel.R.ArcgisMapServiceServiceMap = o + + o.R.ArcgisMapServiceOrganizations = append(o.R.ArcgisMapServiceOrganizations, rel) + } + } + + return nil +} + +// LoadArcgisCachedImages loads the arcgisServiceMap's ArcgisCachedImages into the .R struct +func (o *ArcgisServiceMap) LoadArcgisCachedImages(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.ArcgisCachedImages = nil + + related, err := o.ArcgisCachedImages(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, rel := range related { + rel.R.ArcgisServiceMap = o + } + + o.R.ArcgisCachedImages = related + return nil +} + +// LoadArcgisCachedImages loads the arcgisServiceMap's ArcgisCachedImages into the .R struct +func (os ArcgisServiceMapSlice) LoadArcgisCachedImages(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + tileCachedImages, err := os.ArcgisCachedImages(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + o.R.ArcgisCachedImages = nil + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range tileCachedImages { + + if !(o.ArcgisID == rel.ArcgisID) { + continue + } + + rel.R.ArcgisServiceMap = o + + o.R.ArcgisCachedImages = append(o.R.ArcgisCachedImages, rel) + } + } + + return nil +} diff --git a/db/models/bob_loaders.bob.go b/db/models/bob_loaders.bob.go index 46c5c500..acf58223 100644 --- a/db/models/bob_loaders.bob.go +++ b/db/models/bob_loaders.bob.go @@ -104,6 +104,7 @@ type preloaders struct { ReviewTaskPool reviewTaskPoolPreloader Signal signalPreloader Site sitePreloader + TileCachedImage tileCachedImagePreloader User userPreloader } @@ -196,6 +197,7 @@ func getPreloaders() preloaders { ReviewTaskPool: buildReviewTaskPoolPreloader(), Signal: buildSignalPreloader(), Site: buildSitePreloader(), + TileCachedImage: buildTileCachedImagePreloader(), User: buildUserPreloader(), } } @@ -294,6 +296,7 @@ type thenLoaders[Q orm.Loadable] struct { ReviewTaskPool reviewTaskPoolThenLoader[Q] Signal signalThenLoader[Q] Site siteThenLoader[Q] + TileCachedImage tileCachedImageThenLoader[Q] User userThenLoader[Q] } @@ -386,6 +389,7 @@ func getThenLoaders[Q orm.Loadable]() thenLoaders[Q] { ReviewTaskPool: buildReviewTaskPoolThenLoader[Q](), Signal: buildSignalThenLoader[Q](), Site: buildSiteThenLoader[Q](), + TileCachedImage: buildTileCachedImageThenLoader[Q](), User: buildUserThenLoader[Q](), } } diff --git a/db/models/bob_where.bob.go b/db/models/bob_where.bob.go index cc0b88b3..3002aa42 100644 --- a/db/models/bob_where.bob.go +++ b/db/models/bob_where.bob.go @@ -112,6 +112,7 @@ func Where[Q psql.Filterable]() struct { Signals signalWhere[Q] Sites siteWhere[Q] SpatialRefSys spatialRefSyWhere[Q] + TileCachedImages tileCachedImageWhere[Q] Users userWhere[Q] } { return struct { @@ -210,6 +211,7 @@ func Where[Q psql.Filterable]() struct { Signals signalWhere[Q] Sites siteWhere[Q] SpatialRefSys spatialRefSyWhere[Q] + TileCachedImages tileCachedImageWhere[Q] Users userWhere[Q] }{ Addresses: buildAddressWhere[Q](Addresses.Columns), @@ -307,6 +309,7 @@ func Where[Q psql.Filterable]() struct { Signals: buildSignalWhere[Q](Signals.Columns), Sites: buildSiteWhere[Q](Sites.Columns), SpatialRefSys: buildSpatialRefSyWhere[Q](SpatialRefSys.Columns), + TileCachedImages: buildTileCachedImageWhere[Q](TileCachedImages.Columns), Users: buildUserWhere[Q](Users.Columns), } } diff --git a/db/models/organization.bob.go b/db/models/organization.bob.go index 83ec3389..5db051fc 100644 --- a/db/models/organization.bob.go +++ b/db/models/organization.bob.go @@ -59,6 +59,7 @@ type Organization struct { OfficeAddressState null.Val[string] `db:"office_address_state" ` ArcgisAccountID null.Val[string] `db:"arcgis_account_id" ` FieldseekerServiceFeatureItemID null.Val[string] `db:"fieldseeker_service_feature_item_id" ` + ArcgisMapServiceID null.Val[string] `db:"arcgis_map_service_id" ` R organizationR `db:"-" ` } @@ -115,6 +116,7 @@ type organizationR struct { NoteAudios NoteAudioSlice // note_audio.note_audio_organization_id_fkey NoteImages NoteImageSlice // note_image.note_image_organization_id_fkey ArcgisAccountAccount *ArcgisAccount // organization.organization_arcgis_account_id_fkey + ArcgisMapServiceServiceMap *ArcgisServiceMap // organization.organization_arcgis_map_service_id_fkey FieldseekerServiceFeatureItemServiceFeature *ArcgisServiceFeature // organization.organization_fieldseeker_service_feature_item_id_fkey Nuisances PublicreportNuisanceSlice // publicreport.nuisance.nuisance_organization_id_fkey PublicreportPool PublicreportPoolSlice // publicreport.pool.pool_organization_id_fkey @@ -127,7 +129,7 @@ type organizationR struct { func buildOrganizationColumns(alias string) organizationColumns { return organizationColumns{ ColumnsExpr: expr.NewColumnsExpr( - "id", "name", "import_district_gid", "website", "logo_uuid", "slug", "general_manager_name", "mailing_address_city", "mailing_address_postal_code", "mailing_address_street", "office_address_city", "office_address_postal_code", "office_address_street", "service_area_geometry", "service_area_square_meters", "service_area_centroid", "service_area_extent", "office_fax", "office_phone", "service_area_xmin", "service_area_ymin", "service_area_xmax", "service_area_ymax", "service_area_centroid_geojson", "service_area_centroid_x", "service_area_centroid_y", "mailing_address_country", "mailing_address_state", "office_address_country", "office_address_state", "arcgis_account_id", "fieldseeker_service_feature_item_id", + "id", "name", "import_district_gid", "website", "logo_uuid", "slug", "general_manager_name", "mailing_address_city", "mailing_address_postal_code", "mailing_address_street", "office_address_city", "office_address_postal_code", "office_address_street", "service_area_geometry", "service_area_square_meters", "service_area_centroid", "service_area_extent", "office_fax", "office_phone", "service_area_xmin", "service_area_ymin", "service_area_xmax", "service_area_ymax", "service_area_centroid_geojson", "service_area_centroid_x", "service_area_centroid_y", "mailing_address_country", "mailing_address_state", "office_address_country", "office_address_state", "arcgis_account_id", "fieldseeker_service_feature_item_id", "arcgis_map_service_id", ).WithParent("organization"), tableAlias: alias, ID: psql.Quote(alias, "id"), @@ -162,6 +164,7 @@ func buildOrganizationColumns(alias string) organizationColumns { OfficeAddressState: psql.Quote(alias, "office_address_state"), ArcgisAccountID: psql.Quote(alias, "arcgis_account_id"), FieldseekerServiceFeatureItemID: psql.Quote(alias, "fieldseeker_service_feature_item_id"), + ArcgisMapServiceID: psql.Quote(alias, "arcgis_map_service_id"), } } @@ -200,6 +203,7 @@ type organizationColumns struct { OfficeAddressState psql.Expression ArcgisAccountID psql.Expression FieldseekerServiceFeatureItemID psql.Expression + ArcgisMapServiceID psql.Expression } func (c organizationColumns) Alias() string { @@ -236,10 +240,11 @@ type OrganizationSetter struct { OfficeAddressState omitnull.Val[string] `db:"office_address_state" ` ArcgisAccountID omitnull.Val[string] `db:"arcgis_account_id" ` FieldseekerServiceFeatureItemID omitnull.Val[string] `db:"fieldseeker_service_feature_item_id" ` + ArcgisMapServiceID omitnull.Val[string] `db:"arcgis_map_service_id" ` } func (s OrganizationSetter) SetColumns() []string { - vals := make([]string, 0, 22) + vals := make([]string, 0, 23) if s.ID.IsValue() { vals = append(vals, "id") } @@ -306,6 +311,9 @@ func (s OrganizationSetter) SetColumns() []string { if !s.FieldseekerServiceFeatureItemID.IsUnset() { vals = append(vals, "fieldseeker_service_feature_item_id") } + if !s.ArcgisMapServiceID.IsUnset() { + vals = append(vals, "arcgis_map_service_id") + } return vals } @@ -376,6 +384,9 @@ func (s OrganizationSetter) Overwrite(t *Organization) { if !s.FieldseekerServiceFeatureItemID.IsUnset() { t.FieldseekerServiceFeatureItemID = s.FieldseekerServiceFeatureItemID.MustGetNull() } + if !s.ArcgisMapServiceID.IsUnset() { + t.ArcgisMapServiceID = s.ArcgisMapServiceID.MustGetNull() + } } func (s *OrganizationSetter) Apply(q *dialect.InsertQuery) { @@ -384,7 +395,7 @@ func (s *OrganizationSetter) 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, 22) + vals := make([]bob.Expression, 23) if s.ID.IsValue() { vals[0] = psql.Arg(s.ID.MustGet()) } else { @@ -517,6 +528,12 @@ func (s *OrganizationSetter) Apply(q *dialect.InsertQuery) { vals[21] = psql.Raw("DEFAULT") } + if !s.ArcgisMapServiceID.IsUnset() { + vals[22] = psql.Arg(s.ArcgisMapServiceID.MustGetNull()) + } else { + vals[22] = psql.Raw("DEFAULT") + } + return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "") })) } @@ -526,7 +543,7 @@ func (s OrganizationSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] { } func (s OrganizationSetter) Expressions(prefix ...string) []bob.Expression { - exprs := make([]bob.Expression, 0, 22) + exprs := make([]bob.Expression, 0, 23) if s.ID.IsValue() { exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ @@ -682,6 +699,13 @@ func (s OrganizationSetter) Expressions(prefix ...string) []bob.Expression { }}) } + if !s.ArcgisMapServiceID.IsUnset() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "arcgis_map_service_id")...), + psql.Arg(s.ArcgisMapServiceID), + }}) + } + return exprs } @@ -1878,6 +1902,30 @@ func (os OrganizationSlice) ArcgisAccountAccount(mods ...bob.Mod[*dialect.Select )...) } +// ArcgisMapServiceServiceMap starts a query for related objects on arcgis.service_map +func (o *Organization) ArcgisMapServiceServiceMap(mods ...bob.Mod[*dialect.SelectQuery]) ArcgisServiceMapsQuery { + return ArcgisServiceMaps.Query(append(mods, + sm.Where(ArcgisServiceMaps.Columns.ArcgisID.EQ(psql.Arg(o.ArcgisMapServiceID))), + )...) +} + +func (os OrganizationSlice) ArcgisMapServiceServiceMap(mods ...bob.Mod[*dialect.SelectQuery]) ArcgisServiceMapsQuery { + pkArcgisMapServiceID := make(pgtypes.Array[null.Val[string]], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkArcgisMapServiceID = append(pkArcgisMapServiceID, o.ArcgisMapServiceID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkArcgisMapServiceID), "text[]")), + )) + + return ArcgisServiceMaps.Query(append(mods, + sm.Where(psql.Group(ArcgisServiceMaps.Columns.ArcgisID).OP("IN", PKArgExpr)), + )...) +} + // FieldseekerServiceFeatureItemServiceFeature starts a query for related objects on arcgis.service_feature func (o *Organization) FieldseekerServiceFeatureItemServiceFeature(mods ...bob.Mod[*dialect.SelectQuery]) ArcgisServiceFeaturesQuery { return ArcgisServiceFeatures.Query(append(mods, @@ -4740,6 +4788,54 @@ func (organization0 *Organization) AttachArcgisAccountAccount(ctx context.Contex return nil } +func attachOrganizationArcgisMapServiceServiceMap0(ctx context.Context, exec bob.Executor, count int, organization0 *Organization, arcgisServiceMap1 *ArcgisServiceMap) (*Organization, error) { + setter := &OrganizationSetter{ + ArcgisMapServiceID: omitnull.From(arcgisServiceMap1.ArcgisID), + } + + err := organization0.Update(ctx, exec, setter) + if err != nil { + return nil, fmt.Errorf("attachOrganizationArcgisMapServiceServiceMap0: %w", err) + } + + return organization0, nil +} + +func (organization0 *Organization) InsertArcgisMapServiceServiceMap(ctx context.Context, exec bob.Executor, related *ArcgisServiceMapSetter) error { + var err error + + arcgisServiceMap1, err := ArcgisServiceMaps.Insert(related).One(ctx, exec) + if err != nil { + return fmt.Errorf("inserting related objects: %w", err) + } + + _, err = attachOrganizationArcgisMapServiceServiceMap0(ctx, exec, 1, organization0, arcgisServiceMap1) + if err != nil { + return err + } + + organization0.R.ArcgisMapServiceServiceMap = arcgisServiceMap1 + + arcgisServiceMap1.R.ArcgisMapServiceOrganizations = append(arcgisServiceMap1.R.ArcgisMapServiceOrganizations, organization0) + + return nil +} + +func (organization0 *Organization) AttachArcgisMapServiceServiceMap(ctx context.Context, exec bob.Executor, arcgisServiceMap1 *ArcgisServiceMap) error { + var err error + + _, err = attachOrganizationArcgisMapServiceServiceMap0(ctx, exec, 1, organization0, arcgisServiceMap1) + if err != nil { + return err + } + + organization0.R.ArcgisMapServiceServiceMap = arcgisServiceMap1 + + arcgisServiceMap1.R.ArcgisMapServiceOrganizations = append(arcgisServiceMap1.R.ArcgisMapServiceOrganizations, organization0) + + return nil +} + func attachOrganizationFieldseekerServiceFeatureItemServiceFeature0(ctx context.Context, exec bob.Executor, count int, organization0 *Organization, arcgisServiceFeature1 *ArcgisServiceFeature) (*Organization, error) { setter := &OrganizationSetter{ FieldseekerServiceFeatureItemID: omitnull.From(arcgisServiceFeature1.ItemID), @@ -5229,6 +5325,7 @@ type organizationWhere[Q psql.Filterable] struct { OfficeAddressState psql.WhereNullMod[Q, string] ArcgisAccountID psql.WhereNullMod[Q, string] FieldseekerServiceFeatureItemID psql.WhereNullMod[Q, string] + ArcgisMapServiceID psql.WhereNullMod[Q, string] } func (organizationWhere[Q]) AliasedAs(alias string) organizationWhere[Q] { @@ -5269,6 +5366,7 @@ func buildOrganizationWhere[Q psql.Filterable](cols organizationColumns) organiz OfficeAddressState: psql.WhereNull[Q, string](cols.OfficeAddressState), ArcgisAccountID: psql.WhereNull[Q, string](cols.ArcgisAccountID), FieldseekerServiceFeatureItemID: psql.WhereNull[Q, string](cols.FieldseekerServiceFeatureItemID), + ArcgisMapServiceID: psql.WhereNull[Q, string](cols.ArcgisMapServiceID), } } @@ -5836,6 +5934,18 @@ func (o *Organization) Preload(name string, retrieved any) error { rel.R.ArcgisAccountOrganizations = OrganizationSlice{o} } return nil + case "ArcgisMapServiceServiceMap": + rel, ok := retrieved.(*ArcgisServiceMap) + if !ok { + return fmt.Errorf("organization cannot load %T as %q", retrieved, name) + } + + o.R.ArcgisMapServiceServiceMap = rel + + if rel != nil { + rel.R.ArcgisMapServiceOrganizations = OrganizationSlice{o} + } + return nil case "FieldseekerServiceFeatureItemServiceFeature": rel, ok := retrieved.(*ArcgisServiceFeature) if !ok { @@ -5939,6 +6049,7 @@ func (o *Organization) Preload(name string, retrieved any) error { type organizationPreloader struct { ArcgisAccountAccount func(...psql.PreloadOption) psql.Preloader + ArcgisMapServiceServiceMap func(...psql.PreloadOption) psql.Preloader FieldseekerServiceFeatureItemServiceFeature func(...psql.PreloadOption) psql.Preloader } @@ -5957,6 +6068,19 @@ func buildOrganizationPreloader() organizationPreloader { }, }, ArcgisAccounts.Columns.Names(), opts...) }, + ArcgisMapServiceServiceMap: func(opts ...psql.PreloadOption) psql.Preloader { + return psql.Preload[*ArcgisServiceMap, ArcgisServiceMapSlice](psql.PreloadRel{ + Name: "ArcgisMapServiceServiceMap", + Sides: []psql.PreloadSide{ + { + From: Organizations, + To: ArcgisServiceMaps, + FromColumns: []string{"arcgis_map_service_id"}, + ToColumns: []string{"arcgis_id"}, + }, + }, + }, ArcgisServiceMaps.Columns.Names(), opts...) + }, FieldseekerServiceFeatureItemServiceFeature: func(opts ...psql.PreloadOption) psql.Preloader { return psql.Preload[*ArcgisServiceFeature, ArcgisServiceFeatureSlice](psql.PreloadRel{ Name: "FieldseekerServiceFeatureItemServiceFeature", @@ -6014,6 +6138,7 @@ type organizationThenLoader[Q orm.Loadable] struct { NoteAudios func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] NoteImages func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] ArcgisAccountAccount func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + ArcgisMapServiceServiceMap func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] FieldseekerServiceFeatureItemServiceFeature func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] Nuisances func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] PublicreportPool func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] @@ -6144,6 +6269,9 @@ func buildOrganizationThenLoader[Q orm.Loadable]() organizationThenLoader[Q] { type ArcgisAccountAccountLoadInterface interface { LoadArcgisAccountAccount(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } + type ArcgisMapServiceServiceMapLoadInterface interface { + LoadArcgisMapServiceServiceMap(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } type FieldseekerServiceFeatureItemServiceFeatureLoadInterface interface { LoadFieldseekerServiceFeatureItemServiceFeature(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } @@ -6407,6 +6535,12 @@ func buildOrganizationThenLoader[Q orm.Loadable]() organizationThenLoader[Q] { return retrieved.LoadArcgisAccountAccount(ctx, exec, mods...) }, ), + ArcgisMapServiceServiceMap: thenLoadBuilder[Q]( + "ArcgisMapServiceServiceMap", + func(ctx context.Context, exec bob.Executor, retrieved ArcgisMapServiceServiceMapLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadArcgisMapServiceServiceMap(ctx, exec, mods...) + }, + ), FieldseekerServiceFeatureItemServiceFeature: thenLoadBuilder[Q]( "FieldseekerServiceFeatureItemServiceFeature", func(ctx context.Context, exec bob.Executor, retrieved FieldseekerServiceFeatureItemServiceFeatureLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { @@ -8926,6 +9060,61 @@ func (os OrganizationSlice) LoadArcgisAccountAccount(ctx context.Context, exec b return nil } +// LoadArcgisMapServiceServiceMap loads the organization's ArcgisMapServiceServiceMap into the .R struct +func (o *Organization) LoadArcgisMapServiceServiceMap(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.ArcgisMapServiceServiceMap = nil + + related, err := o.ArcgisMapServiceServiceMap(mods...).One(ctx, exec) + if err != nil { + return err + } + + related.R.ArcgisMapServiceOrganizations = OrganizationSlice{o} + + o.R.ArcgisMapServiceServiceMap = related + return nil +} + +// LoadArcgisMapServiceServiceMap loads the organization's ArcgisMapServiceServiceMap into the .R struct +func (os OrganizationSlice) LoadArcgisMapServiceServiceMap(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + arcgisServiceMaps, err := os.ArcgisMapServiceServiceMap(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range arcgisServiceMaps { + if !o.ArcgisMapServiceID.IsValue() { + continue + } + + if !(o.ArcgisMapServiceID.IsValue() && o.ArcgisMapServiceID.MustGet() == rel.ArcgisID) { + continue + } + + rel.R.ArcgisMapServiceOrganizations = append(rel.R.ArcgisMapServiceOrganizations, o) + + o.R.ArcgisMapServiceServiceMap = rel + break + } + } + + return nil +} + // LoadFieldseekerServiceFeatureItemServiceFeature loads the organization's FieldseekerServiceFeatureItemServiceFeature into the .R struct func (o *Organization) LoadFieldseekerServiceFeatureItemServiceFeature(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { if o == nil { diff --git a/db/models/tile.cached_image.bob.go b/db/models/tile.cached_image.bob.go new file mode 100644 index 00000000..7e5b8009 --- /dev/null +++ b/db/models/tile.cached_image.bob.go @@ -0,0 +1,370 @@ +// 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/orm" + "github.com/Gleipnir-Technology/bob/types/pgtypes" + "github.com/aarondl/opt/omit" +) + +// TileCachedImage is an object representing the database table. +type TileCachedImage struct { + ArcgisID string `db:"arcgis_id" ` + X int32 `db:"x" ` + Y int32 `db:"y" ` + Z int32 `db:"z" ` + + R tileCachedImageR `db:"-" ` +} + +// TileCachedImageSlice is an alias for a slice of pointers to TileCachedImage. +// This should almost always be used instead of []*TileCachedImage. +type TileCachedImageSlice []*TileCachedImage + +// TileCachedImages contains methods to work with the cached_image view +var TileCachedImages = psql.NewViewx[*TileCachedImage, TileCachedImageSlice]("tile", "cached_image", buildTileCachedImageColumns("tile.cached_image")) + +// TileCachedImagesQuery is a query on the cached_image view +type TileCachedImagesQuery = *psql.ViewQuery[*TileCachedImage, TileCachedImageSlice] + +// tileCachedImageR is where relationships are stored. +type tileCachedImageR struct { + ArcgisServiceMap *ArcgisServiceMap // tile.cached_image.cached_image_arcgis_id_fkey +} + +func buildTileCachedImageColumns(alias string) tileCachedImageColumns { + return tileCachedImageColumns{ + ColumnsExpr: expr.NewColumnsExpr( + "arcgis_id", "x", "y", "z", + ).WithParent("tile.cached_image"), + tableAlias: alias, + ArcgisID: psql.Quote(alias, "arcgis_id"), + X: psql.Quote(alias, "x"), + Y: psql.Quote(alias, "y"), + Z: psql.Quote(alias, "z"), + } +} + +type tileCachedImageColumns struct { + expr.ColumnsExpr + tableAlias string + ArcgisID psql.Expression + X psql.Expression + Y psql.Expression + Z psql.Expression +} + +func (c tileCachedImageColumns) Alias() string { + return c.tableAlias +} + +func (tileCachedImageColumns) AliasedAs(alias string) tileCachedImageColumns { + return buildTileCachedImageColumns(alias) +} + +// TileCachedImageSetter is used for insert/upsert/update operations +// All values are optional, and do not have to be set +// Generated columns are not included +type TileCachedImageSetter struct { + ArcgisID omit.Val[string] `db:"arcgis_id" ` + X omit.Val[int32] `db:"x" ` + Y omit.Val[int32] `db:"y" ` + Z omit.Val[int32] `db:"z" ` +} + +func (s TileCachedImageSetter) SetColumns() []string { + vals := make([]string, 0, 4) + if s.ArcgisID.IsValue() { + vals = append(vals, "arcgis_id") + } + if s.X.IsValue() { + vals = append(vals, "x") + } + if s.Y.IsValue() { + vals = append(vals, "y") + } + if s.Z.IsValue() { + vals = append(vals, "z") + } + return vals +} + +func (s TileCachedImageSetter) Overwrite(t *TileCachedImage) { + if s.ArcgisID.IsValue() { + t.ArcgisID = s.ArcgisID.MustGet() + } + if s.X.IsValue() { + t.X = s.X.MustGet() + } + if s.Y.IsValue() { + t.Y = s.Y.MustGet() + } + if s.Z.IsValue() { + t.Z = s.Z.MustGet() + } +} + +func (s *TileCachedImageSetter) 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, 4) + if s.ArcgisID.IsValue() { + vals[0] = psql.Arg(s.ArcgisID.MustGet()) + } else { + vals[0] = psql.Raw("DEFAULT") + } + + if s.X.IsValue() { + vals[1] = psql.Arg(s.X.MustGet()) + } else { + vals[1] = psql.Raw("DEFAULT") + } + + if s.Y.IsValue() { + vals[2] = psql.Arg(s.Y.MustGet()) + } else { + vals[2] = psql.Raw("DEFAULT") + } + + if s.Z.IsValue() { + vals[3] = psql.Arg(s.Z.MustGet()) + } else { + vals[3] = psql.Raw("DEFAULT") + } + + return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "") + })) +} + +func (s TileCachedImageSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] { + return um.Set(s.Expressions()...) +} + +func (s TileCachedImageSetter) Expressions(prefix ...string) []bob.Expression { + exprs := make([]bob.Expression, 0, 4) + + if s.ArcgisID.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "arcgis_id")...), + psql.Arg(s.ArcgisID), + }}) + } + + if s.X.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "x")...), + psql.Arg(s.X), + }}) + } + + if s.Y.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "y")...), + psql.Arg(s.Y), + }}) + } + + if s.Z.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "z")...), + psql.Arg(s.Z), + }}) + } + + return exprs +} + +// AfterQueryHook is called after TileCachedImage is retrieved from the database +func (o *TileCachedImage) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error { + var err error + + switch queryType { + case bob.QueryTypeSelect: + ctx, err = TileCachedImages.AfterSelectHooks.RunHooks(ctx, exec, TileCachedImageSlice{o}) + } + + return err +} + +// AfterQueryHook is called after TileCachedImageSlice is retrieved from the database +func (o TileCachedImageSlice) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error { + var err error + + switch queryType { + case bob.QueryTypeSelect: + ctx, err = TileCachedImages.AfterSelectHooks.RunHooks(ctx, exec, o) + } + + return err +} + +// ArcgisServiceMap starts a query for related objects on arcgis.service_map +func (o *TileCachedImage) ArcgisServiceMap(mods ...bob.Mod[*dialect.SelectQuery]) ArcgisServiceMapsQuery { + return ArcgisServiceMaps.Query(append(mods, + sm.Where(ArcgisServiceMaps.Columns.ArcgisID.EQ(psql.Arg(o.ArcgisID))), + )...) +} + +func (os TileCachedImageSlice) ArcgisServiceMap(mods ...bob.Mod[*dialect.SelectQuery]) ArcgisServiceMapsQuery { + pkArcgisID := make(pgtypes.Array[string], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkArcgisID = append(pkArcgisID, o.ArcgisID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkArcgisID), "text[]")), + )) + + return ArcgisServiceMaps.Query(append(mods, + sm.Where(psql.Group(ArcgisServiceMaps.Columns.ArcgisID).OP("IN", PKArgExpr)), + )...) +} + +type tileCachedImageWhere[Q psql.Filterable] struct { + ArcgisID psql.WhereMod[Q, string] + X psql.WhereMod[Q, int32] + Y psql.WhereMod[Q, int32] + Z psql.WhereMod[Q, int32] +} + +func (tileCachedImageWhere[Q]) AliasedAs(alias string) tileCachedImageWhere[Q] { + return buildTileCachedImageWhere[Q](buildTileCachedImageColumns(alias)) +} + +func buildTileCachedImageWhere[Q psql.Filterable](cols tileCachedImageColumns) tileCachedImageWhere[Q] { + return tileCachedImageWhere[Q]{ + ArcgisID: psql.Where[Q, string](cols.ArcgisID), + X: psql.Where[Q, int32](cols.X), + Y: psql.Where[Q, int32](cols.Y), + Z: psql.Where[Q, int32](cols.Z), + } +} + +func (o *TileCachedImage) Preload(name string, retrieved any) error { + if o == nil { + return nil + } + + switch name { + case "ArcgisServiceMap": + rel, ok := retrieved.(*ArcgisServiceMap) + if !ok { + return fmt.Errorf("tileCachedImage cannot load %T as %q", retrieved, name) + } + + o.R.ArcgisServiceMap = rel + + if rel != nil { + rel.R.ArcgisCachedImages = TileCachedImageSlice{o} + } + return nil + default: + return fmt.Errorf("tileCachedImage has no relationship %q", name) + } +} + +type tileCachedImagePreloader struct { + ArcgisServiceMap func(...psql.PreloadOption) psql.Preloader +} + +func buildTileCachedImagePreloader() tileCachedImagePreloader { + return tileCachedImagePreloader{ + ArcgisServiceMap: func(opts ...psql.PreloadOption) psql.Preloader { + return psql.Preload[*ArcgisServiceMap, ArcgisServiceMapSlice](psql.PreloadRel{ + Name: "ArcgisServiceMap", + Sides: []psql.PreloadSide{ + { + From: TileCachedImages, + To: ArcgisServiceMaps, + FromColumns: []string{"arcgis_id"}, + ToColumns: []string{"arcgis_id"}, + }, + }, + }, ArcgisServiceMaps.Columns.Names(), opts...) + }, + } +} + +type tileCachedImageThenLoader[Q orm.Loadable] struct { + ArcgisServiceMap func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] +} + +func buildTileCachedImageThenLoader[Q orm.Loadable]() tileCachedImageThenLoader[Q] { + type ArcgisServiceMapLoadInterface interface { + LoadArcgisServiceMap(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + + return tileCachedImageThenLoader[Q]{ + ArcgisServiceMap: thenLoadBuilder[Q]( + "ArcgisServiceMap", + func(ctx context.Context, exec bob.Executor, retrieved ArcgisServiceMapLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadArcgisServiceMap(ctx, exec, mods...) + }, + ), + } +} + +// LoadArcgisServiceMap loads the tileCachedImage's ArcgisServiceMap into the .R struct +func (o *TileCachedImage) LoadArcgisServiceMap(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.ArcgisServiceMap = nil + + related, err := o.ArcgisServiceMap(mods...).One(ctx, exec) + if err != nil { + return err + } + + related.R.ArcgisCachedImages = TileCachedImageSlice{o} + + o.R.ArcgisServiceMap = related + return nil +} + +// LoadArcgisServiceMap loads the tileCachedImage's ArcgisServiceMap into the .R struct +func (os TileCachedImageSlice) LoadArcgisServiceMap(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + arcgisServiceMaps, err := os.ArcgisServiceMap(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range arcgisServiceMaps { + + if !(o.ArcgisID == rel.ArcgisID) { + continue + } + + rel.R.ArcgisCachedImages = append(rel.R.ArcgisCachedImages, o) + + o.R.ArcgisServiceMap = rel + break + } + } + + return nil +} diff --git a/platform/geocode/geocode.go b/platform/geocode/geocode.go index e4b92256..93713f55 100644 --- a/platform/geocode/geocode.go +++ b/platform/geocode/geocode.go @@ -71,14 +71,14 @@ func EnsureAddress(ctx context.Context, txn bob.Tx, org *models.Organization, a } created := time.Now() row, err := bob.One(ctx, txn, psql.Insert( - im.Into("address", "country", "created", "geom", "h3cell", "id", "locality", "number_", "postal_code", "region", "street", "unit"), + im.Into("address", "country", "created", "h3cell", "id", "locality", "location", "number_", "postal_code", "region", "street", "unit"), im.Values( psql.Arg(geo.Address.Country), psql.Arg(created), - psql.F("ST_Point", geo.Longitude, geo.Latitude, 4326), psql.Arg(geo.Cell), psql.Raw("DEFAULT"), psql.Arg(geo.Address.Locality), + psql.F("ST_Point", geo.Longitude, geo.Latitude, 4326), psql.Arg(geo.Address.Number), psql.Arg(geo.Address.PostalCode), psql.Arg(geo.Address.Region),