diff options
| author | Leonardo Bishop <me@leonardobishop.com> | 2025-01-17 13:21:24 +0000 |
|---|---|---|
| committer | Leonardo Bishop <me@leonardobishop.com> | 2025-01-17 13:21:24 +0000 |
| commit | c00b690bd6f600554a1404e692bd9e4373325d27 (patch) | |
| tree | 4488b625e1c24af52fced6f60ac1b3ddff1383bc /pkg/database | |
Initial commit
Diffstat (limited to 'pkg/database')
| -rw-r--r-- | pkg/database/database.go | 45 | ||||
| -rw-r--r-- | pkg/database/migrations/0001_initial.sql | 17 | ||||
| -rw-r--r-- | pkg/database/query/favourites.sql | 19 | ||||
| -rw-r--r-- | pkg/database/query/users.sql | 23 | ||||
| -rw-r--r-- | pkg/database/sqlc/db.go | 32 | ||||
| -rw-r--r-- | pkg/database/sqlc/favourites.sql.go | 134 | ||||
| -rw-r--r-- | pkg/database/sqlc/models.go | 22 | ||||
| -rw-r--r-- | pkg/database/sqlc/users.sql.go | 90 |
8 files changed, 382 insertions, 0 deletions
diff --git a/pkg/database/database.go b/pkg/database/database.go new file mode 100644 index 0000000..5570c95 --- /dev/null +++ b/pkg/database/database.go @@ -0,0 +1,45 @@ +package database + +import ( + "context" + "embed" + "fmt" + + "github.com/jackc/pgx/v5/pgxpool" + "github.com/jackc/pgx/v5/stdlib" + "github.com/pressly/goose/v3" +) + +//go:embed migrations/*.sql +var embedMigrations embed.FS + +func Connect(connString string) (*pgxpool.Pool, error) { + ctx := context.Background() + + config, err := pgxpool.ParseConfig(connString) + if err != nil { + return nil, err + } + + pool, err := pgxpool.NewWithConfig(ctx, config) + if err != nil { + return nil, err + } + + return pool, nil +} + +func Migrate(pool *pgxpool.Pool) error { + goose.SetBaseFS(embedMigrations) + + if err := goose.SetDialect("postgres"); err != nil { + return fmt.Errorf("could not set dialect: %w", err) + } + + db := stdlib.OpenDBFromPool(pool) + if err := goose.Up(db, "migrations"); err != nil { + return fmt.Errorf("could not apply migrations: %w", err) + } + + return nil +} diff --git a/pkg/database/migrations/0001_initial.sql b/pkg/database/migrations/0001_initial.sql new file mode 100644 index 0000000..eea0a73 --- /dev/null +++ b/pkg/database/migrations/0001_initial.sql @@ -0,0 +1,17 @@ +-- +goose Up +CREATE TABLE users ( + id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + username varchar(20) UNIQUE NOT NULL, + password char(60) NOT NULL +); + +CREATE TABLE favourites ( + id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + user_id int NOT NULL, + event_guid uuid, + event_id int, + UNIQUE(user_id, event_guid, event_id), + CONSTRAINT chk_favourites CHECK (event_guid IS NOT NULL OR event_id IS NOT NULL), + FOREIGN KEY (user_id) REFERENCES users(id) +); + diff --git a/pkg/database/query/favourites.sql b/pkg/database/query/favourites.sql new file mode 100644 index 0000000..0661daa --- /dev/null +++ b/pkg/database/query/favourites.sql @@ -0,0 +1,19 @@ +-- name: GetFavouritesForUser :many +SELECT * FROM favourites +WHERE user_id = $1; + +-- name: CreateFavourite :one +INSERT INTO favourites ( + user_id, event_guid, event_id +) VALUES ( + $1, $2, $3 +) +RETURNING *; + +-- name: DeleteFavourite :exec +DELETE FROM favourites +WHERE id = $1; + +-- name: DeleteFavouriteByEventDetails :execrows +DELETE FROM favourites +WHERE (event_guid = $1 OR event_id = $2) AND user_id = $3;
\ No newline at end of file diff --git a/pkg/database/query/users.sql b/pkg/database/query/users.sql new file mode 100644 index 0000000..c70ebbb --- /dev/null +++ b/pkg/database/query/users.sql @@ -0,0 +1,23 @@ +-- name: GetUserByID :one +SELECT * FROM users +WHERE id = $1 LIMIT 1; + +-- name: GetUserByName :one +SELECT * FROM users +WHERE username = $1 LIMIT 1; + +-- name: ListUsers :many +SELECT * FROM users +ORDER BY username; + +-- name: CreateUser :one +INSERT INTO users ( + username, password +) VALUES ( + $1, $2 +) +RETURNING *; + +-- name: DeleteUser :exec +DELETE FROM users +WHERE id = $1; diff --git a/pkg/database/sqlc/db.go b/pkg/database/sqlc/db.go new file mode 100644 index 0000000..b931bc5 --- /dev/null +++ b/pkg/database/sqlc/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.27.0 + +package sqlc + +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, + } +} diff --git a/pkg/database/sqlc/favourites.sql.go b/pkg/database/sqlc/favourites.sql.go new file mode 100644 index 0000000..3bf7c06 --- /dev/null +++ b/pkg/database/sqlc/favourites.sql.go @@ -0,0 +1,134 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.27.0 +// source: favourites.sql + +package sqlc + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const createFavourite = `-- name: CreateFavourite :one +INSERT INTO favourites ( + user_id, event_guid, event_id +) VALUES ( + $1, $2, $3 +) +RETURNING id, user_id, event_guid, event_id +` + +type CreateFavouriteParams struct { + UserID int32 `json:"user_id"` + EventGuid pgtype.UUID `json:"event_guid"` + EventID pgtype.Int4 `json:"event_id"` +} + +func (q *Queries) CreateFavourite(ctx context.Context, arg CreateFavouriteParams) (Favourite, error) { + row := q.db.QueryRow(ctx, createFavourite, arg.UserID, arg.EventGuid, arg.EventID) + var i Favourite + err := row.Scan( + &i.ID, + &i.UserID, + &i.EventGuid, + &i.EventID, + ) + return i, err +} + +const deleteFavourite = `-- name: DeleteFavourite :exec +DELETE FROM favourites +WHERE id = $1 +` + +func (q *Queries) DeleteFavourite(ctx context.Context, id int32) error { + _, err := q.db.Exec(ctx, deleteFavourite, id) + return err +} + +const deleteFavouriteByEventDetails = `-- name: DeleteFavouriteByEventDetails :execrows +DELETE FROM favourites +WHERE (event_guid = $1 OR event_id = $2) AND user_id = $3 +` + +type DeleteFavouriteByEventDetailsParams struct { + EventGuid pgtype.UUID `json:"event_guid"` + EventID pgtype.Int4 `json:"event_id"` + UserID int32 `json:"user_id"` +} + +func (q *Queries) DeleteFavouriteByEventDetails(ctx context.Context, arg DeleteFavouriteByEventDetailsParams) (int64, error) { + result, err := q.db.Exec(ctx, deleteFavouriteByEventDetails, arg.EventGuid, arg.EventID, arg.UserID) + if err != nil { + return 0, err + } + return result.RowsAffected(), nil +} + +const deleteFavouriteByEventGuid = `-- name: DeleteFavouriteByEventGuid :execrows +DELETE FROM favourites +WHERE event_guid = $1 AND user_id = $2 +` + +type DeleteFavouriteByEventGuidParams struct { + EventGuid pgtype.UUID `json:"event_guid"` + UserID int32 `json:"user_id"` +} + +func (q *Queries) DeleteFavouriteByEventGuid(ctx context.Context, arg DeleteFavouriteByEventGuidParams) (int64, error) { + result, err := q.db.Exec(ctx, deleteFavouriteByEventGuid, arg.EventGuid, arg.UserID) + if err != nil { + return 0, err + } + return result.RowsAffected(), nil +} + +const deleteFavouriteByEventId = `-- name: DeleteFavouriteByEventId :execrows +DELETE FROM favourites +WHERE event_id = $1 AND user_id = $2 +` + +type DeleteFavouriteByEventIdParams struct { + EventID pgtype.Int4 `json:"event_id"` + UserID int32 `json:"user_id"` +} + +func (q *Queries) DeleteFavouriteByEventId(ctx context.Context, arg DeleteFavouriteByEventIdParams) (int64, error) { + result, err := q.db.Exec(ctx, deleteFavouriteByEventId, arg.EventID, arg.UserID) + if err != nil { + return 0, err + } + return result.RowsAffected(), nil +} + +const getFavouritesForUser = `-- name: GetFavouritesForUser :many +SELECT id, user_id, event_guid, event_id FROM favourites +WHERE user_id = $1 +` + +func (q *Queries) GetFavouritesForUser(ctx context.Context, userID int32) ([]Favourite, error) { + rows, err := q.db.Query(ctx, getFavouritesForUser, userID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Favourite + for rows.Next() { + var i Favourite + if err := rows.Scan( + &i.ID, + &i.UserID, + &i.EventGuid, + &i.EventID, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/pkg/database/sqlc/models.go b/pkg/database/sqlc/models.go new file mode 100644 index 0000000..09208aa --- /dev/null +++ b/pkg/database/sqlc/models.go @@ -0,0 +1,22 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.27.0 + +package sqlc + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +type Favourite struct { + ID int32 `json:"id"` + UserID int32 `json:"user_id"` + EventGuid pgtype.UUID `json:"event_guid"` + EventID pgtype.Int4 `json:"event_id"` +} + +type User struct { + ID int32 `json:"id"` + Username string `json:"username"` + Password string `json:"password"` +} diff --git a/pkg/database/sqlc/users.sql.go b/pkg/database/sqlc/users.sql.go new file mode 100644 index 0000000..dfd2c2f --- /dev/null +++ b/pkg/database/sqlc/users.sql.go @@ -0,0 +1,90 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.27.0 +// source: users.sql + +package sqlc + +import ( + "context" +) + +const createUser = `-- name: CreateUser :one +INSERT INTO users ( + username, password +) VALUES ( + $1, $2 +) +RETURNING id, username, password +` + +type CreateUserParams struct { + Username string `json:"username"` + Password string `json:"password"` +} + +func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error) { + row := q.db.QueryRow(ctx, createUser, arg.Username, arg.Password) + var i User + err := row.Scan(&i.ID, &i.Username, &i.Password) + return i, err +} + +const deleteUser = `-- name: DeleteUser :exec +DELETE FROM users +WHERE id = $1 +` + +func (q *Queries) DeleteUser(ctx context.Context, id int32) error { + _, err := q.db.Exec(ctx, deleteUser, id) + return err +} + +const getUserByID = `-- name: GetUserByID :one +SELECT id, username, password FROM users +WHERE id = $1 LIMIT 1 +` + +func (q *Queries) GetUserByID(ctx context.Context, id int32) (User, error) { + row := q.db.QueryRow(ctx, getUserByID, id) + var i User + err := row.Scan(&i.ID, &i.Username, &i.Password) + return i, err +} + +const getUserByName = `-- name: GetUserByName :one +SELECT id, username, password FROM users +WHERE username = $1 LIMIT 1 +` + +func (q *Queries) GetUserByName(ctx context.Context, username string) (User, error) { + row := q.db.QueryRow(ctx, getUserByName, username) + var i User + err := row.Scan(&i.ID, &i.Username, &i.Password) + return i, err +} + +const listUsers = `-- name: ListUsers :many +SELECT id, username, password FROM users +ORDER BY username +` + +func (q *Queries) ListUsers(ctx context.Context) ([]User, error) { + rows, err := q.db.Query(ctx, listUsers) + if err != nil { + return nil, err + } + defer rows.Close() + var items []User + for rows.Next() { + var i User + if err := rows.Scan(&i.ID, &i.Username, &i.Password); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} |
