Gisle Aune
4 years ago
16 changed files with 674 additions and 3 deletions
-
2database/postgres/db.go
-
15database/postgres/migrations/20210323181041_create_table_tag.sql
-
9database/postgres/migrations/20210323181601_create_index_tag_target.sql
-
20database/postgres/migrations/20210323201210_create_table_story.sql
-
9database/postgres/migrations/20210323203036_create_index_author.sql
-
9database/postgres/migrations/20210323203042_create_index_fictional_date.sql
-
9database/postgres/migrations/20210323203049_create_index_created_date.sql
-
9database/postgres/migrations/20210323203054_create_index_updated_date.sql
-
19database/postgres/psqlcore/models.go
-
113database/postgres/psqlcore/stories.sql.go
-
235database/postgres/psqlcore/tags.sql.go
-
13database/postgres/queries/stories.sql
-
35database/postgres/queries/tags.sql
-
129database/postgres/stories.go
-
46database/postgres/tags.go
-
5models/tag.go
@ -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 |
@ -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 |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue