Initial commot
Have got DB creation and migration working
This commit is contained in:
commit
4ecc12f035
9
docker-compose.yml
Normal file
9
docker-compose.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
version: "3"
|
||||
|
||||
services:
|
||||
db:
|
||||
image: "postgres:17.2"
|
||||
ports:
|
||||
- "5432:5432"
|
||||
environment:
|
||||
POSTGRES_PASSWORD: postgres
|
32
gen/sqlc/dbq/db.go
Normal file
32
gen/sqlc/dbq/db.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
|
||||
package dbq
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
|
||||
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
|
||||
QueryRow(context.Context, string, ...interface{}) pgx.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
13
gen/sqlc/dbq/models.go
Normal file
13
gen/sqlc/dbq/models.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
|
||||
package dbq
|
||||
|
||||
type Site struct {
|
||||
ID int64
|
||||
Name string
|
||||
Url string
|
||||
Theme string
|
||||
Props []byte
|
||||
}
|
56
gen/sqlc/dbq/sites.sql.go
Normal file
56
gen/sqlc/dbq/sites.sql.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// source: sites.sql
|
||||
|
||||
package dbq
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const listSites = `-- name: ListSites :one
|
||||
SELECT id, name, url, theme, props FROM site
|
||||
`
|
||||
|
||||
func (q *Queries) ListSites(ctx context.Context) (Site, error) {
|
||||
row := q.db.QueryRow(ctx, listSites)
|
||||
var i Site
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Url,
|
||||
&i.Theme,
|
||||
&i.Props,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const newSite = `-- name: NewSite :one
|
||||
INSERT INTO site (
|
||||
name,
|
||||
url,
|
||||
theme,
|
||||
props
|
||||
) VALUES ($1, $2, $3, $4)
|
||||
RETURNING id
|
||||
`
|
||||
|
||||
type NewSiteParams struct {
|
||||
Name string
|
||||
Url string
|
||||
Theme string
|
||||
Props []byte
|
||||
}
|
||||
|
||||
func (q *Queries) NewSite(ctx context.Context, arg NewSiteParams) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, newSite,
|
||||
arg.Name,
|
||||
arg.Url,
|
||||
arg.Theme,
|
||||
arg.Props,
|
||||
)
|
||||
var id int64
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
}
|
21
go.mod
Normal file
21
go.mod
Normal file
|
@ -0,0 +1,21 @@
|
|||
module lmika.dev/lmika/hugo-crm
|
||||
|
||||
go 1.23.3
|
||||
|
||||
require (
|
||||
github.com/golang-migrate/migrate/v4 v4.18.1
|
||||
github.com/jackc/pgx/v5 v5.7.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
)
|
33
go.sum
Normal file
33
go.sum
Normal file
|
@ -0,0 +1,33 @@
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/golang-migrate/migrate/v4 v4.18.1 h1:JML/k+t4tpHCpQTCAD62Nu43NUFzHY4CV3uAuvHGC+Y=
|
||||
github.com/golang-migrate/migrate/v4 v4.18.1/go.mod h1:HAX6m3sQgcdO81tdjn5exv20+3Kb13cmGli1hrD6hks=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa h1:s+4MhCQ6YrzisK6hFJUX53drDT4UsSW3DEhKn0ifuHw=
|
||||
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI=
|
||||
github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
30
main.go
Normal file
30
main.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"lmika.dev/lmika/hugo-crm/models"
|
||||
"lmika.dev/lmika/hugo-crm/providers/db"
|
||||
"log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
dbp, err := db.New("postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer dbp.Close()
|
||||
|
||||
log.Println("Connected to database")
|
||||
if err := dbp.Migrate(context.Background()); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Println("Database migrated")
|
||||
|
||||
if err := dbp.InsertSite(context.Background(), &models.Site{
|
||||
Name: "Test site",
|
||||
URL: "https://www.testsite.com",
|
||||
}); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
7
models/sites.go
Normal file
7
models/sites.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package models
|
||||
|
||||
type Site struct {
|
||||
ID int64
|
||||
Name string
|
||||
URL string
|
||||
}
|
59
providers/db/provider.go
Normal file
59
providers/db/provider.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
_ "github.com/golang-migrate/migrate/v4/database/pgx/v5"
|
||||
"github.com/golang-migrate/migrate/v4/source/iofs"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
"lmika.dev/lmika/hugo-crm/gen/sqlc/dbq"
|
||||
"lmika.dev/lmika/hugo-crm/sql"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type DB struct {
|
||||
url string
|
||||
pool *pgxpool.Pool
|
||||
q *dbq.Queries
|
||||
}
|
||||
|
||||
func New(url string) (*DB, error) {
|
||||
pool, err := pgxpool.New(context.Background(), url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &DB{
|
||||
url: url,
|
||||
pool: pool,
|
||||
q: dbq.New(pool),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (db *DB) Close() {
|
||||
db.pool.Close()
|
||||
}
|
||||
|
||||
func (db *DB) Ping(ctx context.Context) error {
|
||||
return db.pool.Ping(ctx)
|
||||
}
|
||||
|
||||
func (db *DB) Migrate(ctx context.Context) error {
|
||||
ms, err := iofs.New(sql.FS, "schema")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dbURL := "pgx5://" + strings.TrimPrefix(db.url, "postgres://")
|
||||
|
||||
m, err := migrate.NewWithSourceInstance("iofs", ms, dbURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = m.Up()
|
||||
if err != nil && !errors.Is(err, migrate.ErrNoChange) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
21
providers/db/sites.go
Normal file
21
providers/db/sites.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"lmika.dev/lmika/hugo-crm/gen/sqlc/dbq"
|
||||
"lmika.dev/lmika/hugo-crm/models"
|
||||
)
|
||||
|
||||
func (db *DB) InsertSite(ctx context.Context, site *models.Site) error {
|
||||
id, err := db.q.NewSite(ctx, dbq.NewSiteParams{
|
||||
Name: site.Name,
|
||||
Url: site.URL,
|
||||
Theme: "default",
|
||||
Props: []byte("{}"),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
site.ID = id
|
||||
return nil
|
||||
}
|
6
sql/fs.go
Normal file
6
sql/fs.go
Normal file
|
@ -0,0 +1,6 @@
|
|||
package sql
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:embed schema/*.sql
|
||||
var FS embed.FS
|
11
sql/queries/sites.sql
Normal file
11
sql/queries/sites.sql
Normal file
|
@ -0,0 +1,11 @@
|
|||
-- name: ListSites :one
|
||||
SELECT * FROM site;
|
||||
|
||||
-- name: NewSite :one
|
||||
INSERT INTO site (
|
||||
name,
|
||||
url,
|
||||
theme,
|
||||
props
|
||||
) VALUES ($1, $2, $3, $4)
|
||||
RETURNING id;
|
7
sql/schema/1_init.up.sql
Normal file
7
sql/schema/1_init.up.sql
Normal file
|
@ -0,0 +1,7 @@
|
|||
CREATE TABLE site (
|
||||
id BIGSERIAL NOT NULL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
url TEXT NOT NULL,
|
||||
theme TEXT NOT NULL,
|
||||
props JSON NOT NULL
|
||||
);
|
Loading…
Reference in a new issue