2019-05-21 11:31:40 +08:00
|
|
|
package database
|
|
|
|
|
2019-05-22 00:24:11 +08:00
|
|
|
import (
|
2022-09-30 18:19:36 +08:00
|
|
|
"context"
|
2022-05-04 05:30:28 +08:00
|
|
|
"embed"
|
2022-09-30 18:19:36 +08:00
|
|
|
"log"
|
2019-05-22 00:24:11 +08:00
|
|
|
|
|
|
|
"github.com/go-shiori/shiori/internal/model"
|
2022-09-30 18:19:36 +08:00
|
|
|
"github.com/jmoiron/sqlx"
|
|
|
|
"github.com/pkg/errors"
|
2019-05-22 00:24:11 +08:00
|
|
|
)
|
|
|
|
|
2022-05-04 05:30:28 +08:00
|
|
|
//go:embed migrations/*
|
|
|
|
var migrations embed.FS
|
|
|
|
|
2019-05-30 11:07:20 +08:00
|
|
|
// OrderMethod is the order method for getting bookmarks
|
|
|
|
type OrderMethod int
|
|
|
|
|
|
|
|
const (
|
|
|
|
// DefaultOrder is oldest to newest.
|
|
|
|
DefaultOrder OrderMethod = iota
|
|
|
|
// ByLastAdded is from newest addition to the oldest.
|
|
|
|
ByLastAdded
|
|
|
|
// ByLastModified is from latest modified to the oldest.
|
|
|
|
ByLastModified
|
|
|
|
)
|
|
|
|
|
2019-05-22 00:24:11 +08:00
|
|
|
// GetBookmarksOptions is options for fetching bookmarks from database.
|
|
|
|
type GetBookmarksOptions struct {
|
2019-08-11 16:55:31 +08:00
|
|
|
IDs []int
|
|
|
|
Tags []string
|
|
|
|
ExcludedTags []string
|
|
|
|
Keyword string
|
|
|
|
WithContent bool
|
|
|
|
OrderMethod OrderMethod
|
|
|
|
Limit int
|
|
|
|
Offset int
|
2019-05-22 00:24:11 +08:00
|
|
|
}
|
|
|
|
|
2019-08-22 15:34:36 +08:00
|
|
|
// GetAccountsOptions is options for fetching accounts from database.
|
|
|
|
type GetAccountsOptions struct {
|
|
|
|
Keyword string
|
|
|
|
Owner bool
|
|
|
|
}
|
|
|
|
|
2019-05-21 11:31:40 +08:00
|
|
|
// DB is interface for accessing and manipulating data in database.
|
|
|
|
type DB interface {
|
2022-03-26 15:33:57 +08:00
|
|
|
// Migrate runs migrations for this database
|
|
|
|
Migrate() error
|
|
|
|
|
2019-05-22 17:13:52 +08:00
|
|
|
// SaveBookmarks saves bookmarks data to database.
|
2022-09-30 18:19:36 +08:00
|
|
|
SaveBookmarks(ctx context.Context, bookmarks ...model.Bookmark) ([]model.Bookmark, error)
|
2019-05-22 00:24:11 +08:00
|
|
|
|
|
|
|
// GetBookmarks fetch list of bookmarks based on submitted options.
|
2022-09-30 18:19:36 +08:00
|
|
|
GetBookmarks(ctx context.Context, opts GetBookmarksOptions) ([]model.Bookmark, error)
|
2019-05-22 00:24:11 +08:00
|
|
|
|
2019-05-27 18:01:53 +08:00
|
|
|
// GetBookmarksCount get count of bookmarks in database.
|
2022-09-30 18:19:36 +08:00
|
|
|
GetBookmarksCount(ctx context.Context, opts GetBookmarksOptions) (int, error)
|
2019-05-27 18:01:53 +08:00
|
|
|
|
2019-05-22 09:13:52 +08:00
|
|
|
// DeleteBookmarks removes all record with matching ids from database.
|
2022-09-30 18:19:36 +08:00
|
|
|
DeleteBookmarks(ctx context.Context, ids ...int) error
|
2019-05-22 09:13:52 +08:00
|
|
|
|
2022-09-30 18:19:36 +08:00
|
|
|
// GetBookmark fetchs bookmark based on its ID or URL.
|
|
|
|
GetBookmark(ctx context.Context, id int, url string) (model.Bookmark, bool, error)
|
2019-05-23 10:22:47 +08:00
|
|
|
|
2019-05-31 23:41:29 +08:00
|
|
|
// SaveAccount saves new account in database
|
2022-09-30 18:19:36 +08:00
|
|
|
SaveAccount(ctx context.Context, a model.Account) error
|
2019-05-31 23:41:29 +08:00
|
|
|
|
|
|
|
// GetAccounts fetch list of account (without its password) with matching keyword.
|
2022-09-30 18:19:36 +08:00
|
|
|
GetAccounts(ctx context.Context, opts GetAccountsOptions) ([]model.Account, error)
|
2019-05-27 18:01:53 +08:00
|
|
|
|
|
|
|
// GetAccount fetch account with matching username.
|
2022-09-30 18:19:36 +08:00
|
|
|
GetAccount(ctx context.Context, username string) (model.Account, bool, error)
|
2019-05-27 18:01:53 +08:00
|
|
|
|
2019-05-31 23:41:29 +08:00
|
|
|
// DeleteAccounts removes all record with matching usernames
|
2022-09-30 18:19:36 +08:00
|
|
|
DeleteAccounts(ctx context.Context, usernames ...string) error
|
2019-05-31 23:41:29 +08:00
|
|
|
|
2019-05-28 18:05:11 +08:00
|
|
|
// GetTags fetch list of tags and its frequency from database.
|
2022-09-30 18:19:36 +08:00
|
|
|
GetTags(ctx context.Context) ([]model.Tag, error)
|
2019-05-28 18:05:11 +08:00
|
|
|
|
2019-08-08 00:30:17 +08:00
|
|
|
// RenameTag change the name of a tag.
|
2022-09-30 18:19:36 +08:00
|
|
|
RenameTag(ctx context.Context, id int, newName string) error
|
2019-08-08 00:30:17 +08:00
|
|
|
|
2019-05-22 00:24:11 +08:00
|
|
|
// CreateNewID creates new id for specified table.
|
2022-09-30 18:19:36 +08:00
|
|
|
CreateNewID(ctx context.Context, table string) (int, error)
|
2019-05-22 00:24:11 +08:00
|
|
|
}
|
|
|
|
|
2022-09-30 18:19:36 +08:00
|
|
|
type dbbase struct {
|
|
|
|
sqlx.DB
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *dbbase) withTx(ctx context.Context, fn func(tx *sqlx.Tx) error) error {
|
|
|
|
tx, err := db.BeginTxx(ctx, nil)
|
|
|
|
if err != nil {
|
|
|
|
return errors.WithStack(err)
|
2019-05-22 00:24:11 +08:00
|
|
|
}
|
2022-09-30 18:19:36 +08:00
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if err := tx.Commit(); err != nil {
|
|
|
|
log.Printf("error during commit: %s", err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
err = fn(tx)
|
|
|
|
if err != nil {
|
|
|
|
if err := tx.Rollback(); err != nil {
|
|
|
|
log.Printf("error during rollback: %s", err)
|
|
|
|
}
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
2019-05-21 11:31:40 +08:00
|
|
|
}
|