add comment repository for postgres.
continuous-integration/drone/push Build is passing

This commit is contained in:
2021-03-27 13:56:51 +01:00
parent 21b7b44159
commit e4761ad4a0
11 changed files with 264 additions and 43 deletions
+12 -4
View File
@@ -83,10 +83,6 @@ func main() {
hideList := make(map[string]bool) hideList := make(map[string]bool)
if parts[1] != "story" && parts[1] != "chapter" {
continue
}
log.Println("Loaded", parts[1], parts[2], "from archive.") log.Println("Loaded", parts[1], parts[2], "from archive.")
switch parts[1] { switch parts[1] {
@@ -159,6 +155,10 @@ func main() {
log.Fatalln("Could not parse story:", parts[2], err) log.Fatalln("Could not parse story:", parts[2], err)
} }
if *flagReplace {
_ = db.Stories().Delete(ctx, story)
}
_, err = db.Stories().Insert(ctx, story) _, err = db.Stories().Insert(ctx, story)
if err != nil { if err != nil {
log.Fatalln("Could not insert story:", parts[2], err) log.Fatalln("Could not insert story:", parts[2], err)
@@ -179,6 +179,10 @@ func main() {
log.Fatalln("Could not parse story:", parts[2], err) log.Fatalln("Could not parse story:", parts[2], err)
} }
if *flagReplace {
_ = db.Chapters().Delete(ctx, chapter)
}
_, err = db.Chapters().Insert(ctx, chapter) _, err = db.Chapters().Insert(ctx, chapter)
if err != nil { if err != nil {
log.Fatalln("Could not insert story:", parts[2], err) log.Fatalln("Could not insert story:", parts[2], err)
@@ -199,6 +203,10 @@ func main() {
log.Fatalln("Could not parse story:", parts[2], err) log.Fatalln("Could not parse story:", parts[2], err)
} }
if *flagReplace {
_ = db.Comments().Delete(ctx, comment)
}
_, err = db.Comments().Insert(ctx, comment) _, err = db.Comments().Insert(ctx, comment)
if err != nil { if err != nil {
log.Fatalln("Could not insert story:", parts[2], err) log.Fatalln("Could not insert story:", parts[2], err)
+19 -2
View File
@@ -84,7 +84,7 @@ func (r *chapterRepository) Update(ctx context.Context, chapter models.Chapter,
return &chapter, nil return &chapter, nil
} }
func (r *chapterRepository) Move(ctx context.Context, chapter models.Chapter, from, to models.Story) (*models.Chapter, error) { func (r *chapterRepository) Move(ctx context.Context, chapter models.Chapter, _, to models.Story) (*models.Chapter, error) {
err := psqlcore.New(r.db).UpdateChapterStoryID(ctx, psqlcore.UpdateChapterStoryIDParams{ err := psqlcore.New(r.db).UpdateChapterStoryID(ctx, psqlcore.UpdateChapterStoryIDParams{
StoryID: to.ID, StoryID: to.ID,
ID: chapter.ID, ID: chapter.ID,
@@ -99,7 +99,24 @@ func (r *chapterRepository) Move(ctx context.Context, chapter models.Chapter, fr
} }
func (r *chapterRepository) Delete(ctx context.Context, chapter models.Chapter) error { func (r *chapterRepository) Delete(ctx context.Context, chapter models.Chapter) error {
return psqlcore.New(r.db).DeleteChapter(ctx, chapter.ID) tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return err
}
defer func() { _ = tx.Rollback() }()
q := psqlcore.New(tx)
err = q.DeleteCommentsByChapterID(ctx, chapter.ID)
if err != nil {
return err
}
err = q.DeleteChapter(ctx, chapter.ID)
if err != nil {
return err
}
return tx.Commit()
} }
func (r *chapterRepository) chapter(chapter psqlcore.StoryChapter) *models.Chapter { func (r *chapterRepository) chapter(chapter psqlcore.StoryChapter) *models.Chapter {
+113
View File
@@ -0,0 +1,113 @@
package postgres
import (
"context"
"database/sql"
"git.aiterp.net/rpdata/api/database/postgres/psqlcore"
"git.aiterp.net/rpdata/api/internal/generate"
"git.aiterp.net/rpdata/api/models"
)
type commentRepository struct {
insertWithIDs bool
db *sql.DB
}
func (r *commentRepository) Find(ctx context.Context, id string) (*models.Comment, error) {
comment, err := psqlcore.New(r.db).SelectComment(ctx, id)
if err != nil {
return nil, err
}
return r.comment(comment), nil
}
func (r *commentRepository) List(ctx context.Context, filter models.CommentFilter) ([]*models.Comment, error) {
params := psqlcore.SelectCommentsParams{
ChapterID: "",
LimitSize: 10000,
}
if filter.ChapterID != nil {
params.ChapterID = *filter.ChapterID
}
if filter.Limit > 0 {
params.LimitSize = int32(filter.Limit)
}
comments, err := psqlcore.New(r.db).SelectComments(ctx, params)
if err != nil {
return nil, err
}
return r.comments(comments), nil
}
func (r *commentRepository) Insert(ctx context.Context, comment models.Comment) (*models.Comment, error) {
if !r.insertWithIDs || len(comment.ID) < 8 {
comment.ID = generate.CommentID()
}
err := psqlcore.New(r.db).InsertComment(ctx, psqlcore.InsertCommentParams{
ID: comment.ID,
ChapterID: comment.ChapterID,
CharacterID: comment.CharacterID,
Subject: comment.Subject,
Author: comment.Author,
CharacterName: comment.CharacterID,
Source: comment.Source,
CreatedDate: comment.CreatedDate.UTC(),
FictionalDate: comment.FictionalDate.UTC(),
EditedDate: comment.EditedDate.UTC(),
})
if err != nil {
return nil, err
}
return &comment, nil
}
func (r *commentRepository) Update(ctx context.Context, comment models.Comment, update models.CommentUpdate) (*models.Comment, error) {
comment.ApplyUpdate(update)
err := psqlcore.New(r.db).UpdateComment(ctx, psqlcore.UpdateCommentParams{
Subject: comment.Subject,
Source: comment.Source,
FictionalDate: comment.FictionalDate.UTC(),
CharacterName: comment.ChapterID,
CharacterID: comment.CharacterID,
ID: comment.ID,
})
if err != nil {
return nil, err
}
return &comment, nil
}
func (r *commentRepository) Delete(ctx context.Context, comment models.Comment) error {
return psqlcore.New(r.db).DeleteComment(ctx, comment.ID)
}
func (r *commentRepository) comment(comment psqlcore.StoryComment) *models.Comment {
return &models.Comment{
ID: comment.ID,
ChapterID: comment.ChapterID,
Subject: comment.Subject,
Author: comment.Author,
CharacterName: comment.CharacterName,
CharacterID: comment.CharacterID,
FictionalDate: comment.FictionalDate,
CreatedDate: comment.CreatedDate,
EditedDate: comment.EditedDate,
Source: comment.Source,
}
}
func (r *commentRepository) comments(comments []psqlcore.StoryComment) []*models.Comment {
results := make([]*models.Comment, 0, len(comments))
for _, comment := range comments {
results = append(results, r.comment(comment))
}
return results
}
+1 -1
View File
@@ -85,7 +85,7 @@ func (d *DB) Chapters() repositories.ChapterRepository {
} }
func (d *DB) Comments() repositories.CommentRepository { func (d *DB) Comments() repositories.CommentRepository {
panic("implement me") return &commentRepository{insertWithIDs: d.insertWithIDs, db: d.db}
} }
func (d *DB) Keys() repositories.KeyRepository { func (d *DB) Keys() repositories.KeyRepository {
@@ -0,0 +1,20 @@
-- +goose Up
-- +goose StatementBegin
CREATE TABLE story_comment (
id TEXT NOT NULL PRIMARY KEY,
chapter_id TEXT NOT NULL,
character_id TEXT NOT NULL,
subject TEXT NOT NULL,
author TEXT NOT NULL,
character_name TEXT NOT NULL,
source TEXT NOT NULL,
created_date TIMESTAMP NOT NULL,
fictional_date TIMESTAMP NOT NULL,
edited_date TIMESTAMP NOT NULL
);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP TABLE story_comment;
-- +goose StatementEnd
@@ -0,0 +1,9 @@
-- +goose Up
-- +goose StatementBegin
CREATE INDEX story_comment_index_chapter_id ON story_comment (chapter_id);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP INDEX IF EXISTS story_comment_index_chapter_id;
-- +goose StatementEnd
+12 -12
View File
@@ -2,29 +2,29 @@
SELECT * FROM story_chapter WHERE id=$1::TEXT LIMIT 1; SELECT * FROM story_chapter WHERE id=$1::TEXT LIMIT 1;
-- name: SelectChapters :many -- name: SelectChapters :many
SELECT * FROM story_chapter WHERE (sqlx.arg(story_id)::TEXT == '' OR story_id=sqlc.arg(story_id)::TEXT) ORDER BY created_date LIMIT sqlc.arg(limit_size)::INT; SELECT * FROM story_chapter WHERE (sqlx.arg(story_id)::TEXT == '' OR story_id = @story_id::TEXT) ORDER BY created_date LIMIT @limit_size;
-- name: InsertChapter :exec -- name: InsertChapter :exec
INSERT INTO story_chapter (id, story_id, title, author, source, created_date, fictional_date, edited_date, comment_mode, comments_locked) INSERT INTO story_chapter (id, story_id, title, author, source, created_date, fictional_date, edited_date, comment_mode, comments_locked)
VALUES ( VALUES (
sqlc.arg(id)::TEXT, sqlc.arg(story_id)::TEXT, sqlc.arg(title)::TEXT, sqlc.arg(author)::TEXT, sqlc.arg(source)::TEXT, @id::TEXT, @story_id::TEXT, @title::TEXT, @author::TEXT, @source::TEXT,
sqlc.arg(created_date)::TIMESTAMP, sqlc.arg(fictional_date)::TIMESTAMP, sqlc.arg(edited_date)::TIMESTAMP, @created_date::TIMESTAMP, @fictional_date::TIMESTAMP, @edited_date::TIMESTAMP,
sqlc.arg(comment_mode)::TEXT, sqlc.arg(comments_locked)::BOOLEAN @comment_mode::TEXT, @comments_locked::BOOLEAN
); );
-- name: UpdateChapterStoryID :exec -- name: UpdateChapterStoryID :exec
UPDATE story_chapter UPDATE story_chapter
SET story_id=sqlc.arg(story_id)::TEXT SET story_id = @story_id::TEXT
WHERE id=sqlc.arg(id); WHERE id = @id;
-- name: UpdateChapter :exec -- name: UpdateChapter :exec
UPDATE story_chapter UPDATE story_chapter
SET title=sqlc.arg(title), SET title = @title,
source=sqlc.arg(source), source = @source,
fictional_date=sqlc.arg(fictional_date), fictional_date = @fictional_date,
comment_mode=sqlc.arg(comment_mode), comment_mode = @comment_mode,
comments_locked=sqlc.arg(comments_locked) comments_locked = @comments_locked
WHERE id=sqlc.arg(id); WHERE id = @id;
-- name: DeleteChapter :exec -- name: DeleteChapter :exec
DELETE FROM story_chapter WHERE id=$1; DELETE FROM story_chapter WHERE id=$1;
+21 -24
View File
@@ -1,50 +1,47 @@
-- name: SelectCharacterByID :one -- name: SelectCharacterByID :one
SELECT * FROM data_character WHERE id = sqlc.arg(id)::text; SELECT * FROM data_character WHERE id = @id::text;
-- name: SelectCharacterByNick :one -- name: SelectCharacterByNick :one
SELECT * FROM data_character WHERE nicks <@ ARRAY[sqlc.arg(nick)::text]; SELECT * FROM data_character WHERE nicks <@ ARRAY[@nick::text];
-- name: SelectCharacterByName :one -- name: SelectCharacterByName :one
SELECT * FROM data_character WHERE name = sqlc.arg(name)::text; SELECT * FROM data_character WHERE name = @name::text;
-- name: SelectCharacters :many -- name: SelectCharacters :many
SELECT * FROM data_character SELECT * FROM data_character
WHERE (sqlc.arg(filter_id)::bool = false OR id = ANY(sqlc.arg(ids)::text[])) WHERE (@filter_id::bool = false OR id = ANY(@ids::text[]))
AND (sqlc.arg(filter_name)::bool = false OR name = ANY(sqlc.arg(names)::text[])) AND (@filter_name::bool = false OR name = ANY(@names::text[]))
AND (sqlc.arg(filter_nick)::bool = false OR nicks && (sqlc.arg(nicks)::text[])) AND (@filter_nick::bool = false OR nicks && (@nicks::text[]))
AND (sqlc.arg(filter_author)::bool = false OR author = sqlc.arg(author)::text) AND (@filter_author::bool = false OR author = @author::text)
AND (sqlc.arg(filter_search)::bool = false OR "ts_vector" @@ to_tsquery(sqlc.arg(search)::text)) AND (@filter_search::bool = false OR "ts_vector" @@ to_tsquery(@search::text))
LIMIT sqlc.arg(limit_size)::int; LIMIT @limit_size::int;
-- name: InsertCharacter :exec -- name: InsertCharacter :exec
INSERT INTO data_character (id, nicks, name, short_name, author, description, ts_vector) VALUES ( INSERT INTO data_character (id, nicks, name, short_name, author, description, ts_vector) VALUES (
sqlc.arg(id)::text, sqlc.arg(nicks)::text[], sqlc.arg(name)::text, @id::text, @nicks::text[], @name::text,
sqlc.arg(short_name)::text, sqlc.arg(author)::text, sqlc.arg(description)::text, @short_name::text, @author::text, @description::text,
to_tsvector( to_tsvector(
'english', 'english', @name::text || ' ' || @description::text || ' ' || @author::text || ' '
sqlc.arg(name)::text || ' ' || sqlc.arg(description)::text || ' ' || sqlc.arg(author)::text || ' ' || immutable_array_to_string(@nicks::text[], ' ')
|| immutable_array_to_string(
sqlc.arg(nicks)::text[], ' '
)
) )
); );
-- name: UpdateCharacter :exec -- name: UpdateCharacter :exec
UPDATE data_character UPDATE data_character
SET name=sqlc.arg(name)::text, SET name = @name::text,
short_name=sqlc.arg(short_name)::text, short_name = @short_name::text,
description=sqlc.arg(description)::text description = @description::text
WHERE id=sqlc.arg(id)::text; WHERE id = @id::text;
-- name: AddCharacterNick :exec -- name: AddCharacterNick :exec
UPDATE data_character UPDATE data_character
SET nicks=append(nicks, sqlc.arg(nick)::text) SET nicks=array_append(nicks, @nick::text)
WHERE id=sqlc.arg(id)::text; WHERE id = @id::text;
-- name: RemoveCharacterNick :exec -- name: RemoveCharacterNick :exec
UPDATE data_character UPDATE data_character
SET nicks=array_remove(nicks, sqlc.arg(nick)::text) SET nicks=array_remove(nicks, @nick::text)
WHERE id=sqlc.arg(id)::text; WHERE id = @id::text;
-- name: DeleteCharacter :exec -- name: DeleteCharacter :exec
DELETE FROM data_character WHERE id=$1; DELETE FROM data_character WHERE id=$1;
+34
View File
@@ -0,0 +1,34 @@
-- name: SelectComment :one
SELECT * FROM story_comment WHERE id=$1;
-- name: InsertComment :exec
INSERT INTO story_comment (id, chapter_id, character_id, subject, author, character_name, source, created_date, fictional_date, edited_date)
VALUES (
@id, @chapter_id, @character_id,
@subject, @author, @character_name, @source,
@created_date, @fictional_date, @edited_date
);
-- name: UpdateComment :exec
UPDATE story_comment
SET subject = @subject,
source = @source,
fictional_date = @fictional_date,
character_name = @character_name,
character_id = @character_id
WHERE id = @id;
-- name: SelectComments :many
SELECT * FROM story_comment WHERE (@chapter_id = '' OR chapter_id = @chapter_id) LIMIT @limit_size;
-- name: DeleteComment :exec
DELETE FROM story_comment WHERE id = $1;
-- name: DeleteCommentsByChapterID :exec
DELETE FROM story_comment WHERE chapter_id = $1;
-- name: DeleteCommentsByStoryID :exec
DELETE FROM story_comment
WHERE chapter_id IN (
SELECT id FROM story_chapter WHERE story_id = $1
);
+5
View File
@@ -193,6 +193,11 @@ func (r *storyRepository) Delete(ctx context.Context, story models.Story) error
return err return err
} }
err = q.DeleteCommentsByStoryID(ctx, story.ID)
if err != nil {
return err
}
err = q.DeleteChaptersByStoryID(ctx, story.ID) err = q.DeleteChaptersByStoryID(ctx, story.ID)
if err != nil { if err != nil {
return err return err
+18
View File
@@ -16,6 +16,24 @@ type Comment struct {
Source string `bson:"source"` Source string `bson:"source"`
} }
func (comment *Comment) ApplyUpdate(update CommentUpdate) {
if update.Source != nil {
comment.Source = *update.Source
}
if update.CharacterName != nil {
comment.CharacterName = *update.CharacterName
}
if update.CharacterID != nil {
comment.CharacterID = *update.CharacterID
}
if update.Subject != nil {
comment.Subject = *update.Subject
}
if update.FictionalDate != nil {
comment.FictionalDate = *update.FictionalDate
}
}
// IsChangeObject is an interface implementation to identify it as a valid // IsChangeObject is an interface implementation to identify it as a valid
// ChangeObject in GQL. // ChangeObject in GQL.
func (*Comment) IsChangeObject() { func (*Comment) IsChangeObject() {