基于SQL的关系型数据库的Storage的通用实现。
go get -u github.com/storage-lock/go-sql-based-storage把基于SQL构建Storage的流程的公共部分抽象出来,这样对于所有支持SQL的存储设备来说就只需要实现不同的部分就可以了,不同的部分使用SqlProvider来封装不同的SQL方言。
创建SqlBasedStorage的时候需要提供一些上下文参数,是通过这个Options来传递的:
type SqlBasedStorageOptions struct {
SqlProvider SqlProvider
ConnectionManager storage.ConnectionManager[*sql.DB]
TableFullName string
}用于封装不同的SQL方言:
package sql_based_storage
import (
"context"
"github.com/storage-lock/go-storage"
)
// SqlProvider 用于提供各种SQl方言
type SqlProvider interface {
// CreateTableSql 构造创建存储锁的表的sql语句以及参数
CreateTableSql(ctx context.Context, tableFullName string) (string, []any)
// UpdateWithVersionSql 构造根据版本更新锁信息的sql
UpdateWithVersionSql(ctx context.Context, tableFullName string, lockId string, exceptedVersion, newVersion storage.Version, lockInformation *storage.LockInformation) (string, []any)
// CreateWithVersionSql 构造根据版本创建锁信息的sql
CreateWithVersionSql(ctx context.Context, tableFullName string, lockId string, version storage.Version, lockInformation *storage.LockInformation) (string, []any)
// DeleteWithVersionSql 构造根据版本删除锁信息的sql
DeleteWithVersionSql(ctx context.Context, tableFullName string, lockId string, exceptedVersion storage.Version, lockInformation *storage.LockInformation) (string, []any)
// NowTimestampSql 构造获取锁的unix mil时间戳的sql
NowTimestampSql(ctx context.Context, tableFullName string) (string, []any)
// SelectLockInformationJsonStringSql 构造根据 lock_id 查询锁信息的sql
SelectLockInformationJsonStringSql(ctx context.Context, tableFullName string, lockId string) (string, []any)
// ListLockInformationJsonStringSql 提供列出所有的锁的json string的sql
ListLockInformationJsonStringSql(ctx context.Context, tableFullName string) (string, []any)
}对SqlProvider的sql97实现。
创建你自己的Storage,内嵌*sql_based_storage.SqlBasedStorage,只覆写必要的方法 :
type FooStorage struct {
*sql_based_storage.SqlBasedStorage
}
var _ storage.Storage = &FooStorage{}
func NewFooStorage(manager storage.ConnectionManager[*sql.DB]) (*FooStorage, error) {
options := sql_based_storage.NewSqlBasedStorageOptions().SetConnectionManager(manager)
storage, err := sql_based_storage.NewSqlBasedStorage(options)
if err != nil {
return nil, err
}
return &FooStorage{
SqlBasedStorage: storage,
}, nil
}
func (x *FooStorage) GetName() string {
return "foo-storage"
}然后实现自己的sql方言,可以从SqlProvider从头开始写,也可以内嵌Sql97Provider只覆写必要的方法:
type FooSqlProvider struct {
sql_based_storage.Sql97Provider
}
var _ sql_based_storage.SqlProvider = &FooSqlProvider{}
func (x *FooSqlProvider) NowTimestampSql(ctx context.Context, tableFullName string) (string, []any) {
return "SELECT NOW()", nil
}最后使用的话:
func main() {
db, err := sql.Open("mysql", "xxx")
if err != nil {
panic(err)
}
connectionManager := storage.NewFixedSqlDBConnectionManager(db)
fooStorage, err := NewFooStorage(connectionManager)
if err != nil {
panic(err)
}
fmt.Println(fooStorage.GetName())
}