refact!: project structure
This commit is contained in:
parent
fd0ca4411b
commit
db53ae04e3
26 changed files with 971 additions and 6395 deletions
32
sql/db.go
Normal file
32
sql/db.go
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.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,
|
||||
}
|
||||
}
|
||||
15
sql/migrations/000001_init.down.sql
Normal file
15
sql/migrations/000001_init.down.sql
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
DROP TABLE IF EXISTS signals;
|
||||
DROP TABLE IF EXISTS title_tags;
|
||||
DROP TABLE IF EXISTS usertitles;
|
||||
DROP TABLE IF EXISTS reviews;
|
||||
DROP TABLE IF EXISTS titles;
|
||||
DROP TABLE IF EXISTS studios;
|
||||
DROP TABLE IF EXISTS users;
|
||||
DROP TABLE IF EXISTS images;
|
||||
DROP TABLE IF EXISTS tags;
|
||||
DROP TABLE IF EXISTS providers;
|
||||
|
||||
DROP TYPE IF EXISTS release_season_t;
|
||||
DROP TYPE IF EXISTS title_status_t;
|
||||
DROP TYPE IF EXISTS storage_type_t;
|
||||
DROP TYPE IF EXISTS usertitle_status_t;
|
||||
99
sql/migrations/000001_init.up.sql
Normal file
99
sql/migrations/000001_init.up.sql
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
-- TODO:
|
||||
-- title table triggers
|
||||
-- maybe jsonb constraints
|
||||
-- actions (delete)
|
||||
CREATE TYPE usertitle_status_t AS ENUM ('finished', 'planned', 'dropped', 'in-progress');
|
||||
CREATE TYPE storage_type_t AS ENUM ('local', 's3');
|
||||
CREATE TYPE title_status_t AS ENUM ('finished', 'ongoing', 'planned');
|
||||
CREATE TYPE release_season_t AS ENUM ('winter', 'spring', 'summer', 'fall');
|
||||
|
||||
CREATE TABLE providers (
|
||||
provider_id serial PRIMARY KEY,
|
||||
provider_name varchar(64) NOT NULL
|
||||
-- token
|
||||
);
|
||||
|
||||
CREATE TABLE tags (
|
||||
tag_id serial PRIMARY KEY,
|
||||
tag_names jsonb NOT NULL --mb constraints
|
||||
);
|
||||
|
||||
|
||||
-- clean unused images
|
||||
CREATE TABLE images (
|
||||
image_id serial PRIMARY KEY,
|
||||
storage_type storage_type_t NOT NULL,
|
||||
image_path varchar(256) UNIQUE NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE users (
|
||||
user_id serial PRIMARY KEY,
|
||||
avatar_id int REFERENCES images (image_id),
|
||||
passhash text NOT NULL,
|
||||
mail varchar(64) CHECK (mail ~ '[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+'),
|
||||
nickname varchar(16) NOT NULL CHECK (nickname ~ '^[a-zA-Z0-9_-]+$'),
|
||||
disp_name varchar(32),
|
||||
user_desc varchar(512),
|
||||
-- timestamp tl dr, also add access ts
|
||||
creation_date timestamp NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE studios (
|
||||
studio_id serial PRIMARY KEY,
|
||||
studio_name varchar(64) UNIQUE,
|
||||
illust_id int REFERENCES images (image_id),
|
||||
studio_desc text
|
||||
);
|
||||
|
||||
CREATE TABLE titles (
|
||||
title_id serial PRIMARY KEY,
|
||||
title_names jsonb NOT NULL,
|
||||
studio_id int NOT NULL REFERENCES studios,
|
||||
poster_id int REFERENCES images (image_id),
|
||||
--signal_ids int[] NOT NULL,
|
||||
title_status title_status_t NOT NULL,
|
||||
rating float CHECK (rating > 0 AND rating <= 10), --by trigger
|
||||
rating_count int CHECK (rating_count >= 0), --by trigger
|
||||
release_year int CHECK (release_year >= 1900),
|
||||
release_season release_season_t,
|
||||
season int CHECK (season >= 0),
|
||||
episodes_aired int CHECK (episodes_aired >= 0),
|
||||
episodes_all int CHECK (episodes_all >= 0),
|
||||
episodes_len jsonb,
|
||||
CHECK ((episodes_aired IS NULL AND episodes_all IS NULL)
|
||||
OR (episodes_aired IS NOT NULL AND episodes_all IS NOT NULL
|
||||
AND episodes_aired <= episodes_all))
|
||||
);
|
||||
|
||||
CREATE TABLE reviews (
|
||||
review_id serial PRIMARY KEY, --???
|
||||
user_id int NOT NULL REFERENCES users,
|
||||
title_id int NOT NULL REFERENCES titles,
|
||||
--image_ids int[], move somewhere
|
||||
review_text text NOT NULL,
|
||||
creation_date timestamp NOT NULL
|
||||
-- constrai (title, user)
|
||||
);
|
||||
|
||||
CREATE TABLE usertitles (
|
||||
usertitle_id serial PRIMARY KEY, -- bigserial, replace by (,)
|
||||
user_id int NOT NULL REFERENCES users,
|
||||
title_id int NOT NULL REFERENCES titles,
|
||||
status usertitle_status_t NOT NULL,
|
||||
rate int CHECK (rate > 0 AND rate <= 10),
|
||||
review_id int REFERENCES reviews
|
||||
);
|
||||
|
||||
CREATE TABLE title_tags (
|
||||
PRIMARY KEY (title_id, tag_id),
|
||||
title_id int NOT NULL REFERENCES titles,
|
||||
tag_id int NOT NULL REFERENCES tags
|
||||
);
|
||||
|
||||
CREATE TABLE signals (
|
||||
signal_id serial PRIMARY KEY,
|
||||
-- title_id
|
||||
raw_data jsonb NOT NULL,
|
||||
provider_id int NOT NULL REFERENCES providers,
|
||||
dirty bool NOT NULL
|
||||
);
|
||||
264
sql/models.go
Normal file
264
sql/models.go
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type ReleaseSeasonT string
|
||||
|
||||
const (
|
||||
ReleaseSeasonTWinter ReleaseSeasonT = "winter"
|
||||
ReleaseSeasonTSpring ReleaseSeasonT = "spring"
|
||||
ReleaseSeasonTSummer ReleaseSeasonT = "summer"
|
||||
ReleaseSeasonTFall ReleaseSeasonT = "fall"
|
||||
)
|
||||
|
||||
func (e *ReleaseSeasonT) Scan(src interface{}) error {
|
||||
switch s := src.(type) {
|
||||
case []byte:
|
||||
*e = ReleaseSeasonT(s)
|
||||
case string:
|
||||
*e = ReleaseSeasonT(s)
|
||||
default:
|
||||
return fmt.Errorf("unsupported scan type for ReleaseSeasonT: %T", src)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NullReleaseSeasonT struct {
|
||||
ReleaseSeasonT ReleaseSeasonT `json:"release_season_t"`
|
||||
Valid bool `json:"valid"` // Valid is true if ReleaseSeasonT is not NULL
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (ns *NullReleaseSeasonT) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
ns.ReleaseSeasonT, ns.Valid = "", false
|
||||
return nil
|
||||
}
|
||||
ns.Valid = true
|
||||
return ns.ReleaseSeasonT.Scan(value)
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (ns NullReleaseSeasonT) Value() (driver.Value, error) {
|
||||
if !ns.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return string(ns.ReleaseSeasonT), nil
|
||||
}
|
||||
|
||||
type StorageTypeT string
|
||||
|
||||
const (
|
||||
StorageTypeTLocal StorageTypeT = "local"
|
||||
StorageTypeTS3 StorageTypeT = "s3"
|
||||
)
|
||||
|
||||
func (e *StorageTypeT) Scan(src interface{}) error {
|
||||
switch s := src.(type) {
|
||||
case []byte:
|
||||
*e = StorageTypeT(s)
|
||||
case string:
|
||||
*e = StorageTypeT(s)
|
||||
default:
|
||||
return fmt.Errorf("unsupported scan type for StorageTypeT: %T", src)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NullStorageTypeT struct {
|
||||
StorageTypeT StorageTypeT `json:"storage_type_t"`
|
||||
Valid bool `json:"valid"` // Valid is true if StorageTypeT is not NULL
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (ns *NullStorageTypeT) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
ns.StorageTypeT, ns.Valid = "", false
|
||||
return nil
|
||||
}
|
||||
ns.Valid = true
|
||||
return ns.StorageTypeT.Scan(value)
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (ns NullStorageTypeT) Value() (driver.Value, error) {
|
||||
if !ns.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return string(ns.StorageTypeT), nil
|
||||
}
|
||||
|
||||
type TitleStatusT string
|
||||
|
||||
const (
|
||||
TitleStatusTFinished TitleStatusT = "finished"
|
||||
TitleStatusTOngoing TitleStatusT = "ongoing"
|
||||
TitleStatusTPlanned TitleStatusT = "planned"
|
||||
)
|
||||
|
||||
func (e *TitleStatusT) Scan(src interface{}) error {
|
||||
switch s := src.(type) {
|
||||
case []byte:
|
||||
*e = TitleStatusT(s)
|
||||
case string:
|
||||
*e = TitleStatusT(s)
|
||||
default:
|
||||
return fmt.Errorf("unsupported scan type for TitleStatusT: %T", src)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NullTitleStatusT struct {
|
||||
TitleStatusT TitleStatusT `json:"title_status_t"`
|
||||
Valid bool `json:"valid"` // Valid is true if TitleStatusT is not NULL
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (ns *NullTitleStatusT) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
ns.TitleStatusT, ns.Valid = "", false
|
||||
return nil
|
||||
}
|
||||
ns.Valid = true
|
||||
return ns.TitleStatusT.Scan(value)
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (ns NullTitleStatusT) Value() (driver.Value, error) {
|
||||
if !ns.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return string(ns.TitleStatusT), nil
|
||||
}
|
||||
|
||||
type UsertitleStatusT string
|
||||
|
||||
const (
|
||||
UsertitleStatusTFinished UsertitleStatusT = "finished"
|
||||
UsertitleStatusTPlanned UsertitleStatusT = "planned"
|
||||
UsertitleStatusTDropped UsertitleStatusT = "dropped"
|
||||
UsertitleStatusTInProgress UsertitleStatusT = "in-progress"
|
||||
)
|
||||
|
||||
func (e *UsertitleStatusT) Scan(src interface{}) error {
|
||||
switch s := src.(type) {
|
||||
case []byte:
|
||||
*e = UsertitleStatusT(s)
|
||||
case string:
|
||||
*e = UsertitleStatusT(s)
|
||||
default:
|
||||
return fmt.Errorf("unsupported scan type for UsertitleStatusT: %T", src)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NullUsertitleStatusT struct {
|
||||
UsertitleStatusT UsertitleStatusT `json:"usertitle_status_t"`
|
||||
Valid bool `json:"valid"` // Valid is true if UsertitleStatusT is not NULL
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (ns *NullUsertitleStatusT) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
ns.UsertitleStatusT, ns.Valid = "", false
|
||||
return nil
|
||||
}
|
||||
ns.Valid = true
|
||||
return ns.UsertitleStatusT.Scan(value)
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (ns NullUsertitleStatusT) Value() (driver.Value, error) {
|
||||
if !ns.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return string(ns.UsertitleStatusT), nil
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
ImageID int32 `json:"image_id"`
|
||||
StorageType StorageTypeT `json:"storage_type"`
|
||||
ImagePath string `json:"image_path"`
|
||||
}
|
||||
|
||||
type Provider struct {
|
||||
ProviderID int32 `json:"provider_id"`
|
||||
ProviderName string `json:"provider_name"`
|
||||
}
|
||||
|
||||
type Review struct {
|
||||
ReviewID int32 `json:"review_id"`
|
||||
UserID int32 `json:"user_id"`
|
||||
TitleID int32 `json:"title_id"`
|
||||
ReviewText string `json:"review_text"`
|
||||
CreationDate pgtype.Timestamp `json:"creation_date"`
|
||||
}
|
||||
|
||||
type Signal struct {
|
||||
SignalID int32 `json:"signal_id"`
|
||||
RawData []byte `json:"raw_data"`
|
||||
ProviderID int32 `json:"provider_id"`
|
||||
Dirty bool `json:"dirty"`
|
||||
}
|
||||
|
||||
type Studio struct {
|
||||
StudioID int32 `json:"studio_id"`
|
||||
StudioName *string `json:"studio_name"`
|
||||
IllustID *int32 `json:"illust_id"`
|
||||
StudioDesc *string `json:"studio_desc"`
|
||||
}
|
||||
|
||||
type Tag struct {
|
||||
TagID int32 `json:"tag_id"`
|
||||
TagNames []byte `json:"tag_names"`
|
||||
}
|
||||
|
||||
type Title struct {
|
||||
TitleID int32 `json:"title_id"`
|
||||
TitleNames []byte `json:"title_names"`
|
||||
StudioID int32 `json:"studio_id"`
|
||||
PosterID *int32 `json:"poster_id"`
|
||||
TitleStatus TitleStatusT `json:"title_status"`
|
||||
Rating *float64 `json:"rating"`
|
||||
RatingCount *int32 `json:"rating_count"`
|
||||
ReleaseYear *int32 `json:"release_year"`
|
||||
ReleaseSeason NullReleaseSeasonT `json:"release_season"`
|
||||
Season *int32 `json:"season"`
|
||||
EpisodesAired *int32 `json:"episodes_aired"`
|
||||
EpisodesAll *int32 `json:"episodes_all"`
|
||||
EpisodesLen []byte `json:"episodes_len"`
|
||||
}
|
||||
|
||||
type TitleTag struct {
|
||||
TitleID int32 `json:"title_id"`
|
||||
TagID int32 `json:"tag_id"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
UserID int32 `json:"user_id"`
|
||||
AvatarID *int32 `json:"avatar_id"`
|
||||
Passhash string `json:"passhash"`
|
||||
Mail *string `json:"mail"`
|
||||
Nickname string `json:"nickname"`
|
||||
DispName *string `json:"disp_name"`
|
||||
UserDesc *string `json:"user_desc"`
|
||||
CreationDate pgtype.Timestamp `json:"creation_date"`
|
||||
}
|
||||
|
||||
type Usertitle struct {
|
||||
UsertitleID int32 `json:"usertitle_id"`
|
||||
UserID int32 `json:"user_id"`
|
||||
TitleID int32 `json:"title_id"`
|
||||
Status UsertitleStatusT `json:"status"`
|
||||
Rate *int32 `json:"rate"`
|
||||
ReviewID *int32 `json:"review_id"`
|
||||
}
|
||||
23
sql/queries.sql.go
Normal file
23
sql/queries.sql.go
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: queries.sql
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const getImageByID = `-- name: GetImageByID :one
|
||||
SELECT image_id, storage_type, image_path
|
||||
FROM images
|
||||
WHERE image_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetImageByID(ctx context.Context, imageID int32) (Image, error) {
|
||||
row := q.db.QueryRow(ctx, getImageByID, imageID)
|
||||
var i Image
|
||||
err := row.Scan(&i.ImageID, &i.StorageType, &i.ImagePath)
|
||||
return i, err
|
||||
}
|
||||
14
sql/sqlc.yaml
Normal file
14
sql/sqlc.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
version: "2"
|
||||
sql:
|
||||
- engine: "postgresql"
|
||||
queries:
|
||||
- "../modules/backend/queries.sql"
|
||||
schema: "migrations"
|
||||
gen:
|
||||
go:
|
||||
package: "sqlc"
|
||||
out: "."
|
||||
sql_package: "pgx/v5"
|
||||
sql_driver: "github.com/jackc/pgx/v5"
|
||||
emit_json_tags: true
|
||||
emit_pointers_for_null_types: true
|
||||
Loading…
Add table
Add a link
Reference in a new issue