Use goose for migrations
This commit is contained in:
@ -20,7 +20,19 @@ type CreateBudgetParams struct {
|
||||
}
|
||||
|
||||
func (q *Queries) CreateBudget(ctx context.Context, arg CreateBudgetParams) (Budget, error) {
|
||||
row := q.db.QueryRow(ctx, createBudget, arg.ID, arg.Name)
|
||||
row := q.db.QueryRowContext(ctx, createBudget, arg.ID, arg.Name)
|
||||
var i Budget
|
||||
err := row.Scan(&i.ID, &i.Name, &i.LastModification)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getBudget = `-- name: GetBudget :one
|
||||
SELECT id, name, last_modification FROM budgets
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetBudget(ctx context.Context, id string) (Budget, error) {
|
||||
row := q.db.QueryRowContext(ctx, getBudget, id)
|
||||
var i Budget
|
||||
err := row.Scan(&i.ID, &i.Name, &i.LastModification)
|
||||
return i, err
|
||||
@ -33,7 +45,7 @@ WHERE user_budgets.user_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetBudgetsForUser(ctx context.Context, userID string) ([]Budget, error) {
|
||||
rows, err := q.db.Query(ctx, getBudgetsForUser, userID)
|
||||
rows, err := q.db.QueryContext(ctx, getBudgetsForUser, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -46,6 +58,9 @@ func (q *Queries) GetBudgetsForUser(ctx context.Context, userID string) ([]Budge
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -2,23 +2,19 @@ package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"git.javil.eu/jacob1123/budgeteer"
|
||||
)
|
||||
|
||||
// Budget returns a budget for a given id.
|
||||
func (s *Repository) Budget(id string) (*budgeteer.Budget, error) {
|
||||
b := &budgeteer.Budget{ID: id}
|
||||
err := s.DB.Select(&b)
|
||||
func (s *Repository) Budget(id string) (*Budget, error) {
|
||||
budget, err := s.DB.GetBudget(context.Background(), id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
return &budget, nil
|
||||
}
|
||||
|
||||
func (s *Repository) BudgetsForUser(id string) ([]Budget, error) {
|
||||
budgets, err := s.DB.GetBudgetsForUser(context.Background(), sql.NullString{id, true})
|
||||
budgets, err := s.DB.GetBudgetsForUser(context.Background(), id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -26,7 +22,7 @@ func (s *Repository) BudgetsForUser(id string) ([]Budget, error) {
|
||||
|
||||
}
|
||||
|
||||
func (s *Repository) NewBudget(name string, userID string) (Budget, error) {
|
||||
func (s *Repository) NewBudget(name string, userID string) (*Budget, error) {
|
||||
b := CreateBudgetParams{ID: s.IDGenerator.New(), Name: name}
|
||||
budget, err := s.DB.CreateBudget(context.Background(), b)
|
||||
if err != nil {
|
||||
@ -39,5 +35,5 @@ func (s *Repository) NewBudget(name string, userID string) (Budget, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return budget, nil
|
||||
return &budget, nil
|
||||
}
|
||||
|
@ -1,17 +1,29 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"embed"
|
||||
"fmt"
|
||||
|
||||
"github.com/jackc/pgx/v4"
|
||||
_ "github.com/jackc/pgx/v4/stdlib"
|
||||
"github.com/pressly/goose/v3"
|
||||
)
|
||||
|
||||
// go:embed schema/*.sql
|
||||
var migrations embed.FS
|
||||
|
||||
// Connect to a database
|
||||
func Connect(server string, user string, password string, database string) (*Queries, error) {
|
||||
conn, err := pgx.Connect(context.Background(), fmt.Sprintf("postgresql://%s:%s@%s/%s", user, password, server, database))
|
||||
connString := fmt.Sprintf("pgx://%s:%s@%s/%s", user, password, server, database)
|
||||
conn, err := sql.Open("pgx", connString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
goose.SetBaseFS(migrations)
|
||||
if err = goose.Up(conn, "schema"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return New(conn), nil
|
||||
}
|
||||
|
@ -4,15 +4,14 @@ package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgconn"
|
||||
"github.com/jackc/pgx/v4"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
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
|
||||
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
|
||||
PrepareContext(context.Context, string) (*sql.Stmt, error)
|
||||
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
|
||||
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
@ -23,7 +22,7 @@ type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
|
||||
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
|
@ -13,10 +13,10 @@ type Budget struct {
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID sql.NullString
|
||||
Email sql.NullString
|
||||
Name sql.NullString
|
||||
Password sql.NullString
|
||||
ID string
|
||||
Email string
|
||||
Name string
|
||||
Password string
|
||||
}
|
||||
|
||||
type UserBudget struct {
|
||||
|
@ -1,9 +1,3 @@
|
||||
CREATE TABLE budgets (
|
||||
id char(26) NOT NULL,
|
||||
name text NOT NULL,
|
||||
last_modification timestamp with time zone
|
||||
);
|
||||
|
||||
-- name: CreateBudget :one
|
||||
INSERT INTO budgets
|
||||
(id, name, last_modification)
|
||||
@ -13,4 +7,8 @@ RETURNING *;
|
||||
-- name: GetBudgetsForUser :many
|
||||
SELECT budgets.* FROM budgets
|
||||
LEFT JOIN user_budgets ON budgets.id = user_budgets.budget_id
|
||||
WHERE user_budgets.user_id = $1;
|
||||
WHERE user_budgets.user_id = $1;
|
||||
|
||||
-- name: GetBudget :one
|
||||
SELECT * FROM budgets
|
||||
WHERE id = $1;
|
@ -1,8 +1,3 @@
|
||||
CREATE TABLE user_budgets (
|
||||
user_id char(26) NOT NULL,
|
||||
budget_id char(26) NOT NULL
|
||||
);
|
||||
|
||||
-- name: LinkBudgetToUser :one
|
||||
INSERT INTO user_budgets
|
||||
(user_id, budget_id)
|
@ -1,10 +1,3 @@
|
||||
CREATE TABLE users (
|
||||
id char(26),
|
||||
email text,
|
||||
name text,
|
||||
password text
|
||||
);
|
||||
|
||||
-- name: GetUserByUsername :one
|
||||
SELECT * FROM users
|
||||
WHERE email = $1;
|
@ -1,11 +1,20 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"git.javil.eu/jacob1123/budgeteer"
|
||||
)
|
||||
|
||||
// Repository represents a PostgreSQL implementation of all ModelServices
|
||||
type Repository struct {
|
||||
DB *Queries
|
||||
IDGenerator budgeteer.IDGenerator
|
||||
IDGenerator *UlidGenerator
|
||||
}
|
||||
|
||||
func NewRepository(queries *Queries) (*Repository, error) {
|
||||
id, err := NewGenerator()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repo := &Repository{
|
||||
DB: queries,
|
||||
IDGenerator: id,
|
||||
}
|
||||
return repo, nil
|
||||
}
|
||||
|
9
postgres/schema/0001_budgets.sql
Normal file
9
postgres/schema/0001_budgets.sql
Normal file
@ -0,0 +1,9 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE budgets (
|
||||
id char(26) NOT NULL,
|
||||
name text NOT NULL,
|
||||
last_modification timestamp with time zone
|
||||
);
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE budgets;
|
8
postgres/schema/0002_user_budgets.sql
Normal file
8
postgres/schema/0002_user_budgets.sql
Normal file
@ -0,0 +1,8 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE user_budgets (
|
||||
user_id char(26) NOT NULL,
|
||||
budget_id char(26) NOT NULL
|
||||
);
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE user_budgets;
|
10
postgres/schema/0003_users.sql
Normal file
10
postgres/schema/0003_users.sql
Normal file
@ -0,0 +1,10 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE users (
|
||||
id char(26) NOT NULL,
|
||||
email text NOT NULL,
|
||||
name text NOT NULL,
|
||||
password text NOT NULL
|
||||
);
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE users;
|
27
postgres/ulid.go
Normal file
27
postgres/ulid.go
Normal file
@ -0,0 +1,27 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/oklog/ulid"
|
||||
)
|
||||
|
||||
type UlidGenerator struct {
|
||||
time time.Time
|
||||
entropy *rand.Rand
|
||||
}
|
||||
|
||||
func NewGenerator() (*UlidGenerator, error) {
|
||||
t := time.Time{}
|
||||
ug := &UlidGenerator{
|
||||
time: t,
|
||||
entropy: rand.New(rand.NewSource(t.UnixNano())),
|
||||
}
|
||||
return ug, nil
|
||||
}
|
||||
|
||||
func (ug *UlidGenerator) New() string {
|
||||
id := ulid.MustNew(ulid.Timestamp(time.Now()), ug.entropy)
|
||||
return id.String()
|
||||
}
|
@ -20,7 +20,7 @@ type LinkBudgetToUserParams struct {
|
||||
}
|
||||
|
||||
func (q *Queries) LinkBudgetToUser(ctx context.Context, arg LinkBudgetToUserParams) (UserBudget, error) {
|
||||
row := q.db.QueryRow(ctx, linkBudgetToUser, arg.UserID, arg.BudgetID)
|
||||
row := q.db.QueryRowContext(ctx, linkBudgetToUser, arg.UserID, arg.BudgetID)
|
||||
var i UserBudget
|
||||
err := row.Scan(&i.UserID, &i.BudgetID)
|
||||
return i, err
|
||||
|
@ -5,7 +5,6 @@ package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
const createUser = `-- name: CreateUser :one
|
||||
@ -16,14 +15,14 @@ RETURNING id, email, name, password
|
||||
`
|
||||
|
||||
type CreateUserParams struct {
|
||||
ID sql.NullString
|
||||
Email sql.NullString
|
||||
Name sql.NullString
|
||||
Password sql.NullString
|
||||
ID string
|
||||
Email string
|
||||
Name string
|
||||
Password string
|
||||
}
|
||||
|
||||
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error) {
|
||||
row := q.db.QueryRow(ctx, createUser,
|
||||
row := q.db.QueryRowContext(ctx, createUser,
|
||||
arg.ID,
|
||||
arg.Email,
|
||||
arg.Name,
|
||||
@ -44,8 +43,8 @@ SELECT id, email, name, password FROM users
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUser(ctx context.Context, id sql.NullString) (User, error) {
|
||||
row := q.db.QueryRow(ctx, getUser, id)
|
||||
func (q *Queries) GetUser(ctx context.Context, id string) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, getUser, id)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
@ -61,8 +60,8 @@ SELECT id, email, name, password FROM users
|
||||
WHERE email = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUserByUsername(ctx context.Context, email sql.NullString) (User, error) {
|
||||
row := q.db.QueryRow(ctx, getUserByUsername, email)
|
||||
func (q *Queries) GetUserByUsername(ctx context.Context, email string) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, getUserByUsername, email)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
|
Reference in New Issue
Block a user