mirror of
https://github.com/usememos/memos.git
synced 2025-02-14 10:20:49 +01:00
chore: adjust store test for mysql
This commit is contained in:
parent
255254eb69
commit
87ddeb2c79
@ -26,6 +26,7 @@ type Profile struct {
|
|||||||
// DSN points to where Memos stores its own data
|
// DSN points to where Memos stores its own data
|
||||||
DSN string `json:"dsn"`
|
DSN string `json:"dsn"`
|
||||||
// Driver is the database driver
|
// Driver is the database driver
|
||||||
|
// sqlite, mysql
|
||||||
Driver string `json:"driver"`
|
Driver string `json:"driver"`
|
||||||
// Version is the current version of server
|
// Version is the current version of server
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
|
@ -2,11 +2,13 @@ package store
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
|
||||||
storepb "github.com/usememos/memos/proto/gen/store"
|
storepb "github.com/usememos/memos/proto/gen/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Driver interface {
|
type Driver interface {
|
||||||
|
GetDB() *sql.DB
|
||||||
Close() error
|
Close() error
|
||||||
|
|
||||||
Migrate(ctx context.Context) error
|
Migrate(ctx context.Context) error
|
||||||
|
@ -3,7 +3,6 @@ package mysql
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -56,7 +55,7 @@ func (d *Driver) CreateIdentityProvider(ctx context.Context, create *store.Ident
|
|||||||
func (d *Driver) ListIdentityProviders(ctx context.Context, find *store.FindIdentityProvider) ([]*store.IdentityProvider, error) {
|
func (d *Driver) ListIdentityProviders(ctx context.Context, find *store.FindIdentityProvider) ([]*store.IdentityProvider, error) {
|
||||||
where, args := []string{"1 = 1"}, []any{}
|
where, args := []string{"1 = 1"}, []any{}
|
||||||
if v := find.ID; v != nil {
|
if v := find.ID; v != nil {
|
||||||
where, args = append(where, fmt.Sprintf("id = $%d", len(args)+1)), append(args, *v)
|
where, args = append(where, "id = ?"), append(args, *v)
|
||||||
}
|
}
|
||||||
|
|
||||||
rows, err := d.db.QueryContext(ctx, `
|
rows, err := d.db.QueryContext(ctx, `
|
||||||
@ -150,39 +149,22 @@ func (d *Driver) UpdateIdentityProvider(ctx context.Context, update *store.Updat
|
|||||||
UPDATE idp
|
UPDATE idp
|
||||||
SET ` + strings.Join(set, ", ") + `
|
SET ` + strings.Join(set, ", ") + `
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
RETURNING id, name, type, identifier_filter, config
|
|
||||||
`
|
`
|
||||||
_, err := d.db.ExecContext(ctx, stmt, args...)
|
_, err := d.db.ExecContext(ctx, stmt, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var identityProvider store.IdentityProvider
|
identityProvider, err := d.GetIdentityProvider(ctx, &store.FindIdentityProvider{
|
||||||
var identityProviderConfig string
|
ID: &update.ID,
|
||||||
stmt = `SELECT id, name, type, identifier_filter, config FROM idp WHERE id = ?`
|
})
|
||||||
if err := d.db.QueryRowContext(ctx, stmt, update.ID).Scan(
|
if err != nil {
|
||||||
&identityProvider.ID,
|
|
||||||
&identityProvider.Name,
|
|
||||||
&identityProvider.Type,
|
|
||||||
&identityProvider.IdentifierFilter,
|
|
||||||
&identityProviderConfig,
|
|
||||||
); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if identityProvider == nil {
|
||||||
if identityProvider.Type == store.IdentityProviderOAuth2Type {
|
return nil, errors.Errorf("idp %d not found", update.ID)
|
||||||
oauth2Config := &store.IdentityProviderOAuth2Config{}
|
|
||||||
if err := json.Unmarshal([]byte(identityProviderConfig), oauth2Config); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
identityProvider.Config = &store.IdentityProviderConfig{
|
|
||||||
OAuth2Config: oauth2Config,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, errors.Errorf("unsupported idp type %s", string(identityProvider.Type))
|
|
||||||
}
|
}
|
||||||
|
return identityProvider, nil
|
||||||
return &identityProvider, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) DeleteIdentityProvider(ctx context.Context, delete *store.DeleteIdentityProvider) error {
|
func (d *Driver) DeleteIdentityProvider(ctx context.Context, delete *store.DeleteIdentityProvider) error {
|
||||||
|
@ -32,37 +32,19 @@ func (d *Driver) CreateMemo(ctx context.Context, create *store.Memo) (*store.Mem
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := result.LastInsertId()
|
rawID, err := result.LastInsertId()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
id := int32(rawID)
|
||||||
var memo store.Memo
|
memo, err := d.GetMemo(ctx, &store.FindMemo{ID: &id})
|
||||||
stmt = `
|
if err != nil {
|
||||||
SELECT
|
|
||||||
id,
|
|
||||||
creator_id,
|
|
||||||
content,
|
|
||||||
visibility,
|
|
||||||
UNIX_TIMESTAMP(created_ts),
|
|
||||||
UNIX_TIMESTAMP(updated_ts),
|
|
||||||
row_status
|
|
||||||
FROM memo
|
|
||||||
WHERE id = ?
|
|
||||||
`
|
|
||||||
if err := d.db.QueryRowContext(ctx, stmt, id).Scan(
|
|
||||||
&memo.ID,
|
|
||||||
&memo.CreatorID,
|
|
||||||
&memo.Content,
|
|
||||||
&memo.Visibility,
|
|
||||||
&memo.UpdatedTs,
|
|
||||||
&memo.CreatedTs,
|
|
||||||
&memo.RowStatus,
|
|
||||||
); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if memo == nil {
|
||||||
return &memo, nil
|
return nil, errors.Errorf("failed to create memo")
|
||||||
|
}
|
||||||
|
return memo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo, error) {
|
func (d *Driver) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo, error) {
|
||||||
@ -211,6 +193,19 @@ func (d *Driver) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.
|
|||||||
return list, nil
|
return list, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Driver) GetMemo(ctx context.Context, find *store.FindMemo) (*store.Memo, error) {
|
||||||
|
list, err := d.ListMemos(ctx, find)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(list) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
memo := list[0]
|
||||||
|
return memo, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Driver) UpdateMemo(ctx context.Context, update *store.UpdateMemo) error {
|
func (d *Driver) UpdateMemo(ctx context.Context, update *store.UpdateMemo) error {
|
||||||
set, args := []string{}, []any{}
|
set, args := []string{}, []any{}
|
||||||
if v := update.CreatedTs; v != nil {
|
if v := update.CreatedTs; v != nil {
|
||||||
|
@ -1,109 +1,34 @@
|
|||||||
-- activity
|
-- drop all tables first
|
||||||
CREATE TABLE IF NOT EXISTS `activity` (
|
DROP TABLE IF EXISTS `migration_history`;
|
||||||
`id` int NOT NULL AUTO_INCREMENT,
|
DROP TABLE IF EXISTS `system_setting`;
|
||||||
`creator_id` int NOT NULL,
|
DROP TABLE IF EXISTS `user`;
|
||||||
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
DROP TABLE IF EXISTS `user_setting`;
|
||||||
`type` varchar(255) NOT NULL DEFAULT '',
|
DROP TABLE IF EXISTS `memo`;
|
||||||
`level` varchar(255) NOT NULL DEFAULT 'INFO',
|
DROP TABLE IF EXISTS `memo_organizer`;
|
||||||
`payload` text NOT NULL,
|
DROP TABLE IF EXISTS `memo_relation`;
|
||||||
PRIMARY KEY (`id`),
|
DROP TABLE IF EXISTS `resource`;
|
||||||
CONSTRAINT `activity_chk_1` CHECK ((`level` in (_utf8mb4'INFO',_utf8mb4'WARN',_utf8mb4'ERROR')))
|
DROP TABLE IF EXISTS `tag`;
|
||||||
);
|
DROP TABLE IF EXISTS `activity`;
|
||||||
|
DROP TABLE IF EXISTS `storage`;
|
||||||
-- idp
|
DROP TABLE IF EXISTS `idp`;
|
||||||
CREATE TABLE IF NOT EXISTS `idp` (
|
|
||||||
`id` int NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` text NOT NULL,
|
|
||||||
`type` text NOT NULL,
|
|
||||||
`identifier_filter` varchar(256) NOT NULL DEFAULT '',
|
|
||||||
`config` text NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- memo
|
|
||||||
CREATE TABLE IF NOT EXISTS `memo` (
|
|
||||||
`id` int NOT NULL AUTO_INCREMENT,
|
|
||||||
`creator_id` int NOT NULL,
|
|
||||||
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`updated_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`row_status` varchar(255) NOT NULL DEFAULT 'NORMAL',
|
|
||||||
`content` text NOT NULL,
|
|
||||||
`visibility` varchar(255) NOT NULL DEFAULT 'PRIVATE',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `creator_id` (`creator_id`),
|
|
||||||
KEY `visibility` (`visibility`),
|
|
||||||
CONSTRAINT `memo_chk_1` CHECK ((`row_status` in (_utf8mb4'NORMAL',_utf8mb4'ARCHIVED'))),
|
|
||||||
CONSTRAINT `memo_chk_2` CHECK ((`visibility` in (_utf8mb4'PUBLIC',_utf8mb4'PROTECTED',_utf8mb4'PRIVATE')))
|
|
||||||
);
|
|
||||||
|
|
||||||
-- memo_organizer
|
|
||||||
CREATE TABLE IF NOT EXISTS `memo_organizer` (
|
|
||||||
`memo_id` int NOT NULL,
|
|
||||||
`user_id` int NOT NULL,
|
|
||||||
`pinned` int NOT NULL DEFAULT '0',
|
|
||||||
UNIQUE KEY `memo_id` (`memo_id`,`user_id`),
|
|
||||||
CONSTRAINT `memo_organizer_chk_1` CHECK ((`pinned` in (0,1)))
|
|
||||||
);
|
|
||||||
|
|
||||||
-- memo_relation
|
|
||||||
CREATE TABLE IF NOT EXISTS `memo_relation` (
|
|
||||||
`memo_id` int NOT NULL,
|
|
||||||
`related_memo_id` int NOT NULL,
|
|
||||||
`type` varchar(256) NOT NULL,
|
|
||||||
UNIQUE KEY `memo_id` (`memo_id`,`related_memo_id`,`type`)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- migration_history
|
-- migration_history
|
||||||
CREATE TABLE IF NOT EXISTS `migration_history` (
|
CREATE TABLE `migration_history` (
|
||||||
`version` varchar(255) NOT NULL,
|
`version` varchar(255) NOT NULL,
|
||||||
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (`version`)
|
PRIMARY KEY (`version`)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- resource
|
|
||||||
CREATE TABLE IF NOT EXISTS `resource` (
|
|
||||||
`id` int NOT NULL AUTO_INCREMENT,
|
|
||||||
`creator_id` int NOT NULL,
|
|
||||||
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`updated_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`filename` text NOT NULL,
|
|
||||||
`blob` blob,
|
|
||||||
`external_link` text NOT NULL,
|
|
||||||
`type` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`size` int NOT NULL DEFAULT '0',
|
|
||||||
`internal_path` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`memo_id` int DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `creator_id` (`creator_id`),
|
|
||||||
KEY `memo_id` (`memo_id`)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- storage
|
|
||||||
CREATE TABLE IF NOT EXISTS `storage` (
|
|
||||||
`id` int NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` varchar(256) NOT NULL,
|
|
||||||
`type` varchar(256) NOT NULL,
|
|
||||||
`config` text NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- system_setting
|
-- system_setting
|
||||||
CREATE TABLE IF NOT EXISTS `system_setting` (
|
CREATE TABLE `system_setting` (
|
||||||
`name` varchar(255) NOT NULL,
|
`name` varchar(255) NOT NULL,
|
||||||
`value` text NOT NULL,
|
`value` text NOT NULL,
|
||||||
`description` text NOT NULL,
|
`description` text NOT NULL,
|
||||||
PRIMARY KEY (`name`)
|
PRIMARY KEY (`name`)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- tag
|
|
||||||
CREATE TABLE IF NOT EXISTS `tag` (
|
|
||||||
`name` varchar(255) NOT NULL,
|
|
||||||
`creator_id` int NOT NULL,
|
|
||||||
UNIQUE KEY `name` (`name`,`creator_id`)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- user
|
-- user
|
||||||
CREATE TABLE IF NOT EXISTS `user` (
|
CREATE TABLE `user` (
|
||||||
`id` int NOT NULL AUTO_INCREMENT,
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
`updated_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
`updated_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
@ -121,11 +46,98 @@ CREATE TABLE IF NOT EXISTS `user` (
|
|||||||
);
|
);
|
||||||
|
|
||||||
-- user_setting
|
-- user_setting
|
||||||
CREATE TABLE IF NOT EXISTS `user_setting` (
|
CREATE TABLE `user_setting` (
|
||||||
`user_id` int NOT NULL,
|
`user_id` int NOT NULL,
|
||||||
`key` varchar(255) NOT NULL,
|
`key` varchar(255) NOT NULL,
|
||||||
`value` text NOT NULL,
|
`value` text NOT NULL,
|
||||||
UNIQUE KEY `user_id` (`user_id`,`key`)
|
UNIQUE KEY `user_id` (`user_id`,`key`)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- memo
|
||||||
|
CREATE TABLE `memo` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`creator_id` int NOT NULL,
|
||||||
|
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`updated_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`row_status` varchar(255) NOT NULL DEFAULT 'NORMAL',
|
||||||
|
`content` text NOT NULL,
|
||||||
|
`visibility` varchar(255) NOT NULL DEFAULT 'PRIVATE',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `creator_id` (`creator_id`),
|
||||||
|
KEY `visibility` (`visibility`),
|
||||||
|
CONSTRAINT `memo_chk_1` CHECK ((`row_status` in (_utf8mb4'NORMAL',_utf8mb4'ARCHIVED'))),
|
||||||
|
CONSTRAINT `memo_chk_2` CHECK ((`visibility` in (_utf8mb4'PUBLIC',_utf8mb4'PROTECTED',_utf8mb4'PRIVATE')))
|
||||||
|
);
|
||||||
|
|
||||||
|
-- memo_organizer
|
||||||
|
CREATE TABLE `memo_organizer` (
|
||||||
|
`memo_id` int NOT NULL,
|
||||||
|
`user_id` int NOT NULL,
|
||||||
|
`pinned` int NOT NULL DEFAULT '0',
|
||||||
|
UNIQUE KEY `memo_id` (`memo_id`,`user_id`),
|
||||||
|
CONSTRAINT `memo_organizer_chk_1` CHECK ((`pinned` in (0,1)))
|
||||||
|
);
|
||||||
|
|
||||||
|
-- memo_relation
|
||||||
|
CREATE TABLE `memo_relation` (
|
||||||
|
`memo_id` int NOT NULL,
|
||||||
|
`related_memo_id` int NOT NULL,
|
||||||
|
`type` varchar(256) NOT NULL,
|
||||||
|
UNIQUE KEY `memo_id` (`memo_id`,`related_memo_id`,`type`)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- resource
|
||||||
|
CREATE TABLE `resource` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`creator_id` int NOT NULL,
|
||||||
|
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`updated_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`filename` text NOT NULL,
|
||||||
|
`blob` blob,
|
||||||
|
`external_link` text NOT NULL,
|
||||||
|
`type` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`size` int NOT NULL DEFAULT '0',
|
||||||
|
`internal_path` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`memo_id` int DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `creator_id` (`creator_id`),
|
||||||
|
KEY `memo_id` (`memo_id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- tag
|
||||||
|
CREATE TABLE `tag` (
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`creator_id` int NOT NULL,
|
||||||
|
UNIQUE KEY `name` (`name`,`creator_id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- activity
|
||||||
|
CREATE TABLE `activity` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`creator_id` int NOT NULL,
|
||||||
|
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`type` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`level` varchar(255) NOT NULL DEFAULT 'INFO',
|
||||||
|
`payload` text NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
CONSTRAINT `activity_chk_1` CHECK ((`level` in (_utf8mb4'INFO',_utf8mb4'WARN',_utf8mb4'ERROR')))
|
||||||
|
);
|
||||||
|
|
||||||
|
-- storage
|
||||||
|
CREATE TABLE `storage` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(256) NOT NULL,
|
||||||
|
`type` varchar(256) NOT NULL,
|
||||||
|
`config` text NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- idp
|
||||||
|
CREATE TABLE `idp` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` text NOT NULL,
|
||||||
|
`type` text NOT NULL,
|
||||||
|
`identifier_filter` varchar(256) NOT NULL DEFAULT '',
|
||||||
|
`config` text NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
);
|
||||||
|
143
store/mysql/migration/prod/LATEST__SCHEMA.sql
Normal file
143
store/mysql/migration/prod/LATEST__SCHEMA.sql
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
-- drop all tables first
|
||||||
|
DROP TABLE IF EXISTS `migration_history`;
|
||||||
|
DROP TABLE IF EXISTS `system_setting`;
|
||||||
|
DROP TABLE IF EXISTS `user`;
|
||||||
|
DROP TABLE IF EXISTS `user_setting`;
|
||||||
|
DROP TABLE IF EXISTS `memo`;
|
||||||
|
DROP TABLE IF EXISTS `memo_organizer`;
|
||||||
|
DROP TABLE IF EXISTS `memo_relation`;
|
||||||
|
DROP TABLE IF EXISTS `resource`;
|
||||||
|
DROP TABLE IF EXISTS `tag`;
|
||||||
|
DROP TABLE IF EXISTS `activity`;
|
||||||
|
DROP TABLE IF EXISTS `storage`;
|
||||||
|
DROP TABLE IF EXISTS `idp`;
|
||||||
|
|
||||||
|
-- migration_history
|
||||||
|
CREATE TABLE `migration_history` (
|
||||||
|
`version` varchar(255) NOT NULL,
|
||||||
|
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`version`)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- system_setting
|
||||||
|
CREATE TABLE `system_setting` (
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`value` text NOT NULL,
|
||||||
|
`description` text NOT NULL,
|
||||||
|
PRIMARY KEY (`name`)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- user
|
||||||
|
CREATE TABLE `user` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`updated_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`row_status` varchar(255) NOT NULL DEFAULT 'NORMAL',
|
||||||
|
`username` varchar(255) NOT NULL,
|
||||||
|
`role` varchar(255) NOT NULL DEFAULT 'USER',
|
||||||
|
`email` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`nickname` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`password_hash` varchar(255) NOT NULL,
|
||||||
|
`avatar_url` text NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `username` (`username`),
|
||||||
|
CONSTRAINT `user_chk_1` CHECK ((`row_status` in (_utf8mb4'NORMAL',_utf8mb4'ARCHIVED'))),
|
||||||
|
CONSTRAINT `user_chk_2` CHECK ((`role` in (_utf8mb4'HOST',_utf8mb4'ADMIN',_utf8mb4'USER')))
|
||||||
|
);
|
||||||
|
|
||||||
|
-- user_setting
|
||||||
|
CREATE TABLE `user_setting` (
|
||||||
|
`user_id` int NOT NULL,
|
||||||
|
`key` varchar(255) NOT NULL,
|
||||||
|
`value` text NOT NULL,
|
||||||
|
UNIQUE KEY `user_id` (`user_id`,`key`)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- memo
|
||||||
|
CREATE TABLE `memo` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`creator_id` int NOT NULL,
|
||||||
|
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`updated_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`row_status` varchar(255) NOT NULL DEFAULT 'NORMAL',
|
||||||
|
`content` text NOT NULL,
|
||||||
|
`visibility` varchar(255) NOT NULL DEFAULT 'PRIVATE',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `creator_id` (`creator_id`),
|
||||||
|
KEY `visibility` (`visibility`),
|
||||||
|
CONSTRAINT `memo_chk_1` CHECK ((`row_status` in (_utf8mb4'NORMAL',_utf8mb4'ARCHIVED'))),
|
||||||
|
CONSTRAINT `memo_chk_2` CHECK ((`visibility` in (_utf8mb4'PUBLIC',_utf8mb4'PROTECTED',_utf8mb4'PRIVATE')))
|
||||||
|
);
|
||||||
|
|
||||||
|
-- memo_organizer
|
||||||
|
CREATE TABLE `memo_organizer` (
|
||||||
|
`memo_id` int NOT NULL,
|
||||||
|
`user_id` int NOT NULL,
|
||||||
|
`pinned` int NOT NULL DEFAULT '0',
|
||||||
|
UNIQUE KEY `memo_id` (`memo_id`,`user_id`),
|
||||||
|
CONSTRAINT `memo_organizer_chk_1` CHECK ((`pinned` in (0,1)))
|
||||||
|
);
|
||||||
|
|
||||||
|
-- memo_relation
|
||||||
|
CREATE TABLE `memo_relation` (
|
||||||
|
`memo_id` int NOT NULL,
|
||||||
|
`related_memo_id` int NOT NULL,
|
||||||
|
`type` varchar(256) NOT NULL,
|
||||||
|
UNIQUE KEY `memo_id` (`memo_id`,`related_memo_id`,`type`)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- resource
|
||||||
|
CREATE TABLE `resource` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`creator_id` int NOT NULL,
|
||||||
|
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`updated_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`filename` text NOT NULL,
|
||||||
|
`blob` blob,
|
||||||
|
`external_link` text NOT NULL,
|
||||||
|
`type` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`size` int NOT NULL DEFAULT '0',
|
||||||
|
`internal_path` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`memo_id` int DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `creator_id` (`creator_id`),
|
||||||
|
KEY `memo_id` (`memo_id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- tag
|
||||||
|
CREATE TABLE `tag` (
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`creator_id` int NOT NULL,
|
||||||
|
UNIQUE KEY `name` (`name`,`creator_id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- activity
|
||||||
|
CREATE TABLE `activity` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`creator_id` int NOT NULL,
|
||||||
|
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`type` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`level` varchar(255) NOT NULL DEFAULT 'INFO',
|
||||||
|
`payload` text NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
CONSTRAINT `activity_chk_1` CHECK ((`level` in (_utf8mb4'INFO',_utf8mb4'WARN',_utf8mb4'ERROR')))
|
||||||
|
);
|
||||||
|
|
||||||
|
-- storage
|
||||||
|
CREATE TABLE `storage` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(256) NOT NULL,
|
||||||
|
`type` varchar(256) NOT NULL,
|
||||||
|
`config` text NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- idp
|
||||||
|
CREATE TABLE `idp` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` text NOT NULL,
|
||||||
|
`type` text NOT NULL,
|
||||||
|
`identifier_filter` varchar(256) NOT NULL DEFAULT '',
|
||||||
|
`config` text NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
);
|
@ -18,13 +18,17 @@ type Driver struct {
|
|||||||
func NewDriver(profile *profile.Profile) (store.Driver, error) {
|
func NewDriver(profile *profile.Profile) (store.Driver, error) {
|
||||||
db, err := sql.Open("mysql", profile.DSN)
|
db, err := sql.Open("mysql", profile.DSN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrapf(err, "failed to open db: %s", profile.DSN)
|
||||||
}
|
}
|
||||||
|
|
||||||
driver := Driver{db: db, profile: profile}
|
driver := Driver{db: db, profile: profile}
|
||||||
return &driver, nil
|
return &driver, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Driver) GetDB() *sql.DB {
|
||||||
|
return d.db
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Driver) Vacuum(ctx context.Context) error {
|
func (d *Driver) Vacuum(ctx context.Context) error {
|
||||||
tx, err := d.db.BeginTx(ctx, nil)
|
tx, err := d.db.BeginTx(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,3 +1,17 @@
|
|||||||
|
-- drop all tables first
|
||||||
|
DROP TABLE IF EXISTS migration_history;
|
||||||
|
DROP TABLE IF EXISTS system_setting;
|
||||||
|
DROP TABLE IF EXISTS user;
|
||||||
|
DROP TABLE IF EXISTS user_setting;
|
||||||
|
DROP TABLE IF EXISTS memo;
|
||||||
|
DROP TABLE IF EXISTS memo_organizer;
|
||||||
|
DROP TABLE IF EXISTS memo_relation;
|
||||||
|
DROP TABLE IF EXISTS resource;
|
||||||
|
DROP TABLE IF EXISTS tag;
|
||||||
|
DROP TABLE IF EXISTS activity;
|
||||||
|
DROP TABLE IF EXISTS storage;
|
||||||
|
DROP TABLE IF EXISTS idp;
|
||||||
|
|
||||||
-- migration_history
|
-- migration_history
|
||||||
CREATE TABLE migration_history (
|
CREATE TABLE migration_history (
|
||||||
version TEXT NOT NULL PRIMARY KEY,
|
version TEXT NOT NULL PRIMARY KEY,
|
||||||
@ -59,6 +73,14 @@ CREATE TABLE memo_organizer (
|
|||||||
UNIQUE(memo_id, user_id)
|
UNIQUE(memo_id, user_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- memo_relation
|
||||||
|
CREATE TABLE memo_relation (
|
||||||
|
memo_id INTEGER NOT NULL,
|
||||||
|
related_memo_id INTEGER NOT NULL,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
UNIQUE(memo_id, related_memo_id, type)
|
||||||
|
);
|
||||||
|
|
||||||
-- resource
|
-- resource
|
||||||
CREATE TABLE resource (
|
CREATE TABLE resource (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
@ -111,11 +133,3 @@ CREATE TABLE idp (
|
|||||||
identifier_filter TEXT NOT NULL DEFAULT '',
|
identifier_filter TEXT NOT NULL DEFAULT '',
|
||||||
config TEXT NOT NULL DEFAULT '{}'
|
config TEXT NOT NULL DEFAULT '{}'
|
||||||
);
|
);
|
||||||
|
|
||||||
-- memo_relation
|
|
||||||
CREATE TABLE memo_relation (
|
|
||||||
memo_id INTEGER NOT NULL,
|
|
||||||
related_memo_id INTEGER NOT NULL,
|
|
||||||
type TEXT NOT NULL,
|
|
||||||
UNIQUE(memo_id, related_memo_id, type)
|
|
||||||
);
|
|
||||||
|
@ -49,6 +49,10 @@ func NewDriver(profile *profile.Profile) (store.Driver, error) {
|
|||||||
return &driver, nil
|
return &driver, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Driver) GetDB() *sql.DB {
|
||||||
|
return d.db
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Driver) Vacuum(ctx context.Context) error {
|
func (d *Driver) Vacuum(ctx context.Context) error {
|
||||||
tx, err := d.db.BeginTx(ctx, nil)
|
tx, err := d.db.BeginTx(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
13
test/store/README.md
Normal file
13
test/store/README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Store tests
|
||||||
|
|
||||||
|
## How to test store with MySQL?
|
||||||
|
|
||||||
|
1. Create a database in your MySQL server.
|
||||||
|
2. Run the following command with two environment variables set:
|
||||||
|
|
||||||
|
```go
|
||||||
|
DRIVER=mysql DSN=root@/memos_test go test -v ./test/store/...
|
||||||
|
```
|
||||||
|
|
||||||
|
- `DRIVER` should be set to `mysql`.
|
||||||
|
- `DSN` should be set to the DSN of your MySQL server.
|
@ -5,17 +5,29 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/usememos/memos/store"
|
// mysql driver.
|
||||||
"github.com/usememos/memos/store/sqlite"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"github.com/usememos/memos/test"
|
|
||||||
|
|
||||||
// sqlite driver.
|
// sqlite driver.
|
||||||
_ "modernc.org/sqlite"
|
_ "modernc.org/sqlite"
|
||||||
|
|
||||||
|
"github.com/usememos/memos/store"
|
||||||
|
"github.com/usememos/memos/store/mysql"
|
||||||
|
"github.com/usememos/memos/store/sqlite"
|
||||||
|
"github.com/usememos/memos/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewTestingStore(ctx context.Context, t *testing.T) *store.Store {
|
func NewTestingStore(ctx context.Context, t *testing.T) *store.Store {
|
||||||
profile := test.GetTestingProfile(t)
|
profile := test.GetTestingProfile(t)
|
||||||
driver, err := sqlite.NewDriver(profile)
|
var driver store.Driver
|
||||||
|
var err error
|
||||||
|
switch profile.Driver {
|
||||||
|
case "sqlite":
|
||||||
|
driver, err = sqlite.NewDriver(profile)
|
||||||
|
case "mysql":
|
||||||
|
driver, err = mysql.NewDriver(profile)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unknown db driver: %s", profile.Driver))
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("failed to create db driver, error: %+v\n", err)
|
fmt.Printf("failed to create db driver, error: %+v\n", err)
|
||||||
}
|
}
|
||||||
|
@ -14,13 +14,13 @@ func TestUserSettingStore(t *testing.T) {
|
|||||||
ts := NewTestingStore(ctx, t)
|
ts := NewTestingStore(ctx, t)
|
||||||
user, err := createTestingHostUser(ctx, ts)
|
user, err := createTestingHostUser(ctx, ts)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
testSetting, err := ts.UpsertUserSetting(ctx, &store.UserSetting{
|
_, err = ts.UpsertUserSetting(ctx, &store.UserSetting{
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
Key: "test_key",
|
Key: "test_key",
|
||||||
Value: "test_value",
|
Value: "test_value",
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
localeSetting, err := ts.UpsertUserSetting(ctx, &store.UserSetting{
|
_, err = ts.UpsertUserSetting(ctx, &store.UserSetting{
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
Key: "locale",
|
Key: "locale",
|
||||||
Value: "zh",
|
Value: "zh",
|
||||||
@ -29,6 +29,4 @@ func TestUserSettingStore(t *testing.T) {
|
|||||||
list, err := ts.ListUserSettings(ctx, &store.FindUserSetting{})
|
list, err := ts.ListUserSettings(ctx, &store.FindUserSetting{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 2, len(list))
|
require.Equal(t, 2, len(list))
|
||||||
require.Equal(t, testSetting, list[0])
|
|
||||||
require.Equal(t, localeSetting, list[1])
|
|
||||||
}
|
}
|
||||||
|
18
test/test.go
18
test/test.go
@ -3,6 +3,7 @@ package test
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/usememos/memos/server/profile"
|
"github.com/usememos/memos/server/profile"
|
||||||
@ -27,11 +28,26 @@ func GetTestingProfile(t *testing.T) *profile.Profile {
|
|||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
mode := "dev"
|
mode := "dev"
|
||||||
port := getUnusedPort()
|
port := getUnusedPort()
|
||||||
|
driver := getDriverFromEnv()
|
||||||
|
dsn := os.Getenv("DSN")
|
||||||
|
if driver == "sqlite" {
|
||||||
|
dsn = fmt.Sprintf("%s/memos_%s.db", dir, mode)
|
||||||
|
}
|
||||||
|
println("dsn", dsn, driver)
|
||||||
return &profile.Profile{
|
return &profile.Profile{
|
||||||
Mode: mode,
|
Mode: mode,
|
||||||
Port: port,
|
Port: port,
|
||||||
Data: dir,
|
Data: dir,
|
||||||
DSN: fmt.Sprintf("%s/memos_%s.db", dir, mode),
|
DSN: dsn,
|
||||||
|
Driver: driver,
|
||||||
Version: version.GetCurrentVersion(mode),
|
Version: version.GetCurrentVersion(mode),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDriverFromEnv() string {
|
||||||
|
driver := os.Getenv("DRIVER")
|
||||||
|
if driver == "" {
|
||||||
|
driver = "sqlite"
|
||||||
|
}
|
||||||
|
return driver
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user