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