Use uuid.UUID everywhere and have postgres generate ids

This commit is contained in:
2021-11-29 21:49:37 +00:00
parent 5e8a98872f
commit 85ef7557c1
19 changed files with 199 additions and 93 deletions

View File

@ -5,46 +5,43 @@ package postgres
import (
"context"
"github.com/google/uuid"
)
const createBudget = `-- name: CreateBudget :one
INSERT INTO budgets
(id, name, last_modification)
VALUES ($1, $2, NOW())
RETURNING id, name, last_modification
(name, last_modification)
VALUES ($1, NOW())
RETURNING name, last_modification, id
`
type CreateBudgetParams struct {
ID string
Name string
}
func (q *Queries) CreateBudget(ctx context.Context, arg CreateBudgetParams) (Budget, error) {
row := q.db.QueryRowContext(ctx, createBudget, arg.ID, arg.Name)
func (q *Queries) CreateBudget(ctx context.Context, name string) (Budget, error) {
row := q.db.QueryRowContext(ctx, createBudget, name)
var i Budget
err := row.Scan(&i.ID, &i.Name, &i.LastModification)
err := row.Scan(&i.Name, &i.LastModification, &i.ID)
return i, err
}
const getBudget = `-- name: GetBudget :one
SELECT id, name, last_modification FROM budgets
SELECT name, last_modification, id FROM budgets
WHERE id = $1
`
func (q *Queries) GetBudget(ctx context.Context, id string) (Budget, error) {
func (q *Queries) GetBudget(ctx context.Context, id uuid.UUID) (Budget, error) {
row := q.db.QueryRowContext(ctx, getBudget, id)
var i Budget
err := row.Scan(&i.ID, &i.Name, &i.LastModification)
err := row.Scan(&i.Name, &i.LastModification, &i.ID)
return i, err
}
const getBudgetsForUser = `-- name: GetBudgetsForUser :many
SELECT budgets.id, budgets.name, budgets.last_modification FROM budgets
SELECT budgets.name, budgets.last_modification, budgets.id FROM budgets
LEFT JOIN user_budgets ON budgets.id = user_budgets.budget_id
WHERE user_budgets.user_id = $1
`
func (q *Queries) GetBudgetsForUser(ctx context.Context, userID string) ([]Budget, error) {
func (q *Queries) GetBudgetsForUser(ctx context.Context, userID uuid.UUID) ([]Budget, error) {
rows, err := q.db.QueryContext(ctx, getBudgetsForUser, userID)
if err != nil {
return nil, err
@ -53,7 +50,7 @@ func (q *Queries) GetBudgetsForUser(ctx context.Context, userID string) ([]Budge
var items []Budget
for rows.Next() {
var i Budget
if err := rows.Scan(&i.ID, &i.Name, &i.LastModification); err != nil {
if err := rows.Scan(&i.Name, &i.LastModification, &i.ID); err != nil {
return nil, err
}
items = append(items, i)

View File

@ -2,10 +2,12 @@ package postgres
import (
"context"
"github.com/google/uuid"
)
// Budget returns a budget for a given id.
func (s *Repository) Budget(id string) (*Budget, error) {
func (s *Repository) Budget(id uuid.UUID) (*Budget, error) {
budget, err := s.DB.GetBudget(context.Background(), id)
if err != nil {
return nil, err
@ -13,7 +15,7 @@ func (s *Repository) Budget(id string) (*Budget, error) {
return &budget, nil
}
func (s *Repository) BudgetsForUser(id string) ([]Budget, error) {
func (s *Repository) BudgetsForUser(id uuid.UUID) ([]Budget, error) {
budgets, err := s.DB.GetBudgetsForUser(context.Background(), id)
if err != nil {
return nil, err
@ -22,9 +24,8 @@ func (s *Repository) BudgetsForUser(id 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)
func (s *Repository) NewBudget(name string, userID uuid.UUID) (*Budget, error) {
budget, err := s.DB.CreateBudget(context.Background(), name)
if err != nil {
return nil, err
}

View File

@ -4,22 +4,33 @@ package postgres
import (
"database/sql"
"time"
"github.com/google/uuid"
)
type Budget struct {
ID string
Name string
LastModification sql.NullTime
ID uuid.UUID
}
type Transaction struct {
ID uuid.UUID
BudgetID uuid.UUID
Date time.Time
Memo sql.NullString
Amount string
}
type User struct {
ID string
Email string
Name string
Password string
ID uuid.UUID
}
type UserBudget struct {
UserID string
BudgetID string
UserID uuid.UUID
BudgetID uuid.UUID
}

View File

@ -1,7 +1,7 @@
-- name: CreateBudget :one
INSERT INTO budgets
(id, name, last_modification)
VALUES ($1, $2, NOW())
(name, last_modification)
VALUES ($1, NOW())
RETURNING *;
-- name: GetBudgetsForUser :many

View File

@ -0,0 +1,9 @@
-- name: CreateTransaction :one
INSERT INTO transactions
(budget_id, date, memo, amount)
VALUES ($1, $2, $3, $4)
RETURNING *;
-- name: GetTransactionsForBudget :many
SELECT transactions.* FROM transactions
WHERE transactions.budget_id = $1;

View File

@ -2,19 +2,12 @@ package postgres
// Repository represents a PostgreSQL implementation of all ModelServices
type Repository struct {
DB *Queries
IDGenerator *UlidGenerator
DB *Queries
}
func NewRepository(queries *Queries) (*Repository, error) {
id, err := NewGenerator()
if err != nil {
return nil, err
}
repo := &Repository{
DB: queries,
IDGenerator: id,
DB: queries,
}
return repo, nil
}

View File

@ -0,0 +1,11 @@
-- +goose Up
CREATE TABLE transactions (
id uuid DEFAULT uuid_generate_v4() NOT NULL,
budget_id uuid NOT NULL,
date date NOT NULL,
memo text NULL,
amount decimal(12,2) NOT NULL
);
-- +goose Down
DROP TABLE transactions;

View File

@ -0,0 +1,23 @@
-- +goose Up
ALTER TABLE budgets DROP COLUMN id;
ALTER TABLE budgets ADD COLUMN id uuid DEFAULT uuid_generate_v4() NOT NULL;
ALTER TABLE users DROP COLUMN id;
ALTER TABLE users ADD COLUMN id uuid DEFAULT uuid_generate_v4() NOT NULL;
ALTER TABLE user_budgets DROP COLUMN user_id;
ALTER TABLE user_budgets DROP COLUMN budget_id;
ALTER TABLE user_budgets ADD COLUMN user_id uuid NOT NULL;
ALTER TABLE user_budgets ADD COLUMN budget_id uuid NOT NULL;
-- +goose Down
ALTER TABLE budgets DROP COLUMN id;
ALTER TABLE budgets ADD COLUMN id char(26) NOT NULL;
ALTER TABLE users DROP COLUMN id;
ALTER TABLE users ADD COLUMN id char(26) NOT NULL;
ALTER TABLE user_budgets DROP COLUMN user_id;
ALTER TABLE user_budgets DROP COLUMN budget_id;
ALTER TABLE user_budgets ADD COLUMN user_id char(26) NOT NULL;
ALTER TABLE user_budgets ADD COLUMN budget_id char(26) NOT NULL;

View File

@ -0,0 +1,78 @@
// Code generated by sqlc. DO NOT EDIT.
// source: transactions.sql
package postgres
import (
"context"
"database/sql"
"time"
"github.com/google/uuid"
)
const createTransaction = `-- name: CreateTransaction :one
INSERT INTO transactions
(budget_id, date, memo, amount)
VALUES ($1, $2, $3, $4)
RETURNING id, budget_id, date, memo, amount
`
type CreateTransactionParams struct {
BudgetID uuid.UUID
Date time.Time
Memo sql.NullString
Amount string
}
func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionParams) (Transaction, error) {
row := q.db.QueryRowContext(ctx, createTransaction,
arg.BudgetID,
arg.Date,
arg.Memo,
arg.Amount,
)
var i Transaction
err := row.Scan(
&i.ID,
&i.BudgetID,
&i.Date,
&i.Memo,
&i.Amount,
)
return i, err
}
const getTransactionsForBudget = `-- name: GetTransactionsForBudget :many
SELECT transactions.id, transactions.budget_id, transactions.date, transactions.memo, transactions.amount FROM transactions
WHERE transactions.budget_id = $1
`
func (q *Queries) GetTransactionsForBudget(ctx context.Context, budgetID uuid.UUID) ([]Transaction, error) {
rows, err := q.db.QueryContext(ctx, getTransactionsForBudget, budgetID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Transaction
for rows.Next() {
var i Transaction
if err := rows.Scan(
&i.ID,
&i.BudgetID,
&i.Date,
&i.Memo,
&i.Amount,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}

View File

@ -1,27 +0,0 @@
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()
}

View File

@ -5,6 +5,8 @@ package postgres
import (
"context"
"github.com/google/uuid"
)
const linkBudgetToUser = `-- name: LinkBudgetToUser :one
@ -15,8 +17,8 @@ RETURNING user_id, budget_id
`
type LinkBudgetToUserParams struct {
UserID string
BudgetID string
UserID uuid.UUID
BudgetID uuid.UUID
}
func (q *Queries) LinkBudgetToUser(ctx context.Context, arg LinkBudgetToUserParams) (UserBudget, error) {

View File

@ -5,17 +5,19 @@ package postgres
import (
"context"
"github.com/google/uuid"
)
const createUser = `-- name: CreateUser :one
INSERT INTO users
(id, email, name, password)
VALUES ($1, $2, $3, $4)
RETURNING id, email, name, password
RETURNING email, name, password, id
`
type CreateUserParams struct {
ID string
ID uuid.UUID
Email string
Name string
Password string
@ -30,33 +32,33 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, e
)
var i User
err := row.Scan(
&i.ID,
&i.Email,
&i.Name,
&i.Password,
&i.ID,
)
return i, err
}
const getUser = `-- name: GetUser :one
SELECT id, email, name, password FROM users
SELECT email, name, password, id FROM users
WHERE id = $1
`
func (q *Queries) GetUser(ctx context.Context, id string) (User, error) {
func (q *Queries) GetUser(ctx context.Context, id uuid.UUID) (User, error) {
row := q.db.QueryRowContext(ctx, getUser, id)
var i User
err := row.Scan(
&i.ID,
&i.Email,
&i.Name,
&i.Password,
&i.ID,
)
return i, err
}
const getUserByUsername = `-- name: GetUserByUsername :one
SELECT id, email, name, password FROM users
SELECT email, name, password, id FROM users
WHERE email = $1
`
@ -64,10 +66,10 @@ func (q *Queries) GetUserByUsername(ctx context.Context, email string) (User, er
row := q.db.QueryRowContext(ctx, getUserByUsername, email)
var i User
err := row.Scan(
&i.ID,
&i.Email,
&i.Name,
&i.Password,
&i.ID,
)
return i, err
}