This commit is contained in:
@@ -65,7 +65,7 @@ func (d *DB) Characters() repositories.CharacterRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *DB) Tags() repositories.TagRepository {
|
func (d *DB) Tags() repositories.TagRepository {
|
||||||
panic("implement me")
|
return &tagRepository{db: d.db}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DB) Logs() repositories.LogRepository {
|
func (d *DB) Logs() repositories.LogRepository {
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
-- +goose Up
|
||||||
|
-- +goose StatementBegin
|
||||||
|
CREATE TABLE common_tag (
|
||||||
|
tag TEXT NOT NULL,
|
||||||
|
target_kind TEXT NOT NULL,
|
||||||
|
target_id TEXT NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (tag, target_kind, target_id)
|
||||||
|
);
|
||||||
|
-- +goose StatementEnd
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
-- +goose StatementBegin
|
||||||
|
DROP TABLE common_tag;
|
||||||
|
-- +goose StatementEnd
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
-- +goose Up
|
||||||
|
-- +goose StatementBegin
|
||||||
|
CREATE INDEX common_tag_index_target ON common_tag (target_kind, target_id);
|
||||||
|
-- +goose StatementEnd
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
-- +goose StatementBegin
|
||||||
|
DROP INDEX IF EXISTS common_tag_index_target;
|
||||||
|
-- +goose StatementEnd
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
-- +goose Up
|
||||||
|
-- +goose StatementBegin
|
||||||
|
CREATE TABLE story (
|
||||||
|
id TEXT NOT NULL PRIMARY KEY,
|
||||||
|
author TEXT NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
category TEXT NOT NULL,
|
||||||
|
open BOOLEAN NOT NULL,
|
||||||
|
listed BOOLEAN NOT NULL,
|
||||||
|
sort_by_fictional_date BOOLEAN NOT NULL,
|
||||||
|
created_date TIMESTAMP NOT NULL,
|
||||||
|
fictional_date TIMESTAMP NOT NULL,
|
||||||
|
updated_date TIMESTAMP NOT NULL
|
||||||
|
);
|
||||||
|
-- +goose StatementEnd
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
-- +goose StatementBegin
|
||||||
|
DROP TABLE story;
|
||||||
|
-- +goose StatementEnd
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
-- +goose Up
|
||||||
|
-- +goose StatementBegin
|
||||||
|
CREATE INDEX story_index_author ON story (author);
|
||||||
|
-- +goose StatementEnd
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
-- +goose StatementBegin
|
||||||
|
DROP INDEX IF EXISTS story_index_author
|
||||||
|
-- +goose StatementEnd
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
-- +goose Up
|
||||||
|
-- +goose StatementBegin
|
||||||
|
CREATE INDEX story_index_fictional_date ON story (fictional_date);
|
||||||
|
-- +goose StatementEnd
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
-- +goose StatementBegin
|
||||||
|
DROP INDEX IF EXISTS story_index_fictional_date
|
||||||
|
-- +goose StatementEnd
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
-- +goose Up
|
||||||
|
-- +goose StatementBegin
|
||||||
|
CREATE INDEX story_index_created_date ON story (created_date);
|
||||||
|
-- +goose StatementEnd
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
-- +goose StatementBegin
|
||||||
|
DROP INDEX IF EXISTS story_index_created_date
|
||||||
|
-- +goose StatementEnd
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
-- +goose Up
|
||||||
|
-- +goose StatementBegin
|
||||||
|
CREATE INDEX story_index_updated_date ON story (updated_date);
|
||||||
|
-- +goose StatementEnd
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
-- +goose StatementBegin
|
||||||
|
DROP INDEX IF EXISTS story_index_updated_date
|
||||||
|
-- +goose StatementEnd
|
||||||
@@ -8,6 +8,12 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type CommonTag struct {
|
||||||
|
Tag string `json:"tag"`
|
||||||
|
TargetKind string `json:"target_kind"`
|
||||||
|
TargetID string `json:"target_id"`
|
||||||
|
}
|
||||||
|
|
||||||
type CoreCounter struct {
|
type CoreCounter struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Value sql.NullInt32 `json:"value"`
|
Value sql.NullInt32 `json:"value"`
|
||||||
@@ -41,3 +47,16 @@ type DataCharacter struct {
|
|||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
TsVector interface{} `json:"ts_vector"`
|
TsVector interface{} `json:"ts_vector"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Story struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Author string `json:"author"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Category string `json:"category"`
|
||||||
|
Open bool `json:"open"`
|
||||||
|
Listed bool `json:"listed"`
|
||||||
|
SortByFictionalDate bool `json:"sort_by_fictional_date"`
|
||||||
|
CreatedDate time.Time `json:"created_date"`
|
||||||
|
FictionalDate time.Time `json:"fictional_date"`
|
||||||
|
UpdatedDate time.Time `json:"updated_date"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
|
// source: stories.sql
|
||||||
|
|
||||||
|
package psqlcore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/lib/pq"
|
||||||
|
)
|
||||||
|
|
||||||
|
const selectStories = `-- name: SelectStories :many
|
||||||
|
SELECT id, author, name, category, open, listed, sort_by_fictional_date, created_date, fictional_date, updated_date FROM story
|
||||||
|
WHERE ($1::bool = false OR id = ANY($2::text[]))
|
||||||
|
AND ($3::bool = false OR name = $4::text)
|
||||||
|
AND ($5::bool = false OR fictional_date >= $6::timestamp)
|
||||||
|
AND ($7::bool = false OR fictional_date <= $8::timestamp)
|
||||||
|
AND ($9::bool = false OR category = $10::text)
|
||||||
|
AND ($11::bool = false OR open = $12::bool)
|
||||||
|
AND ($13::bool = false OR unlisted = $14::bool)
|
||||||
|
LIMIT $15::int
|
||||||
|
`
|
||||||
|
|
||||||
|
type SelectStoriesParams struct {
|
||||||
|
FilterID bool `json:"filter_id"`
|
||||||
|
Ids []string `json:"ids"`
|
||||||
|
FilterAuthor bool `json:"filter_author"`
|
||||||
|
Author string `json:"author"`
|
||||||
|
FilterEarlistFictionalDate bool `json:"filter_earlist_fictional_date"`
|
||||||
|
EarliestFictionalDate time.Time `json:"earliest_fictional_date"`
|
||||||
|
FilterLastestFictionalDate bool `json:"filter_lastest_fictional_date"`
|
||||||
|
LatestFictionalDate time.Time `json:"latest_fictional_date"`
|
||||||
|
FilterCategory bool `json:"filter_category"`
|
||||||
|
Category string `json:"category"`
|
||||||
|
FilterOpen bool `json:"filter_open"`
|
||||||
|
Open bool `json:"open"`
|
||||||
|
FilterUnlisted bool `json:"filter_unlisted"`
|
||||||
|
Unlisted bool `json:"unlisted"`
|
||||||
|
LimitSize int32 `json:"limit_size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) SelectStories(ctx context.Context, arg SelectStoriesParams) ([]Story, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, selectStories,
|
||||||
|
arg.FilterID,
|
||||||
|
pq.Array(arg.Ids),
|
||||||
|
arg.FilterAuthor,
|
||||||
|
arg.Author,
|
||||||
|
arg.FilterEarlistFictionalDate,
|
||||||
|
arg.EarliestFictionalDate,
|
||||||
|
arg.FilterLastestFictionalDate,
|
||||||
|
arg.LatestFictionalDate,
|
||||||
|
arg.FilterCategory,
|
||||||
|
arg.Category,
|
||||||
|
arg.FilterOpen,
|
||||||
|
arg.Open,
|
||||||
|
arg.FilterUnlisted,
|
||||||
|
arg.Unlisted,
|
||||||
|
arg.LimitSize,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
items := []Story{}
|
||||||
|
for rows.Next() {
|
||||||
|
var i Story
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.Author,
|
||||||
|
&i.Name,
|
||||||
|
&i.Category,
|
||||||
|
&i.Open,
|
||||||
|
&i.Listed,
|
||||||
|
&i.SortByFictionalDate,
|
||||||
|
&i.CreatedDate,
|
||||||
|
&i.FictionalDate,
|
||||||
|
&i.UpdatedDate,
|
||||||
|
); 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
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectStory = `-- name: SelectStory :one
|
||||||
|
SELECT id, author, name, category, open, listed, sort_by_fictional_date, created_date, fictional_date, updated_date FROM story WHERE id = $1 LIMIT 1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) SelectStory(ctx context.Context, id string) (Story, error) {
|
||||||
|
row := q.db.QueryRowContext(ctx, selectStory, id)
|
||||||
|
var i Story
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.Author,
|
||||||
|
&i.Name,
|
||||||
|
&i.Category,
|
||||||
|
&i.Open,
|
||||||
|
&i.Listed,
|
||||||
|
&i.SortByFictionalDate,
|
||||||
|
&i.CreatedDate,
|
||||||
|
&i.FictionalDate,
|
||||||
|
&i.UpdatedDate,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
|
// source: tags.sql
|
||||||
|
|
||||||
|
package psqlcore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/lib/pq"
|
||||||
|
)
|
||||||
|
|
||||||
|
const clearTag = `-- name: ClearTag :exec
|
||||||
|
DELETE FROM common_tag
|
||||||
|
WHERE tag=$1::TEXT
|
||||||
|
AND target_kind=$2::TEXT
|
||||||
|
AND target_id=$3::TEXT
|
||||||
|
`
|
||||||
|
|
||||||
|
type ClearTagParams struct {
|
||||||
|
Tag string `json:"tag"`
|
||||||
|
TargetKind string `json:"target_kind"`
|
||||||
|
TargetID string `json:"target_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) ClearTag(ctx context.Context, arg ClearTagParams) error {
|
||||||
|
_, err := q.db.ExecContext(ctx, clearTag, arg.Tag, arg.TargetKind, arg.TargetID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearTagsByTarget = `-- name: ClearTagsByTarget :exec
|
||||||
|
DELETE FROM common_tag
|
||||||
|
WHERE target_kind=$1::TEXT
|
||||||
|
AND target_id=$2::TEXT
|
||||||
|
`
|
||||||
|
|
||||||
|
type ClearTagsByTargetParams struct {
|
||||||
|
TargetKind string `json:"target_kind"`
|
||||||
|
TargetID string `json:"target_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) ClearTagsByTarget(ctx context.Context, arg ClearTagsByTargetParams) error {
|
||||||
|
_, err := q.db.ExecContext(ctx, clearTagsByTarget, arg.TargetKind, arg.TargetID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectDistinctTags = `-- name: SelectDistinctTags :many
|
||||||
|
SELECT DISTINCT tag FROM common_tag
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) SelectDistinctTags(ctx context.Context) ([]string, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, selectDistinctTags)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
items := []string{}
|
||||||
|
for rows.Next() {
|
||||||
|
var tag string
|
||||||
|
if err := rows.Scan(&tag); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, tag)
|
||||||
|
}
|
||||||
|
if err := rows.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectDistinctTagsByKind = `-- name: SelectDistinctTagsByKind :many
|
||||||
|
SELECT DISTINCT tag FROM common_tag WHERE tag LIKE '$1::text%'
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) SelectDistinctTagsByKind(ctx context.Context) ([]string, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, selectDistinctTagsByKind)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
items := []string{}
|
||||||
|
for rows.Next() {
|
||||||
|
var tag string
|
||||||
|
if err := rows.Scan(&tag); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, tag)
|
||||||
|
}
|
||||||
|
if err := rows.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectTagsByTag = `-- name: SelectTagsByTag :many
|
||||||
|
SELECT tag, target_kind, target_id FROM common_tag WHERE tag = $1::text
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) SelectTagsByTag(ctx context.Context, tagName string) ([]CommonTag, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, selectTagsByTag, tagName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
items := []CommonTag{}
|
||||||
|
for rows.Next() {
|
||||||
|
var i CommonTag
|
||||||
|
if err := rows.Scan(&i.Tag, &i.TargetKind, &i.TargetID); 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
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectTagsByTags = `-- name: SelectTagsByTags :many
|
||||||
|
SELECT tag, target_kind, target_id FROM common_tag WHERE tag = ANY($1::text[])
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) SelectTagsByTags(ctx context.Context, tagNames []string) ([]CommonTag, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, selectTagsByTags, pq.Array(tagNames))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
items := []CommonTag{}
|
||||||
|
for rows.Next() {
|
||||||
|
var i CommonTag
|
||||||
|
if err := rows.Scan(&i.Tag, &i.TargetKind, &i.TargetID); 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
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectTagsByTarget = `-- name: SelectTagsByTarget :many
|
||||||
|
SELECT tag, target_kind, target_id FROM common_tag WHERE target_kind = $1 AND target_id = $2::text
|
||||||
|
`
|
||||||
|
|
||||||
|
type SelectTagsByTargetParams struct {
|
||||||
|
TargetKind string `json:"target_kind"`
|
||||||
|
Column2 string `json:"column_2"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) SelectTagsByTarget(ctx context.Context, arg SelectTagsByTargetParams) ([]CommonTag, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, selectTagsByTarget, arg.TargetKind, arg.Column2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
items := []CommonTag{}
|
||||||
|
for rows.Next() {
|
||||||
|
var i CommonTag
|
||||||
|
if err := rows.Scan(&i.Tag, &i.TargetKind, &i.TargetID); 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
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectTagsByTargets = `-- name: SelectTagsByTargets :many
|
||||||
|
SELECT tag, target_kind, target_id FROM common_tag WHERE target_kind = $1 AND target_id = ANY($2::text[])
|
||||||
|
`
|
||||||
|
|
||||||
|
type SelectTagsByTargetsParams struct {
|
||||||
|
TargetKind string `json:"target_kind"`
|
||||||
|
Column2 []string `json:"column_2"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) SelectTagsByTargets(ctx context.Context, arg SelectTagsByTargetsParams) ([]CommonTag, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, selectTagsByTargets, arg.TargetKind, pq.Array(arg.Column2))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
items := []CommonTag{}
|
||||||
|
for rows.Next() {
|
||||||
|
var i CommonTag
|
||||||
|
if err := rows.Scan(&i.Tag, &i.TargetKind, &i.TargetID); 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
|
||||||
|
}
|
||||||
|
|
||||||
|
const setTag = `-- name: SetTag :exec
|
||||||
|
INSERT INTO common_tag (tag, target_kind, target_id)
|
||||||
|
VALUES (
|
||||||
|
$1::TEXT, $2::TEXT, $3::TEXT
|
||||||
|
)
|
||||||
|
ON CONFLICT DO NOTHING
|
||||||
|
`
|
||||||
|
|
||||||
|
type SetTagParams struct {
|
||||||
|
Tag string `json:"tag"`
|
||||||
|
TargetKind string `json:"target_kind"`
|
||||||
|
TargetID string `json:"target_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) SetTag(ctx context.Context, arg SetTagParams) error {
|
||||||
|
_, err := q.db.ExecContext(ctx, setTag, arg.Tag, arg.TargetKind, arg.TargetID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
-- name: SelectStory :one
|
||||||
|
SELECT * FROM story WHERE id = $1 LIMIT 1;
|
||||||
|
|
||||||
|
-- name: SelectStories :many
|
||||||
|
SELECT * FROM story
|
||||||
|
WHERE (sqlc.arg(filter_id)::bool = false OR id = ANY(sqlc.arg(ids)::text[]))
|
||||||
|
AND (sqlc.arg(filter_author)::bool = false OR name = sqlc.arg(author)::text)
|
||||||
|
AND (sqlc.arg(filter_earlist_fictional_date)::bool = false OR fictional_date >= sqlc.arg(earliest_fictional_date)::timestamp)
|
||||||
|
AND (sqlc.arg(filter_lastest_fictional_date)::bool = false OR fictional_date <= sqlc.arg(latest_fictional_date)::timestamp)
|
||||||
|
AND (sqlc.arg(filter_category)::bool = false OR category = sqlc.arg(category)::text)
|
||||||
|
AND (sqlc.arg(filter_open)::bool = false OR open = sqlc.arg(open)::bool)
|
||||||
|
AND (sqlc.arg(filter_unlisted)::bool = false OR unlisted = sqlc.arg(unlisted)::bool)
|
||||||
|
LIMIT sqlc.arg(limit_size)::int;
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
-- name: SetTag :exec
|
||||||
|
INSERT INTO common_tag (tag, target_kind, target_id)
|
||||||
|
VALUES (
|
||||||
|
sqlc.arg(tag)::TEXT, sqlc.arg(target_kind)::TEXT, sqlc.arg(target_id)::TEXT
|
||||||
|
)
|
||||||
|
ON CONFLICT DO NOTHING;
|
||||||
|
|
||||||
|
-- name: ClearTag :exec
|
||||||
|
DELETE FROM common_tag
|
||||||
|
WHERE tag=sqlc.arg(tag)::TEXT
|
||||||
|
AND target_kind=sqlc.arg(target_kind)::TEXT
|
||||||
|
AND target_id=sqlc.arg(target_id)::TEXT;
|
||||||
|
|
||||||
|
-- name: ClearTagsByTarget :exec
|
||||||
|
DELETE FROM common_tag
|
||||||
|
WHERE target_kind=sqlc.arg(target_kind)::TEXT
|
||||||
|
AND target_id=sqlc.arg(target_id)::TEXT;
|
||||||
|
|
||||||
|
-- name: SelectDistinctTags :many
|
||||||
|
SELECT DISTINCT tag FROM common_tag;
|
||||||
|
|
||||||
|
-- name: SelectDistinctTagsByKind :many
|
||||||
|
SELECT DISTINCT tag FROM common_tag WHERE tag LIKE '$1::text%';
|
||||||
|
|
||||||
|
-- name: SelectTagsByTag :many
|
||||||
|
SELECT * FROM common_tag WHERE tag = sqlc.arg(tag_name)::text;
|
||||||
|
|
||||||
|
-- name: SelectTagsByTags :many
|
||||||
|
SELECT * FROM common_tag WHERE tag = ANY(sqlc.arg(tag_names)::text[]);
|
||||||
|
|
||||||
|
-- name: SelectTagsByTarget :many
|
||||||
|
SELECT * FROM common_tag WHERE target_kind = $1 AND target_id = $2::text;
|
||||||
|
|
||||||
|
-- name: SelectTagsByTargets :many
|
||||||
|
SELECT * FROM common_tag WHERE target_kind = $1 AND target_id = ANY($2::text[]);
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
package postgres
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"git.aiterp.net/rpdata/api/database/postgres/psqlcore"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type storyRepository struct {
|
||||||
|
insertWithIDs bool
|
||||||
|
db *sql.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *storyRepository) Find(ctx context.Context, id string) (*models.Story, error) {
|
||||||
|
q := psqlcore.New(r.db)
|
||||||
|
story, err := q.SelectStory(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tags, err := q.SelectTagsByTarget(ctx, psqlcore.SelectTagsByTargetParams{
|
||||||
|
TargetKind: "Story",
|
||||||
|
TargetID: story.ID,
|
||||||
|
})
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.story(story, tags), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *storyRepository) List(ctx context.Context, filter models.StoryFilter) ([]*models.Story, error) {
|
||||||
|
q := psqlcore.New(r.db)
|
||||||
|
params := psqlcore.SelectStoriesParams{LimitSize: 100}
|
||||||
|
|
||||||
|
if len(filter.Tags) > 0 {
|
||||||
|
params.FilterID = true
|
||||||
|
if len(filter.Tags) == 1 {
|
||||||
|
tags, err := q.SelectTagsByKindName(ctx, psqlcore.SelectTagsByKindNameParams{
|
||||||
|
Kind: string(filter.Tags[0].Kind),
|
||||||
|
Name: filter.Tags[0].Name,
|
||||||
|
})
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tag := range tags {
|
||||||
|
params.Ids = append(params.Ids, tag.TargetID)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(params.Ids) == 0 {
|
||||||
|
return []*models.Story{}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if filter.Limit > 0 {
|
||||||
|
params.LimitSize = 1000000
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *storyRepository) Insert(ctx context.Context, story models.Story) (*models.Story, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *storyRepository) Update(ctx context.Context, story models.Story, update models.StoryUpdate) (*models.Story, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *storyRepository) AddTag(ctx context.Context, story models.Story, tag models.Tag) error {
|
||||||
|
return psqlcore.New(r.db).SetTag(ctx, psqlcore.SetTagParams{
|
||||||
|
Kind: string(tag.Kind),
|
||||||
|
Name: tag.Name,
|
||||||
|
TargetKind: "Story",
|
||||||
|
TargetID: story.ID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *storyRepository) RemoveTag(ctx context.Context, story models.Story, tag models.Tag) error {
|
||||||
|
return psqlcore.New(r.db).ClearTag(ctx, psqlcore.ClearTagParams{
|
||||||
|
Kind: string(tag.Kind),
|
||||||
|
Name: tag.Name,
|
||||||
|
TargetKind: "Story",
|
||||||
|
TargetID: story.ID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *storyRepository) Delete(ctx context.Context, story models.Story) error {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *storyRepository) story(story psqlcore.Story, tags []psqlcore.CommonTag) *models.Story {
|
||||||
|
tags2 := make([]models.Tag, 0, 8)
|
||||||
|
for _, tag := range tags {
|
||||||
|
if tag.TargetKind == "Story" && tag.TargetID == story.ID {
|
||||||
|
tags2 = append(tags2, models.Tag{
|
||||||
|
Kind: models.TagKind(tag.Kind),
|
||||||
|
Name: tag.Name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &models.Story{
|
||||||
|
ID: story.ID,
|
||||||
|
Author: story.Author,
|
||||||
|
Name: story.Name,
|
||||||
|
Category: models.StoryCategory(story.Category),
|
||||||
|
Open: story.Open,
|
||||||
|
Listed: story.Listed,
|
||||||
|
Tags: tags2,
|
||||||
|
CreatedDate: story.CreatedDate,
|
||||||
|
FictionalDate: story.FictionalDate,
|
||||||
|
UpdatedDate: story.UpdatedDate,
|
||||||
|
SortByFictionalDate: story.SortByFictionalDate,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *storyRepository) stories(stories []psqlcore.Story, tags []psqlcore.CommonTag) []*models.Story {
|
||||||
|
results := make([]*models.Story, 0, len(stories))
|
||||||
|
for _, story := range stories {
|
||||||
|
results = append(results, r.story(story, tags))
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package postgres
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"git.aiterp.net/rpdata/api/database/postgres/psqlcore"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tagRepository struct {
|
||||||
|
db *sql.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *tagRepository) Find(ctx context.Context, kind models.TagKind, name string) (*models.Tag, error) {
|
||||||
|
tag, err := psqlcore.New(r.db).SelectTagsByTag(ctx, fmt.Sprintf("%s:%s", kind, nmae))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &models.Tag{Kind: models.TagKind(tag.Kind), Name: tag.Name}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *tagRepository) List(ctx context.Context, filter models.TagFilter) ([]*models.Tag, error) {
|
||||||
|
var tags []string
|
||||||
|
var err error
|
||||||
|
if filter.Kind != nil {
|
||||||
|
tags, err = psqlcore.New(r.db).SelectDistinctTagsByKind(ctx, string(*filter.Kind))
|
||||||
|
} else {
|
||||||
|
tags, err = psqlcore.New(r.db).SelectDistinctTags(ctx)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return models.DecodeTagArray(tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func modelsTagsFromDataTags(tags []psqlcore.CommonTag) []*models.Tag {
|
||||||
|
results := make([]*models.Tag, len(tags))
|
||||||
|
for i, tag := range tags {
|
||||||
|
results[i] = &models.Tag{Kind: models.TagKind(tag.Kind), Name: tag.Name}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
+3
-2
@@ -55,9 +55,10 @@ func EncodeTagArray(arr []Tag) []string {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func DecodeTagArray(arr []string) ([]Tag, error) {
|
func DecodeTagArray(arr []string) ([]*Tag, error) {
|
||||||
result := make([]Tag, len(arr))
|
result := make([]*Tag, 0, len(arr))
|
||||||
for i, v := range arr {
|
for i, v := range arr {
|
||||||
|
result = append(result, &Tag{})
|
||||||
err := result[i].Decode(v)
|
err := result[i].Decode(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
Reference in New Issue
Block a user