Move database logic into separate subdirectory

I'm trying to see if this speeds up builds a bit. May not without a
module boundary, but for now it's nice organization to have as the
program grows.
This commit is contained in:
Eli Ribble 2025-11-24 18:08:24 +00:00
parent 338f90708e
commit 41587c3694
No known key found for this signature in database
333 changed files with 206 additions and 200 deletions

View file

@ -0,0 +1,111 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
_ "embed"
"io"
"iter"
"time"
"github.com/aarondl/opt/null"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/bob/dialect/psql/dialect"
"github.com/stephenafamo/bob/orm"
"github.com/stephenafamo/scan"
)
//go:embed oauth_by_user_id.bob.sql
var formattedQueries_oauth_by_user_id string
var oauthTokenByUserIdSQL = formattedQueries_oauth_by_user_id[156:694]
type OauthTokenByUserIdQuery = orm.ModQuery[*dialect.SelectQuery, oauthTokenByUserId, OauthTokenByUserIdRow, []OauthTokenByUserIdRow, oauthTokenByUserIdTransformer]
func OauthTokenByUserId(UserID int32) *OauthTokenByUserIdQuery {
var expressionTypArgs oauthTokenByUserId
expressionTypArgs.UserID = psql.Arg(UserID)
return &OauthTokenByUserIdQuery{
Query: orm.Query[oauthTokenByUserId, OauthTokenByUserIdRow, []OauthTokenByUserIdRow, oauthTokenByUserIdTransformer]{
ExecQuery: orm.ExecQuery[oauthTokenByUserId]{
BaseQuery: bob.BaseQuery[oauthTokenByUserId]{
Expression: expressionTypArgs,
Dialect: dialect.Dialect,
QueryType: bob.QueryTypeSelect,
},
},
Scanner: func(context.Context, []string) (func(*scan.Row) (any, error), func(any) (OauthTokenByUserIdRow, error)) {
return func(row *scan.Row) (any, error) {
var t OauthTokenByUserIdRow
row.ScheduleScanByIndex(0, &t.ID)
row.ScheduleScanByIndex(1, &t.AccessToken)
row.ScheduleScanByIndex(2, &t.AccessTokenExpires)
row.ScheduleScanByIndex(3, &t.RefreshToken)
row.ScheduleScanByIndex(4, &t.Username)
row.ScheduleScanByIndex(5, &t.UserID)
row.ScheduleScanByIndex(6, &t.ArcgisID)
row.ScheduleScanByIndex(7, &t.ArcgisLicenseTypeID)
row.ScheduleScanByIndex(8, &t.RefreshTokenExpires)
row.ScheduleScanByIndex(9, &t.InvalidatedAt)
return &t, nil
}, func(v any) (OauthTokenByUserIdRow, error) {
return *(v.(*OauthTokenByUserIdRow)), nil
}
},
},
Mod: bob.ModFunc[*dialect.SelectQuery](func(q *dialect.SelectQuery) {
q.AppendSelect(expressionTypArgs.subExpr(7, 501))
q.SetTable(expressionTypArgs.subExpr(507, 518))
q.AppendWhere(expressionTypArgs.subExpr(526, 538))
}),
}
}
type OauthTokenByUserIdRow = struct {
ID int32 `db:"id"`
AccessToken string `db:"access_token"`
AccessTokenExpires time.Time `db:"access_token_expires"`
RefreshToken string `db:"refresh_token"`
Username string `db:"username"`
UserID int32 `db:"user_id"`
ArcgisID null.Val[string] `db:"arcgis_id"`
ArcgisLicenseTypeID null.Val[string] `db:"arcgis_license_type_id"`
RefreshTokenExpires time.Time `db:"refresh_token_expires"`
InvalidatedAt null.Val[time.Time] `db:"invalidated_at"`
}
type oauthTokenByUserIdTransformer = bob.SliceTransformer[OauthTokenByUserIdRow, []OauthTokenByUserIdRow]
type oauthTokenByUserId struct {
UserID bob.Expression
}
func (o oauthTokenByUserId) args() iter.Seq[orm.ArgWithPosition] {
return func(yield func(arg orm.ArgWithPosition) bool) {
if !yield(orm.ArgWithPosition{
Name: "userID",
Start: 536,
Stop: 538,
Expression: o.UserID,
}) {
return
}
}
}
func (o oauthTokenByUserId) raw(from, to int) string {
return oauthTokenByUserIdSQL[from:to]
}
func (o oauthTokenByUserId) subExpr(from, to int) bob.Expression {
return orm.ArgsToExpression(oauthTokenByUserIdSQL, from, to, o.args())
}
func (o oauthTokenByUserId) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
return o.subExpr(0, len(oauthTokenByUserIdSQL)).WriteSQL(ctx, w, d, start)
}

View file

@ -0,0 +1,6 @@
-- Code generated by BobGen psql v0.41.1. DO NOT EDIT.
-- This file is meant to be re-generated in place and/or deleted at any time.
-- OauthTokenByUserId
SELECT "oauth_token"."id" AS "id", "oauth_token"."access_token" AS "access_token", "oauth_token"."access_token_expires" AS "access_token_expires", "oauth_token"."refresh_token" AS "refresh_token", "oauth_token"."username" AS "username", "oauth_token"."user_id" AS "user_id", "oauth_token"."arcgis_id" AS "arcgis_id", "oauth_token"."arcgis_license_type_id" AS "arcgis_license_type_id", "oauth_token"."refresh_token_expires" AS "refresh_token_expires", "oauth_token"."invalidated_at" AS "invalidated_at" FROM oauth_token WHERE
user_id = $1;

View file

@ -0,0 +1,131 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
"fmt"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
testutils "github.com/stephenafamo/bob/test/utils"
)
func TestOauthTokenByUserId(t *testing.T) {
t.Run("Base", func(t *testing.T) {
var sb strings.Builder
query := OauthTokenByUserId(random_int32(nil))
if _, err := query.WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(oauthTokenByUserIdSQL, sb.String()); diff != "" {
t.Fatalf("unexpected result (-got +want):\n%s", diff)
}
})
t.Run("Mod", func(t *testing.T) {
var sb strings.Builder
query := OauthTokenByUserId(random_int32(nil))
if _, err := psql.Select(query).WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
queryDiff, err := testutils.QueryDiff(oauthTokenByUserIdSQL, sb.String(), formatQuery)
if err != nil {
t.Fatal(err)
}
if queryDiff != "" {
fmt.Println(sb.String())
t.Fatalf("unexpected result (-got +want):\n%s", queryDiff)
}
})
t.Run("Scanning", func(t *testing.T) {
if testDB == nil {
t.Skip("skipping test, no DSN provided")
}
ctxTx, cancel := context.WithCancel(t.Context())
defer cancel()
tx, err := testDB.Begin(ctxTx)
if err != nil {
t.Fatalf("Error starting transaction: %v", err)
}
defer func() {
if err := tx.Rollback(ctxTx); err != nil {
t.Fatalf("Error rolling back transaction: %v", err)
}
}()
query, args, err := bob.Build(ctxTx, psql.Select(OauthTokenByUserId(random_int32(nil))))
if err != nil {
t.Fatal(err)
}
rows, err := tx.QueryContext(ctxTx, query, args...)
if err != nil {
t.Fatal(err)
}
defer rows.Close()
columns, err := rows.Columns()
if err != nil {
t.Fatal(err)
}
if len(columns) != 10 {
t.Fatalf("expected %d columns, got %d", 10, len(columns))
}
if columns[0] != "id" {
t.Fatalf("expected column %d to be %s, got %s", 0, "id", columns[0])
}
if columns[1] != "access_token" {
t.Fatalf("expected column %d to be %s, got %s", 1, "access_token", columns[1])
}
if columns[2] != "access_token_expires" {
t.Fatalf("expected column %d to be %s, got %s", 2, "access_token_expires", columns[2])
}
if columns[3] != "refresh_token" {
t.Fatalf("expected column %d to be %s, got %s", 3, "refresh_token", columns[3])
}
if columns[4] != "username" {
t.Fatalf("expected column %d to be %s, got %s", 4, "username", columns[4])
}
if columns[5] != "user_id" {
t.Fatalf("expected column %d to be %s, got %s", 5, "user_id", columns[5])
}
if columns[6] != "arcgis_id" {
t.Fatalf("expected column %d to be %s, got %s", 6, "arcgis_id", columns[6])
}
if columns[7] != "arcgis_license_type_id" {
t.Fatalf("expected column %d to be %s, got %s", 7, "arcgis_license_type_id", columns[7])
}
if columns[8] != "refresh_token_expires" {
t.Fatalf("expected column %d to be %s, got %s", 8, "refresh_token_expires", columns[8])
}
if columns[9] != "invalidated_at" {
t.Fatalf("expected column %d to be %s, got %s", 9, "invalidated_at", columns[9])
}
})
}

View file

@ -0,0 +1,3 @@
-- OauthTokenByUserId
SELECT * FROM oauth_token WHERE
user_id = $1;

View file

@ -0,0 +1,96 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
_ "embed"
"io"
"iter"
"github.com/aarondl/opt/null"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/bob/dialect/psql/dialect"
"github.com/stephenafamo/bob/orm"
"github.com/stephenafamo/scan"
)
//go:embed org_by_oauth_id.bob.sql
var formattedQueries_org_by_oauth_id string
var orgByOauthIdSQL = formattedQueries_org_by_oauth_id[150:363]
type OrgByOauthIdQuery = orm.ModQuery[*dialect.SelectQuery, orgByOauthId, OrgByOauthIdRow, []OrgByOauthIdRow, orgByOauthIdTransformer]
func OrgByOauthId(ID int32) *OrgByOauthIdQuery {
var expressionTypArgs orgByOauthId
expressionTypArgs.ID = psql.Arg(ID)
return &OrgByOauthIdQuery{
Query: orm.Query[orgByOauthId, OrgByOauthIdRow, []OrgByOauthIdRow, orgByOauthIdTransformer]{
ExecQuery: orm.ExecQuery[orgByOauthId]{
BaseQuery: bob.BaseQuery[orgByOauthId]{
Expression: expressionTypArgs,
Dialect: dialect.Dialect,
QueryType: bob.QueryTypeSelect,
},
},
Scanner: func(context.Context, []string) (func(*scan.Row) (any, error), func(any) (OrgByOauthIdRow, error)) {
return func(row *scan.Row) (any, error) {
var t OrgByOauthIdRow
row.ScheduleScanByIndex(0, &t.OrganizationID)
row.ScheduleScanByIndex(1, &t.ArcgisID)
row.ScheduleScanByIndex(2, &t.FieldseekerURL)
return &t, nil
}, func(v any) (OrgByOauthIdRow, error) {
return *(v.(*OrgByOauthIdRow)), nil
}
},
},
Mod: bob.ModFunc[*dialect.SelectQuery](func(q *dialect.SelectQuery) {
q.AppendSelect(expressionTypArgs.subExpr(7, 94))
q.SetTable(expressionTypArgs.subExpr(100, 196))
q.AppendWhere(expressionTypArgs.subExpr(203, 213))
}),
}
}
type OrgByOauthIdRow = struct {
OrganizationID int32 `db:"organization_id"`
ArcgisID null.Val[string] `db:"arcgis_id"`
FieldseekerURL null.Val[string] `db:"fieldseeker_url"`
}
type orgByOauthIdTransformer = bob.SliceTransformer[OrgByOauthIdRow, []OrgByOauthIdRow]
type orgByOauthId struct {
ID bob.Expression
}
func (o orgByOauthId) args() iter.Seq[orm.ArgWithPosition] {
return func(yield func(arg orm.ArgWithPosition) bool) {
if !yield(orm.ArgWithPosition{
Name: "id",
Start: 211,
Stop: 213,
Expression: o.ID,
}) {
return
}
}
}
func (o orgByOauthId) raw(from, to int) string {
return orgByOauthIdSQL[from:to]
}
func (o orgByOauthId) subExpr(from, to int) bob.Expression {
return orm.ArgsToExpression(orgByOauthIdSQL, from, to, o.args())
}
func (o orgByOauthId) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
return o.subExpr(0, len(orgByOauthIdSQL)).WriteSQL(ctx, w, d, start)
}

View file

@ -0,0 +1,9 @@
-- Code generated by BobGen psql v0.41.1. DO NOT EDIT.
-- This file is meant to be re-generated in place and/or deleted at any time.
-- OrgByOauthId
SELECT o.id AS organization_id, o.arcgis_id AS arcgis_id, o.fieldseeker_url AS fieldseeker_url
FROM oauth_token ot
JOIN user_ u ON ot.user_id = u.id
JOIN organization o ON u.organization_id = o.id
WHERE ot.id = $1;

View file

@ -0,0 +1,103 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
"fmt"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
testutils "github.com/stephenafamo/bob/test/utils"
)
func TestOrgByOauthId(t *testing.T) {
t.Run("Base", func(t *testing.T) {
var sb strings.Builder
query := OrgByOauthId(random_int32(nil))
if _, err := query.WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(orgByOauthIdSQL, sb.String()); diff != "" {
t.Fatalf("unexpected result (-got +want):\n%s", diff)
}
})
t.Run("Mod", func(t *testing.T) {
var sb strings.Builder
query := OrgByOauthId(random_int32(nil))
if _, err := psql.Select(query).WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
queryDiff, err := testutils.QueryDiff(orgByOauthIdSQL, sb.String(), formatQuery)
if err != nil {
t.Fatal(err)
}
if queryDiff != "" {
fmt.Println(sb.String())
t.Fatalf("unexpected result (-got +want):\n%s", queryDiff)
}
})
t.Run("Scanning", func(t *testing.T) {
if testDB == nil {
t.Skip("skipping test, no DSN provided")
}
ctxTx, cancel := context.WithCancel(t.Context())
defer cancel()
tx, err := testDB.Begin(ctxTx)
if err != nil {
t.Fatalf("Error starting transaction: %v", err)
}
defer func() {
if err := tx.Rollback(ctxTx); err != nil {
t.Fatalf("Error rolling back transaction: %v", err)
}
}()
query, args, err := bob.Build(ctxTx, psql.Select(OrgByOauthId(random_int32(nil))))
if err != nil {
t.Fatal(err)
}
rows, err := tx.QueryContext(ctxTx, query, args...)
if err != nil {
t.Fatal(err)
}
defer rows.Close()
columns, err := rows.Columns()
if err != nil {
t.Fatal(err)
}
if len(columns) != 3 {
t.Fatalf("expected %d columns, got %d", 3, len(columns))
}
if columns[0] != "organization_id" {
t.Fatalf("expected column %d to be %s, got %s", 0, "organization_id", columns[0])
}
if columns[1] != "arcgis_id" {
t.Fatalf("expected column %d to be %s, got %s", 1, "arcgis_id", columns[1])
}
if columns[2] != "fieldseeker_url" {
t.Fatalf("expected column %d to be %s, got %s", 2, "fieldseeker_url", columns[2])
}
})
}

View file

@ -0,0 +1,6 @@
-- OrgByOauthId
SELECT o.id AS organization_id, o.arcgis_id AS arcgis_id, o.fieldseeker_url AS fieldseeker_url
FROM oauth_token ot
JOIN user_ u ON ot.user_id = u.id
JOIN organization o ON u.organization_id = o.id
WHERE ot.id = $1

View file

@ -0,0 +1,124 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"strconv"
"strings"
"time"
enums "github.com/Gleipnir-Technology/nidus-sync/db/enums"
"github.com/jaswdr/faker/v2"
"github.com/shopspring/decimal"
"github.com/stephenafamo/bob"
pg_query "github.com/wasilibs/go-pgquery"
)
// Set the testDB to enable tests that use the database
var testDB bob.Transactor[bob.Tx]
func formatQuery(s string) (string, error) {
aTree, err := pg_query.Parse(s)
if err != nil {
return "", err
}
return pg_query.Deparse(aTree)
}
var defaultFaker = faker.New()
func random_decimal_Decimal(f *faker.Faker, limits ...string) decimal.Decimal {
if f == nil {
f = &defaultFaker
}
var precision int64 = 7
var scale int64 = 3
if len(limits) > 0 {
precision, _ = strconv.ParseInt(limits[0], 10, 32)
}
if len(limits) > 1 {
scale, _ = strconv.ParseInt(limits[1], 10, 32)
}
baseVal := f.Float32(10, -1, 1)
for baseVal == -1 || baseVal == 0 || baseVal == 1 {
baseVal = f.Float32(10, -1, 1)
}
precisionDecimal, _ := decimal.NewFromInt(10).PowInt32(int32(precision))
val := decimal.
NewFromFloat32(baseVal).
Mul(precisionDecimal).
Shift(int32(-1 * scale)).
RoundDown(int32(scale))
return val
}
func random_enums_Arcgislicensetype(f *faker.Faker, limits ...string) enums.Arcgislicensetype {
if f == nil {
f = &defaultFaker
}
var e enums.Arcgislicensetype
all := e.All()
return all[f.IntBetween(0, len(all)-1)]
}
func random_enums_Hashtype(f *faker.Faker, limits ...string) enums.Hashtype {
if f == nil {
f = &defaultFaker
}
var e enums.Hashtype
all := e.All()
return all[f.IntBetween(0, len(all)-1)]
}
func random_int32(f *faker.Faker, limits ...string) int32 {
if f == nil {
f = &defaultFaker
}
return f.Int32()
}
func random_int64(f *faker.Faker, limits ...string) int64 {
if f == nil {
f = &defaultFaker
}
return f.Int64()
}
func random_string(f *faker.Faker, limits ...string) string {
if f == nil {
f = &defaultFaker
}
val := strings.Join(f.Lorem().Words(f.IntBetween(1, 5)), " ")
if len(limits) == 0 {
return val
}
limitInt, _ := strconv.Atoi(limits[0])
if limitInt > 0 && limitInt < len(val) {
val = val[:limitInt]
}
return val
}
func random_time_Time(f *faker.Faker, limits ...string) time.Time {
if f == nil {
f = &defaultFaker
}
year := time.Hour * 24 * 365
min := time.Now().Add(-year)
max := time.Now().Add(year)
return f.Time().TimeBetween(min, max)
}

View file

@ -0,0 +1,114 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
_ "embed"
"io"
"iter"
"github.com/aarondl/opt/null"
"github.com/shopspring/decimal"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/bob/dialect/psql/dialect"
"github.com/stephenafamo/bob/expr"
"github.com/stephenafamo/bob/orm"
"github.com/stephenafamo/scan"
)
//go:embed trapcount_by_location_id.bob.sql
var formattedQueries_trapcount_by_location_id string
var trapCountByLocationIDSQL = formattedQueries_trapcount_by_location_id[159:591]
type TrapCountByLocationIDQuery = orm.ModQuery[*dialect.SelectQuery, trapCountByLocationID, TrapCountByLocationIDRow, []TrapCountByLocationIDRow, trapCountByLocationIDTransformer]
func TrapCountByLocationID(OrganizationID int32, LocID []string) *TrapCountByLocationIDQuery {
var expressionTypArgs trapCountByLocationID
expressionTypArgs.OrganizationID = psql.Arg(OrganizationID)
expressionTypArgs.LocID = expr.ToArgs(LocID...)
return &TrapCountByLocationIDQuery{
Query: orm.Query[trapCountByLocationID, TrapCountByLocationIDRow, []TrapCountByLocationIDRow, trapCountByLocationIDTransformer]{
ExecQuery: orm.ExecQuery[trapCountByLocationID]{
BaseQuery: bob.BaseQuery[trapCountByLocationID]{
Expression: expressionTypArgs,
Dialect: dialect.Dialect,
QueryType: bob.QueryTypeSelect,
},
},
Scanner: func(context.Context, []string) (func(*scan.Row) (any, error), func(any) (TrapCountByLocationIDRow, error)) {
return func(row *scan.Row) (any, error) {
var t TrapCountByLocationIDRow
row.ScheduleScanByIndex(0, &t.TrapdataGlobalid)
row.ScheduleScanByIndex(1, &t.TrapdataEnddate)
row.ScheduleScanByIndex(2, &t.TotalFemales)
row.ScheduleScanByIndex(3, &t.TotalMales)
row.ScheduleScanByIndex(4, &t.Total)
return &t, nil
}, func(v any) (TrapCountByLocationIDRow, error) {
return *(v.(*TrapCountByLocationIDRow)), nil
}
},
},
Mod: bob.ModFunc[*dialect.SelectQuery](func(q *dialect.SelectQuery) {
q.AppendSelect(expressionTypArgs.subExpr(12, 223))
q.SetTable(expressionTypArgs.subExpr(234, 318))
q.AppendWhere(expressionTypArgs.subExpr(330, 379))
q.AppendGroup(expressionTypArgs.subExpr(394, 432))
}),
}
}
type TrapCountByLocationIDRow = struct {
TrapdataGlobalid string `db:"trapdata_globalid"`
TrapdataEnddate null.Val[int64] `db:"trapdata_enddate"`
TotalFemales decimal.Decimal `db:"total_females"`
TotalMales int64 `db:"total_males"`
Total decimal.Decimal `db:"total"`
}
type trapCountByLocationIDTransformer = bob.SliceTransformer[TrapCountByLocationIDRow, []TrapCountByLocationIDRow]
type trapCountByLocationID struct {
OrganizationID bob.Expression
LocID bob.Expression
}
func (o trapCountByLocationID) args() iter.Seq[orm.ArgWithPosition] {
return func(yield func(arg orm.ArgWithPosition) bool) {
if !yield(orm.ArgWithPosition{
Name: "organizationID",
Start: 351,
Stop: 353,
Expression: o.OrganizationID,
}) {
return
}
if !yield(orm.ArgWithPosition{
Name: "locID",
Start: 376,
Stop: 378,
Expression: o.LocID,
}) {
return
}
}
}
func (o trapCountByLocationID) raw(from, to int) string {
return trapCountByLocationIDSQL[from:to]
}
func (o trapCountByLocationID) subExpr(from, to int) bob.Expression {
return orm.ArgsToExpression(trapCountByLocationIDSQL, from, to, o.args())
}
func (o trapCountByLocationID) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
return o.subExpr(0, len(trapCountByLocationIDSQL)).WriteSQL(ctx, w, d, start)
}

View file

@ -0,0 +1,19 @@
-- Code generated by BobGen psql v0.41.1. DO NOT EDIT.
-- This file is meant to be re-generated in place and/or deleted at any time.
-- TrapCountByLocationID
SELECT
td.globalid AS trapdata_globalid,
td.enddatetime AS trapdata_enddate,
COALESCE(SUM(sa.females), 0) AS total_females,
COALESCE(SUM(sa.males), 0) AS total_males,
COALESCE(SUM(sa.total), 0) AS total
FROM
fs_trapdata td
LEFT JOIN
fs_speciesabundance sa ON td.globalid = sa.trapdata_id
WHERE
td.organization_id = $1
AND td.loc_id IN ($2)
GROUP BY
td.globalid, td.loc_id, td.enddatetime;

View file

@ -0,0 +1,111 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
"fmt"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
testutils "github.com/stephenafamo/bob/test/utils"
)
func TestTrapCountByLocationID(t *testing.T) {
t.Run("Base", func(t *testing.T) {
var sb strings.Builder
query := TrapCountByLocationID(random_int32(nil), []string{random_string(nil)})
if _, err := query.WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(trapCountByLocationIDSQL, sb.String()); diff != "" {
t.Fatalf("unexpected result (-got +want):\n%s", diff)
}
})
t.Run("Mod", func(t *testing.T) {
var sb strings.Builder
query := TrapCountByLocationID(random_int32(nil), []string{random_string(nil)})
if _, err := psql.Select(query).WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
queryDiff, err := testutils.QueryDiff(trapCountByLocationIDSQL, sb.String(), formatQuery)
if err != nil {
t.Fatal(err)
}
if queryDiff != "" {
fmt.Println(sb.String())
t.Fatalf("unexpected result (-got +want):\n%s", queryDiff)
}
})
t.Run("Scanning", func(t *testing.T) {
if testDB == nil {
t.Skip("skipping test, no DSN provided")
}
ctxTx, cancel := context.WithCancel(t.Context())
defer cancel()
tx, err := testDB.Begin(ctxTx)
if err != nil {
t.Fatalf("Error starting transaction: %v", err)
}
defer func() {
if err := tx.Rollback(ctxTx); err != nil {
t.Fatalf("Error rolling back transaction: %v", err)
}
}()
query, args, err := bob.Build(ctxTx, psql.Select(TrapCountByLocationID(random_int32(nil), []string{random_string(nil)})))
if err != nil {
t.Fatal(err)
}
rows, err := tx.QueryContext(ctxTx, query, args...)
if err != nil {
t.Fatal(err)
}
defer rows.Close()
columns, err := rows.Columns()
if err != nil {
t.Fatal(err)
}
if len(columns) != 5 {
t.Fatalf("expected %d columns, got %d", 5, len(columns))
}
if columns[0] != "trapdata_globalid" {
t.Fatalf("expected column %d to be %s, got %s", 0, "trapdata_globalid", columns[0])
}
if columns[1] != "trapdata_enddate" {
t.Fatalf("expected column %d to be %s, got %s", 1, "trapdata_enddate", columns[1])
}
if columns[2] != "total_females" {
t.Fatalf("expected column %d to be %s, got %s", 2, "total_females", columns[2])
}
if columns[3] != "total_males" {
t.Fatalf("expected column %d to be %s, got %s", 3, "total_males", columns[3])
}
if columns[4] != "total" {
t.Fatalf("expected column %d to be %s, got %s", 4, "total", columns[4])
}
})
}

View file

@ -0,0 +1,17 @@
-- TrapCountByLocationID
SELECT
td.globalid AS trapdata_globalid,
td.enddatetime AS trapdata_enddate,
COALESCE(SUM(sa.females), 0) AS total_females,
COALESCE(SUM(sa.males), 0) AS total_males,
COALESCE(SUM(sa.total), 0) AS total
FROM
fs_trapdata td
LEFT JOIN
fs_speciesabundance sa ON td.globalid = sa.trapdata_id
WHERE
td.organization_id = $1
AND td.loc_id IN ($2)
GROUP BY
td.globalid, td.loc_id, td.enddatetime;

View file

@ -0,0 +1,108 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
_ "embed"
"io"
"iter"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/bob/dialect/psql/dialect"
"github.com/stephenafamo/bob/expr"
"github.com/stephenafamo/bob/orm"
"github.com/stephenafamo/scan"
)
//go:embed trapdata_by_location_id_recent.bob.sql
var formattedQueries_trapdata_by_location_id_recent string
var trapDataByLocationIDRecentSQL = formattedQueries_trapdata_by_location_id_recent[164:454]
type TrapDataByLocationIDRecentQuery = orm.ModQuery[*dialect.SelectQuery, trapDataByLocationIDRecent, TrapDataByLocationIDRecentRow, []TrapDataByLocationIDRecentRow, trapDataByLocationIDRecentTransformer]
func TrapDataByLocationIDRecent(OrganizationID int32, LocID []string) *TrapDataByLocationIDRecentQuery {
var expressionTypArgs trapDataByLocationIDRecent
expressionTypArgs.OrganizationID = psql.Arg(OrganizationID)
expressionTypArgs.LocID = expr.ToArgs(LocID...)
return &TrapDataByLocationIDRecentQuery{
Query: orm.Query[trapDataByLocationIDRecent, TrapDataByLocationIDRecentRow, []TrapDataByLocationIDRecentRow, trapDataByLocationIDRecentTransformer]{
ExecQuery: orm.ExecQuery[trapDataByLocationIDRecent]{
BaseQuery: bob.BaseQuery[trapDataByLocationIDRecent]{
Expression: expressionTypArgs,
Dialect: dialect.Dialect,
QueryType: bob.QueryTypeSelect,
},
},
Scanner: func(context.Context, []string) (func(*scan.Row) (any, error), func(any) (TrapDataByLocationIDRecentRow, error)) {
return func(row *scan.Row) (any, error) {
var t TrapDataByLocationIDRecentRow
row.ScheduleScanByIndex(0, &t.Enddatetime)
row.ScheduleScanByIndex(1, &t.Globalid)
row.ScheduleScanByIndex(2, &t.LocID)
return &t, nil
}, func(v any) (TrapDataByLocationIDRecentRow, error) {
return *(v.(*TrapDataByLocationIDRecentRow)), nil
}
},
},
Mod: bob.ModFunc[*dialect.SelectQuery](func(q *dialect.SelectQuery) {
q.AppendSelect(expressionTypArgs.subExpr(7, 36))
q.SetTable(expressionTypArgs.subExpr(42, 244))
q.AppendWhere(expressionTypArgs.subExpr(251, 264))
q.CombinedOrder.AppendOrder(expressionTypArgs.subExpr(274, 290))
}),
}
}
type TrapDataByLocationIDRecentRow = struct {
Enddatetime int64 `db:"enddatetime"`
Globalid string `db:"globalid"`
LocID string `db:"loc_id"`
}
type trapDataByLocationIDRecentTransformer = bob.SliceTransformer[TrapDataByLocationIDRecentRow, []TrapDataByLocationIDRecentRow]
type trapDataByLocationIDRecent struct {
OrganizationID bob.Expression
LocID bob.Expression
}
func (o trapDataByLocationIDRecent) args() iter.Seq[orm.ArgWithPosition] {
return func(yield func(arg orm.ArgWithPosition) bool) {
if !yield(orm.ArgWithPosition{
Name: "organizationID",
Start: 207,
Stop: 209,
Expression: o.OrganizationID,
}) {
return
}
if !yield(orm.ArgWithPosition{
Name: "locID",
Start: 227,
Stop: 229,
Expression: o.LocID,
}) {
return
}
}
}
func (o trapDataByLocationIDRecent) raw(from, to int) string {
return trapDataByLocationIDRecentSQL[from:to]
}
func (o trapDataByLocationIDRecent) subExpr(from, to int) bob.Expression {
return orm.ArgsToExpression(trapDataByLocationIDRecentSQL, from, to, o.args())
}
func (o trapDataByLocationIDRecent) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
return o.subExpr(0, len(trapDataByLocationIDRecentSQL)).WriteSQL(ctx, w, d, start)
}

View file

@ -0,0 +1,15 @@
-- Code generated by BobGen psql v0.41.1. DO NOT EDIT.
-- This file is meant to be re-generated in place and/or deleted at any time.
-- TrapDataByLocationIDRecent
SELECT enddatetime, globalid, loc_id
FROM (
SELECT enddatetime, globalid, loc_id, ROW_NUMBER()
OVER (PARTITION BY loc_id ORDER BY enddatetime DESC) as row_num
FROM fs_trapdata
WHERE
organization_id = $1 AND
loc_id IN ($2)
) ranked_data
WHERE row_num <= 10
ORDER BY enddatetime DESC;

View file

@ -0,0 +1,103 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
"fmt"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
testutils "github.com/stephenafamo/bob/test/utils"
)
func TestTrapDataByLocationIDRecent(t *testing.T) {
t.Run("Base", func(t *testing.T) {
var sb strings.Builder
query := TrapDataByLocationIDRecent(random_int32(nil), []string{random_string(nil)})
if _, err := query.WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(trapDataByLocationIDRecentSQL, sb.String()); diff != "" {
t.Fatalf("unexpected result (-got +want):\n%s", diff)
}
})
t.Run("Mod", func(t *testing.T) {
var sb strings.Builder
query := TrapDataByLocationIDRecent(random_int32(nil), []string{random_string(nil)})
if _, err := psql.Select(query).WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
queryDiff, err := testutils.QueryDiff(trapDataByLocationIDRecentSQL, sb.String(), formatQuery)
if err != nil {
t.Fatal(err)
}
if queryDiff != "" {
fmt.Println(sb.String())
t.Fatalf("unexpected result (-got +want):\n%s", queryDiff)
}
})
t.Run("Scanning", func(t *testing.T) {
if testDB == nil {
t.Skip("skipping test, no DSN provided")
}
ctxTx, cancel := context.WithCancel(t.Context())
defer cancel()
tx, err := testDB.Begin(ctxTx)
if err != nil {
t.Fatalf("Error starting transaction: %v", err)
}
defer func() {
if err := tx.Rollback(ctxTx); err != nil {
t.Fatalf("Error rolling back transaction: %v", err)
}
}()
query, args, err := bob.Build(ctxTx, psql.Select(TrapDataByLocationIDRecent(random_int32(nil), []string{random_string(nil)})))
if err != nil {
t.Fatal(err)
}
rows, err := tx.QueryContext(ctxTx, query, args...)
if err != nil {
t.Fatal(err)
}
defer rows.Close()
columns, err := rows.Columns()
if err != nil {
t.Fatal(err)
}
if len(columns) != 3 {
t.Fatalf("expected %d columns, got %d", 3, len(columns))
}
if columns[0] != "enddatetime" {
t.Fatalf("expected column %d to be %s, got %s", 0, "enddatetime", columns[0])
}
if columns[1] != "globalid" {
t.Fatalf("expected column %d to be %s, got %s", 1, "globalid", columns[1])
}
if columns[2] != "loc_id" {
t.Fatalf("expected column %d to be %s, got %s", 2, "loc_id", columns[2])
}
})
}

View file

@ -0,0 +1,12 @@
-- TrapDataByLocationIDRecent
SELECT enddatetime, globalid, loc_id
FROM (
SELECT enddatetime, globalid, loc_id, ROW_NUMBER()
OVER (PARTITION BY loc_id ORDER BY enddatetime DESC) as row_num
FROM fs_trapdata
WHERE
organization_id = $1 AND
loc_id IN ($2)
) ranked_data
WHERE row_num <= 10
ORDER BY enddatetime DESC;

View file

@ -0,0 +1,106 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
_ "embed"
"io"
"iter"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/bob/dialect/psql/dialect"
"github.com/stephenafamo/bob/orm"
"github.com/stephenafamo/scan"
)
//go:embed traplocation_by_source_id.bob.sql
var formattedQueries_traplocation_by_source_id string
var trapLocationBySourceIDSQL = formattedQueries_traplocation_by_source_id[160:411]
type TrapLocationBySourceIDQuery = orm.ModQuery[*dialect.SelectQuery, trapLocationBySourceID, TrapLocationBySourceIDRow, []TrapLocationBySourceIDRow, trapLocationBySourceIDTransformer]
func TrapLocationBySourceID(OrganizationID int32, Globalid string) *TrapLocationBySourceIDQuery {
var expressionTypArgs trapLocationBySourceID
expressionTypArgs.OrganizationID = psql.Arg(OrganizationID)
expressionTypArgs.Globalid = psql.Arg(Globalid)
return &TrapLocationBySourceIDQuery{
Query: orm.Query[trapLocationBySourceID, TrapLocationBySourceIDRow, []TrapLocationBySourceIDRow, trapLocationBySourceIDTransformer]{
ExecQuery: orm.ExecQuery[trapLocationBySourceID]{
BaseQuery: bob.BaseQuery[trapLocationBySourceID]{
Expression: expressionTypArgs,
Dialect: dialect.Dialect,
QueryType: bob.QueryTypeSelect,
},
},
Scanner: func(context.Context, []string) (func(*scan.Row) (any, error), func(any) (TrapLocationBySourceIDRow, error)) {
return func(row *scan.Row) (any, error) {
var t TrapLocationBySourceIDRow
row.ScheduleScanByIndex(0, &t.TrapLocationGlobalid)
row.ScheduleScanByIndex(1, &t.Distance)
return &t, nil
}, func(v any) (TrapLocationBySourceIDRow, error) {
return *(v.(*TrapLocationBySourceIDRow)), nil
}
},
},
Mod: bob.ModFunc[*dialect.SelectQuery](func(q *dialect.SelectQuery) {
q.CombinedLimit.SetLimit(psql.Raw("4"))
q.AppendSelect(expressionTypArgs.subExpr(9, 90))
q.SetTable(expressionTypArgs.subExpr(98, 148))
q.AppendWhere(expressionTypArgs.subExpr(157, 202))
q.CombinedOrder.AppendOrder(expressionTypArgs.subExpr(214, 243))
}),
}
}
type TrapLocationBySourceIDRow = struct {
TrapLocationGlobalid string `db:"trap_location_globalid"`
Distance string `db:"distance"`
}
type trapLocationBySourceIDTransformer = bob.SliceTransformer[TrapLocationBySourceIDRow, []TrapLocationBySourceIDRow]
type trapLocationBySourceID struct {
OrganizationID bob.Expression
Globalid bob.Expression
}
func (o trapLocationBySourceID) args() iter.Seq[orm.ArgWithPosition] {
return func(yield func(arg orm.ArgWithPosition) bool) {
if !yield(orm.ArgWithPosition{
Name: "organizationID",
Start: 178,
Stop: 180,
Expression: o.OrganizationID,
}) {
return
}
if !yield(orm.ArgWithPosition{
Name: "globalid",
Start: 200,
Stop: 202,
Expression: o.Globalid,
}) {
return
}
}
}
func (o trapLocationBySourceID) raw(from, to int) string {
return trapLocationBySourceIDSQL[from:to]
}
func (o trapLocationBySourceID) subExpr(from, to int) bob.Expression {
return orm.ArgsToExpression(trapLocationBySourceIDSQL, from, to, o.args())
}
func (o trapLocationBySourceID) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
return o.subExpr(0, len(trapLocationBySourceIDSQL)).WriteSQL(ctx, w, d, start)
}

View file

@ -0,0 +1,17 @@
-- Code generated by BobGen psql v0.41.1. DO NOT EDIT.
-- This file is meant to be re-generated in place and/or deleted at any time.
-- TrapLocationBySourceID
SELECT
tl.globalid AS trap_location_globalid,
ST_Distance(pl.geom, tl.geom) AS distance
FROM
fs_pointlocation pl
CROSS JOIN
fs_traplocation tl
WHERE
tl.organization_id = $1 AND
pl.globalid = $2
ORDER BY
ST_Distance(pl.geom, tl.geom)
LIMIT 4;

View file

@ -0,0 +1,99 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
"fmt"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
testutils "github.com/stephenafamo/bob/test/utils"
)
func TestTrapLocationBySourceID(t *testing.T) {
t.Run("Base", func(t *testing.T) {
var sb strings.Builder
query := TrapLocationBySourceID(random_int32(nil), random_string(nil))
if _, err := query.WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(trapLocationBySourceIDSQL, sb.String()); diff != "" {
t.Fatalf("unexpected result (-got +want):\n%s", diff)
}
})
t.Run("Mod", func(t *testing.T) {
var sb strings.Builder
query := TrapLocationBySourceID(random_int32(nil), random_string(nil))
if _, err := psql.Select(query).WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
queryDiff, err := testutils.QueryDiff(trapLocationBySourceIDSQL, sb.String(), formatQuery)
if err != nil {
t.Fatal(err)
}
if queryDiff != "" {
fmt.Println(sb.String())
t.Fatalf("unexpected result (-got +want):\n%s", queryDiff)
}
})
t.Run("Scanning", func(t *testing.T) {
if testDB == nil {
t.Skip("skipping test, no DSN provided")
}
ctxTx, cancel := context.WithCancel(t.Context())
defer cancel()
tx, err := testDB.Begin(ctxTx)
if err != nil {
t.Fatalf("Error starting transaction: %v", err)
}
defer func() {
if err := tx.Rollback(ctxTx); err != nil {
t.Fatalf("Error rolling back transaction: %v", err)
}
}()
query, args, err := bob.Build(ctxTx, psql.Select(TrapLocationBySourceID(random_int32(nil), random_string(nil))))
if err != nil {
t.Fatal(err)
}
rows, err := tx.QueryContext(ctxTx, query, args...)
if err != nil {
t.Fatal(err)
}
defer rows.Close()
columns, err := rows.Columns()
if err != nil {
t.Fatal(err)
}
if len(columns) != 2 {
t.Fatalf("expected %d columns, got %d", 2, len(columns))
}
if columns[0] != "trap_location_globalid" {
t.Fatalf("expected column %d to be %s, got %s", 0, "trap_location_globalid", columns[0])
}
if columns[1] != "distance" {
t.Fatalf("expected column %d to be %s, got %s", 1, "distance", columns[1])
}
})
}

View file

@ -0,0 +1,14 @@
-- TrapLocationBySourceID
SELECT
tl.globalid AS trap_location_globalid,
ST_Distance(pl.geom, tl.geom) AS distance
FROM
fs_pointlocation pl
CROSS JOIN
fs_traplocation tl
WHERE
tl.organization_id = $1 AND
pl.globalid = $2
ORDER BY
ST_Distance(pl.geom, tl.geom)
LIMIT 4

View file

@ -0,0 +1,95 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
_ "embed"
"io"
"iter"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/bob/dialect/psql/dialect"
"github.com/stephenafamo/bob/orm"
)
//go:embed update_oauth_org.bob.sql
var formattedQueries_update_oauth_org string
var updateOauthTokenOrgSQL = formattedQueries_update_oauth_org[157:249]
type UpdateOauthTokenOrgQuery = orm.ModExecQuery[*dialect.UpdateQuery, updateOauthTokenOrg]
func UpdateOauthTokenOrg(ArcgisID string, ArcgisLicenseTypeID string, RefreshToken string) *UpdateOauthTokenOrgQuery {
var expressionTypArgs updateOauthTokenOrg
expressionTypArgs.ArcgisID = psql.Arg(ArcgisID)
expressionTypArgs.ArcgisLicenseTypeID = psql.Arg(ArcgisLicenseTypeID)
expressionTypArgs.RefreshToken = psql.Arg(RefreshToken)
return &UpdateOauthTokenOrgQuery{
ExecQuery: orm.ExecQuery[updateOauthTokenOrg]{
BaseQuery: bob.BaseQuery[updateOauthTokenOrg]{
Expression: expressionTypArgs,
Dialect: dialect.Dialect,
QueryType: bob.QueryTypeUpdate,
},
},
Mod: bob.ModFunc[*dialect.UpdateQuery](func(q *dialect.UpdateQuery) {
q.Table.Expression = expressionTypArgs.subExpr(7, 18)
q.AppendSet(expressionTypArgs.subExpr(23, 66))
q.AppendWhere(expressionTypArgs.subExpr(74, 92))
}),
}
}
type updateOauthTokenOrg struct {
ArcgisID bob.Expression
ArcgisLicenseTypeID bob.Expression
RefreshToken bob.Expression
}
func (o updateOauthTokenOrg) args() iter.Seq[orm.ArgWithPosition] {
return func(yield func(arg orm.ArgWithPosition) bool) {
if !yield(orm.ArgWithPosition{
Name: "arcgisID",
Start: 35,
Stop: 37,
Expression: o.ArcgisID,
}) {
return
}
if !yield(orm.ArgWithPosition{
Name: "arcgisLicenseTypeID",
Start: 64,
Stop: 66,
Expression: o.ArcgisLicenseTypeID,
}) {
return
}
if !yield(orm.ArgWithPosition{
Name: "refreshToken",
Start: 90,
Stop: 92,
Expression: o.RefreshToken,
}) {
return
}
}
}
func (o updateOauthTokenOrg) raw(from, to int) string {
return updateOauthTokenOrgSQL[from:to]
}
func (o updateOauthTokenOrg) subExpr(from, to int) bob.Expression {
return orm.ArgsToExpression(updateOauthTokenOrgSQL, from, to, o.args())
}
func (o updateOauthTokenOrg) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
return o.subExpr(0, len(updateOauthTokenOrgSQL)).WriteSQL(ctx, w, d, start)
}

View file

@ -0,0 +1,6 @@
-- Code generated by BobGen psql v0.41.1. DO NOT EDIT.
-- This file is meant to be re-generated in place and/or deleted at any time.
-- UpdateOauthTokenOrg
UPDATE oauth_token SET arcgis_id = $1, arcgis_license_type_id = $2
WHERE refresh_token = $3;

View file

@ -0,0 +1,76 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
"fmt"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
testutils "github.com/stephenafamo/bob/test/utils"
)
func TestUpdateOauthTokenOrg(t *testing.T) {
t.Run("Base", func(t *testing.T) {
var sb strings.Builder
query := UpdateOauthTokenOrg(random_string(nil), random_string(nil), random_string(nil))
if _, err := query.WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(updateOauthTokenOrgSQL, sb.String()); diff != "" {
t.Fatalf("unexpected result (-got +want):\n%s", diff)
}
})
t.Run("Mod", func(t *testing.T) {
var sb strings.Builder
query := UpdateOauthTokenOrg(random_string(nil), random_string(nil), random_string(nil))
if _, err := psql.Update(query).WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
queryDiff, err := testutils.QueryDiff(updateOauthTokenOrgSQL, sb.String(), formatQuery)
if err != nil {
t.Fatal(err)
}
if queryDiff != "" {
fmt.Println(sb.String())
t.Fatalf("unexpected result (-got +want):\n%s", queryDiff)
}
})
t.Run("Exec", func(t *testing.T) {
if testDB == nil {
t.Skip("skipping test, no DSN provided")
}
ctxTx, cancel := context.WithCancel(t.Context())
defer cancel()
tx, err := testDB.Begin(ctxTx)
if err != nil {
t.Fatalf("Error starting transaction: %v", err)
}
defer func() {
if err := tx.Rollback(ctxTx); err != nil {
t.Fatalf("Error rolling back transaction: %v", err)
}
}()
query := psql.Update(UpdateOauthTokenOrg(random_string(nil), random_string(nil), random_string(nil)))
if _, err := bob.Exec(ctxTx, tx, query); err != nil {
t.Fatal(err)
}
})
}

View file

@ -0,0 +1,3 @@
-- UpdateOauthTokenOrg
UPDATE oauth_token SET arcgis_id = $1, arcgis_license_type_id = $2
WHERE refresh_token = $3;

View file

@ -0,0 +1,116 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
_ "embed"
"io"
"iter"
"time"
enums "github.com/Gleipnir-Technology/nidus-sync/db/enums"
"github.com/aarondl/opt/null"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/bob/dialect/psql/dialect"
"github.com/stephenafamo/bob/orm"
"github.com/stephenafamo/scan"
)
//go:embed user_by_username.bob.sql
var formattedQueries_user_by_username string
var userByUsernameSQL = formattedQueries_user_by_username[152:773]
type UserByUsernameQuery = orm.ModQuery[*dialect.SelectQuery, userByUsername, UserByUsernameRow, []UserByUsernameRow, userByUsernameTransformer]
func UserByUsername(Username string) *UserByUsernameQuery {
var expressionTypArgs userByUsername
expressionTypArgs.Username = psql.Arg(Username)
return &UserByUsernameQuery{
Query: orm.Query[userByUsername, UserByUsernameRow, []UserByUsernameRow, userByUsernameTransformer]{
ExecQuery: orm.ExecQuery[userByUsername]{
BaseQuery: bob.BaseQuery[userByUsername]{
Expression: expressionTypArgs,
Dialect: dialect.Dialect,
QueryType: bob.QueryTypeSelect,
},
},
Scanner: func(context.Context, []string) (func(*scan.Row) (any, error), func(any) (UserByUsernameRow, error)) {
return func(row *scan.Row) (any, error) {
var t UserByUsernameRow
row.ScheduleScanByIndex(0, &t.ID)
row.ScheduleScanByIndex(1, &t.ArcgisAccessToken)
row.ScheduleScanByIndex(2, &t.ArcgisLicense)
row.ScheduleScanByIndex(3, &t.ArcgisRefreshToken)
row.ScheduleScanByIndex(4, &t.ArcgisRefreshTokenExpires)
row.ScheduleScanByIndex(5, &t.ArcgisRole)
row.ScheduleScanByIndex(6, &t.DisplayName)
row.ScheduleScanByIndex(7, &t.Email)
row.ScheduleScanByIndex(8, &t.OrganizationID)
row.ScheduleScanByIndex(9, &t.Username)
row.ScheduleScanByIndex(10, &t.PasswordHashType)
row.ScheduleScanByIndex(11, &t.PasswordHash)
return &t, nil
}, func(v any) (UserByUsernameRow, error) {
return *(v.(*UserByUsernameRow)), nil
}
},
},
Mod: bob.ModFunc[*dialect.SelectQuery](func(q *dialect.SelectQuery) {
q.AppendSelect(expressionTypArgs.subExpr(7, 551))
q.SetTable(expressionTypArgs.subExpr(557, 562))
q.AppendWhere(expressionTypArgs.subExpr(570, 621))
}),
}
}
type UserByUsernameRow = struct {
ID int32 `db:"id"`
ArcgisAccessToken null.Val[string] `db:"arcgis_access_token"`
ArcgisLicense null.Val[enums.Arcgislicensetype] `db:"arcgis_license"`
ArcgisRefreshToken null.Val[string] `db:"arcgis_refresh_token"`
ArcgisRefreshTokenExpires null.Val[time.Time] `db:"arcgis_refresh_token_expires"`
ArcgisRole null.Val[string] `db:"arcgis_role"`
DisplayName string `db:"display_name"`
Email null.Val[string] `db:"email"`
OrganizationID null.Val[int32] `db:"organization_id"`
Username string `db:"username"`
PasswordHashType enums.Hashtype `db:"password_hash_type"`
PasswordHash string `db:"password_hash"`
}
type userByUsernameTransformer = bob.SliceTransformer[UserByUsernameRow, []UserByUsernameRow]
type userByUsername struct {
Username bob.Expression
}
func (o userByUsername) args() iter.Seq[orm.ArgWithPosition] {
return func(yield func(arg orm.ArgWithPosition) bool) {
if !yield(orm.ArgWithPosition{
Name: "username",
Start: 581,
Stop: 583,
Expression: o.Username,
}) {
return
}
}
}
func (o userByUsername) raw(from, to int) string {
return userByUsernameSQL[from:to]
}
func (o userByUsername) subExpr(from, to int) bob.Expression {
return orm.ArgsToExpression(userByUsernameSQL, from, to, o.args())
}
func (o userByUsername) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
return o.subExpr(0, len(userByUsernameSQL)).WriteSQL(ctx, w, d, start)
}

View file

@ -0,0 +1,7 @@
-- Code generated by BobGen psql v0.41.1. DO NOT EDIT.
-- This file is meant to be re-generated in place and/or deleted at any time.
-- UserByUsername
SELECT "user_"."id" AS "id", "user_"."arcgis_access_token" AS "arcgis_access_token", "user_"."arcgis_license" AS "arcgis_license", "user_"."arcgis_refresh_token" AS "arcgis_refresh_token", "user_"."arcgis_refresh_token_expires" AS "arcgis_refresh_token_expires", "user_"."arcgis_role" AS "arcgis_role", "user_"."display_name" AS "display_name", "user_"."email" AS "email", "user_"."organization_id" AS "organization_id", "user_"."username" AS "username", "user_"."password_hash_type" AS "password_hash_type", "user_"."password_hash" AS "password_hash" FROM user_ WHERE
username = $1 AND
password_hash_type = 'bcrypt-14';

View file

@ -0,0 +1,139 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
"fmt"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
testutils "github.com/stephenafamo/bob/test/utils"
)
func TestUserByUsername(t *testing.T) {
t.Run("Base", func(t *testing.T) {
var sb strings.Builder
query := UserByUsername(random_string(nil))
if _, err := query.WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(userByUsernameSQL, sb.String()); diff != "" {
t.Fatalf("unexpected result (-got +want):\n%s", diff)
}
})
t.Run("Mod", func(t *testing.T) {
var sb strings.Builder
query := UserByUsername(random_string(nil))
if _, err := psql.Select(query).WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
queryDiff, err := testutils.QueryDiff(userByUsernameSQL, sb.String(), formatQuery)
if err != nil {
t.Fatal(err)
}
if queryDiff != "" {
fmt.Println(sb.String())
t.Fatalf("unexpected result (-got +want):\n%s", queryDiff)
}
})
t.Run("Scanning", func(t *testing.T) {
if testDB == nil {
t.Skip("skipping test, no DSN provided")
}
ctxTx, cancel := context.WithCancel(t.Context())
defer cancel()
tx, err := testDB.Begin(ctxTx)
if err != nil {
t.Fatalf("Error starting transaction: %v", err)
}
defer func() {
if err := tx.Rollback(ctxTx); err != nil {
t.Fatalf("Error rolling back transaction: %v", err)
}
}()
query, args, err := bob.Build(ctxTx, psql.Select(UserByUsername(random_string(nil))))
if err != nil {
t.Fatal(err)
}
rows, err := tx.QueryContext(ctxTx, query, args...)
if err != nil {
t.Fatal(err)
}
defer rows.Close()
columns, err := rows.Columns()
if err != nil {
t.Fatal(err)
}
if len(columns) != 12 {
t.Fatalf("expected %d columns, got %d", 12, len(columns))
}
if columns[0] != "id" {
t.Fatalf("expected column %d to be %s, got %s", 0, "id", columns[0])
}
if columns[1] != "arcgis_access_token" {
t.Fatalf("expected column %d to be %s, got %s", 1, "arcgis_access_token", columns[1])
}
if columns[2] != "arcgis_license" {
t.Fatalf("expected column %d to be %s, got %s", 2, "arcgis_license", columns[2])
}
if columns[3] != "arcgis_refresh_token" {
t.Fatalf("expected column %d to be %s, got %s", 3, "arcgis_refresh_token", columns[3])
}
if columns[4] != "arcgis_refresh_token_expires" {
t.Fatalf("expected column %d to be %s, got %s", 4, "arcgis_refresh_token_expires", columns[4])
}
if columns[5] != "arcgis_role" {
t.Fatalf("expected column %d to be %s, got %s", 5, "arcgis_role", columns[5])
}
if columns[6] != "display_name" {
t.Fatalf("expected column %d to be %s, got %s", 6, "display_name", columns[6])
}
if columns[7] != "email" {
t.Fatalf("expected column %d to be %s, got %s", 7, "email", columns[7])
}
if columns[8] != "organization_id" {
t.Fatalf("expected column %d to be %s, got %s", 8, "organization_id", columns[8])
}
if columns[9] != "username" {
t.Fatalf("expected column %d to be %s, got %s", 9, "username", columns[9])
}
if columns[10] != "password_hash_type" {
t.Fatalf("expected column %d to be %s, got %s", 10, "password_hash_type", columns[10])
}
if columns[11] != "password_hash" {
t.Fatalf("expected column %d to be %s, got %s", 11, "password_hash", columns[11])
}
})
}

View file

@ -0,0 +1,4 @@
-- UserByUsername
SELECT * FROM user_ WHERE
username = $1 AND
password_hash_type = 'bcrypt-14';