Browse Source

add comment repository for postgres.

master
Gisle Aune 3 years ago
parent
commit
e4761ad4a0
  1. 16
      cmd/rpdata-restore/main.go
  2. 21
      database/postgres/chapters.go
  3. 113
      database/postgres/comments.go
  4. 2
      database/postgres/db.go
  5. 20
      database/postgres/migrations/20210327101320_create_table_comment.sql
  6. 9
      database/postgres/migrations/20210327101854_create_index_comment_chapter_id.sql
  7. 24
      database/postgres/queries/chapters.sql
  8. 45
      database/postgres/queries/characters.sql
  9. 34
      database/postgres/queries/comments.sql
  10. 5
      database/postgres/stories.go
  11. 18
      models/comment.go

16
cmd/rpdata-restore/main.go

@ -83,10 +83,6 @@ func main() {
hideList := make(map[string]bool)
if parts[1] != "story" && parts[1] != "chapter" {
continue
}
log.Println("Loaded", parts[1], parts[2], "from archive.")
switch parts[1] {
@ -159,6 +155,10 @@ func main() {
log.Fatalln("Could not parse story:", parts[2], err)
}
if *flagReplace {
_ = db.Stories().Delete(ctx, story)
}
_, err = db.Stories().Insert(ctx, story)
if err != nil {
log.Fatalln("Could not insert story:", parts[2], err)
@ -179,6 +179,10 @@ func main() {
log.Fatalln("Could not parse story:", parts[2], err)
}
if *flagReplace {
_ = db.Chapters().Delete(ctx, chapter)
}
_, err = db.Chapters().Insert(ctx, chapter)
if err != nil {
log.Fatalln("Could not insert story:", parts[2], err)
@ -199,6 +203,10 @@ func main() {
log.Fatalln("Could not parse story:", parts[2], err)
}
if *flagReplace {
_ = db.Comments().Delete(ctx, comment)
}
_, err = db.Comments().Insert(ctx, comment)
if err != nil {
log.Fatalln("Could not insert story:", parts[2], err)

21
database/postgres/chapters.go

@ -84,7 +84,7 @@ func (r *chapterRepository) Update(ctx context.Context, chapter models.Chapter,
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{
StoryID: to.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 {
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 {

113
database/postgres/comments.go

@ -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
}

2
database/postgres/db.go

@ -85,7 +85,7 @@ func (d *DB) Chapters() repositories.ChapterRepository {
}
func (d *DB) Comments() repositories.CommentRepository {
panic("implement me")
return &commentRepository{insertWithIDs: d.insertWithIDs, db: d.db}
}
func (d *DB) Keys() repositories.KeyRepository {

20
database/postgres/migrations/20210327101320_create_table_comment.sql

@ -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

9
database/postgres/migrations/20210327101854_create_index_comment_chapter_id.sql

@ -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

24
database/postgres/queries/chapters.sql

@ -2,29 +2,29 @@
SELECT * FROM story_chapter WHERE id=$1::TEXT LIMIT 1;
-- 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
INSERT INTO story_chapter (id, story_id, title, author, source, created_date, fictional_date, edited_date, comment_mode, comments_locked)
VALUES (
sqlc.arg(id)::TEXT, sqlc.arg(story_id)::TEXT, sqlc.arg(title)::TEXT, sqlc.arg(author)::TEXT, sqlc.arg(source)::TEXT,
sqlc.arg(created_date)::TIMESTAMP, sqlc.arg(fictional_date)::TIMESTAMP, sqlc.arg(edited_date)::TIMESTAMP,
sqlc.arg(comment_mode)::TEXT, sqlc.arg(comments_locked)::BOOLEAN
@id::TEXT, @story_id::TEXT, @title::TEXT, @author::TEXT, @source::TEXT,
@created_date::TIMESTAMP, @fictional_date::TIMESTAMP, @edited_date::TIMESTAMP,
@comment_mode::TEXT, @comments_locked::BOOLEAN
);
-- name: UpdateChapterStoryID :exec
UPDATE story_chapter
SET story_id=sqlc.arg(story_id)::TEXT
WHERE id=sqlc.arg(id);
SET story_id = @story_id::TEXT
WHERE id = @id;
-- name: UpdateChapter :exec
UPDATE story_chapter
SET title=sqlc.arg(title),
source=sqlc.arg(source),
fictional_date=sqlc.arg(fictional_date),
comment_mode=sqlc.arg(comment_mode),
comments_locked=sqlc.arg(comments_locked)
WHERE id=sqlc.arg(id);
SET title = @title,
source = @source,
fictional_date = @fictional_date,
comment_mode = @comment_mode,
comments_locked = @comments_locked
WHERE id = @id;
-- name: DeleteChapter :exec
DELETE FROM story_chapter WHERE id=$1;

45
database/postgres/queries/characters.sql

@ -1,50 +1,47 @@
-- name: SelectCharacterByID :one
SELECT * FROM data_character WHERE id = sqlc.arg(id)::text;
SELECT * FROM data_character WHERE id = @id::text;
-- 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
SELECT * FROM data_character WHERE name = sqlc.arg(name)::text;
SELECT * FROM data_character WHERE name = @name::text;
-- name: SelectCharacters :many
SELECT * FROM data_character
WHERE (sqlc.arg(filter_id)::bool = false OR id = ANY(sqlc.arg(ids)::text[]))
AND (sqlc.arg(filter_name)::bool = false OR name = ANY(sqlc.arg(names)::text[]))
AND (sqlc.arg(filter_nick)::bool = false OR nicks && (sqlc.arg(nicks)::text[]))
AND (sqlc.arg(filter_author)::bool = false OR author = sqlc.arg(author)::text)
AND (sqlc.arg(filter_search)::bool = false OR "ts_vector" @@ to_tsquery(sqlc.arg(search)::text))
LIMIT sqlc.arg(limit_size)::int;
WHERE (@filter_id::bool = false OR id = ANY(@ids::text[]))
AND (@filter_name::bool = false OR name = ANY(@names::text[]))
AND (@filter_nick::bool = false OR nicks && (@nicks::text[]))
AND (@filter_author::bool = false OR author = @author::text)
AND (@filter_search::bool = false OR "ts_vector" @@ to_tsquery(@search::text))
LIMIT @limit_size::int;
-- name: InsertCharacter :exec
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,
sqlc.arg(short_name)::text, sqlc.arg(author)::text, sqlc.arg(description)::text,
@id::text, @nicks::text[], @name::text,
@short_name::text, @author::text, @description::text,
to_tsvector(
'english',
sqlc.arg(name)::text || ' ' || sqlc.arg(description)::text || ' ' || sqlc.arg(author)::text || ' '
|| immutable_array_to_string(
sqlc.arg(nicks)::text[], ' '
)
'english', @name::text || ' ' || @description::text || ' ' || @author::text || ' '
|| immutable_array_to_string(@nicks::text[], ' ')
)
);
-- name: UpdateCharacter :exec
UPDATE data_character
SET name=sqlc.arg(name)::text,
short_name=sqlc.arg(short_name)::text,
description=sqlc.arg(description)::text
WHERE id=sqlc.arg(id)::text;
SET name = @name::text,
short_name = @short_name::text,
description = @description::text
WHERE id = @id::text;
-- name: AddCharacterNick :exec
UPDATE data_character
SET nicks=append(nicks, sqlc.arg(nick)::text)
WHERE id=sqlc.arg(id)::text;
SET nicks=array_append(nicks, @nick::text)
WHERE id = @id::text;
-- name: RemoveCharacterNick :exec
UPDATE data_character
SET nicks=array_remove(nicks, sqlc.arg(nick)::text)
WHERE id=sqlc.arg(id)::text;
SET nicks=array_remove(nicks, @nick::text)
WHERE id = @id::text;
-- name: DeleteCharacter :exec
DELETE FROM data_character WHERE id=$1;

34
database/postgres/queries/comments.sql

@ -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
database/postgres/stories.go

@ -193,6 +193,11 @@ func (r *storyRepository) Delete(ctx context.Context, story models.Story) error
return err
}
err = q.DeleteCommentsByStoryID(ctx, story.ID)
if err != nil {
return err
}
err = q.DeleteChaptersByStoryID(ctx, story.ID)
if err != nil {
return err

18
models/comment.go

@ -16,6 +16,24 @@ type Comment struct {
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
// ChangeObject in GQL.
func (*Comment) IsChangeObject() {

Loading…
Cancel
Save