Files
grosbeak/internal/domain64/database.go
Matt Jadud f53639af2f Queueing, prepping to fetch
A lot more to go, but this is the core.

Need to think about how to test the queue handlers.
2025-11-30 21:29:30 -05:00

184 lines
4.5 KiB
Go

package domain64
import (
"context"
"database/sql"
_ "embed"
"fmt"
"log"
"slices"
"sync"
sqlc "git.jadud.com/jadudm/grosbeak/internal/domain64/sqlc"
"github.com/jpillora/go-tld"
)
//go:embed sqlc/schema.sql
var ddl string
type Domain64Map struct {
mu sync.Mutex
m map[string]int
DB *sql.DB
Queries *sqlc.Queries
}
func NewDomain64Map() (*Domain64Map, error) {
d64m := &Domain64Map{}
d64m.DB = nil
d64m.Queries = nil
return d64m, nil
}
func (d64m *Domain64Map) Setup(db *sql.DB) {
log.Printf("creating domain64 tables\n")
if _, err := db.ExecContext(context.Background(), ddl); err != nil {
log.Printf("setup err: %s", err.Error())
panic(err)
}
d64m.DB = db
d64m.Queries = sqlc.New(db)
}
func (d64m *Domain64Map) URLToRFQDN(url *tld.URL) string {
s := ""
if url.TLD != "" {
s += url.TLD
}
if url.Domain != "" {
s += "." + url.Domain
}
if url.Subdomain != "" {
s += "." + url.Subdomain
}
s += url.Path
return s
}
func _get_or_insert_tld(queries *sqlc.Queries, d64 *Domain64, url *tld.URL) error {
ctx := context.Background()
tld_id, err := queries.GetTLDId(ctx, url.TLD)
if err != nil {
cnt, err := queries.CountTLDs(ctx)
if err != nil {
return err
}
d64.TLD = cnt + 1
err = queries.InsertTLD(ctx, sqlc.InsertTLDParams{TldID: d64.TLD, Tld: url.TLD})
if err != nil {
return err
}
} else {
d64.TLD = tld_id
}
return nil
}
func _get_or_insert_domain(queries *sqlc.Queries, d64 *Domain64, url *tld.URL) error {
ctx := context.Background()
domain_id, err := queries.GetDomainId(ctx, sqlc.GetDomainIdParams{TldID: d64.TLD, Domain: url.Domain})
if err != nil {
cnt, err := queries.CountDomains(ctx, d64.TLD)
if err != nil {
return err
}
d64.Domain = cnt + 1
err = queries.InsertDomain(ctx, sqlc.InsertDomainParams{TldID: d64.TLD, DomainID: d64.Domain, Domain: url.Domain})
if err != nil {
return err
}
} else {
d64.Domain = domain_id
}
return nil
}
func _get_or_insert_subdomain(queries *sqlc.Queries, d64 *Domain64, url *tld.URL) error {
ctx := context.Background()
subdomain_id, err := queries.GetSubdomainId(ctx, sqlc.GetSubdomainIdParams{
TldID: int64(d64.TLD), DomainID: int64(d64.Domain), Subdomain: url.Subdomain,
})
if err != nil {
if url.Subdomain == "" {
d64.Subdomain = 0
} else {
cnt, err := queries.CountSubdomains(ctx, sqlc.CountSubdomainsParams{TldID: d64.TLD, DomainID: d64.Domain})
if err != nil {
return err
}
d64.Subdomain = cnt + 1
err = queries.InsertSubdomain(ctx, sqlc.InsertSubdomainParams{TldID: d64.TLD, DomainID: d64.Domain, SubdomainID: d64.Subdomain, Subdomain: url.Subdomain})
if err != nil {
return err
}
}
} else {
d64.Subdomain = subdomain_id
}
return nil
}
func _get_or_insert_path(queries *sqlc.Queries, d64 *Domain64, url *tld.URL) error {
ctx := context.Background()
log.Println(url, url.Path)
path_id, err := queries.GetPathId(ctx, sqlc.GetPathIdParams{
TldID: d64.TLD, DomainID: d64.Domain, SubdomainID: d64.Subdomain, Path: url.Path,
})
if err != nil {
if url.Path == "/" {
d64.Path = 0
} else {
cnt, err := queries.CountPaths(ctx, sqlc.CountPathsParams{TldID: d64.TLD, DomainID: d64.Domain, SubdomainID: d64.Subdomain})
if err != nil {
return err
}
d64.Path = cnt + 1
err = queries.InsertPath(ctx, sqlc.InsertPathParams{TldID: d64.TLD, DomainID: d64.Domain, SubdomainID: d64.Subdomain, PathID: d64.Path, Path: url.Path})
if err != nil {
return err
}
}
} else {
d64.Path = path_id
}
return nil
}
// FIXME: This feels like a very convoluted way to maintain the domain names.
// However, I also need to maintain uniqueness. Can I do this in one table?
func (d64m *Domain64Map) URLToDomain64(url *tld.URL) (*Domain64, error) {
allowed_schemes := []string{"https"}
if !slices.Contains(allowed_schemes, url.Scheme) {
return nil, fmt.Errorf("URL scheme must be in %q; given %s", allowed_schemes, url.Scheme)
}
d64 := &Domain64{}
// These manipulate both the DB and the Domain64 struct
err := _get_or_insert_tld(d64m.Queries, d64, url)
if err != nil {
return nil, err
}
err = _get_or_insert_domain(d64m.Queries, d64, url)
if err != nil {
return nil, err
}
err = _get_or_insert_subdomain(d64m.Queries, d64, url)
if err != nil {
return nil, err
}
err = _get_or_insert_path(d64m.Queries, d64, url)
if err != nil {
return nil, err
}
return d64, nil
}
func NullInt64(i int64) sql.NullInt64 {
return sql.NullInt64{Int64: i, Valid: true}
}
func NullString(s string) sql.NullString {
return sql.NullString{String: s, Valid: true}
}