Use uuid.UUID everywhere and have postgres generate ids
This commit is contained in:
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
9
postgres/queries/transactions.sql
Normal file
9
postgres/queries/transactions.sql
Normal 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;
|
@ -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
|
||||
}
|
||||
|
11
postgres/schema/0004_transactions.sql
Normal file
11
postgres/schema/0004_transactions.sql
Normal 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;
|
23
postgres/schema/0005_migrate-to-uuid.sql
Normal file
23
postgres/schema/0005_migrate-to-uuid.sql
Normal 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;
|
78
postgres/transactions.sql.go
Normal file
78
postgres/transactions.sql.go
Normal 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
|
||||
}
|
@ -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()
|
||||
}
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user