parent
d10e3dcd4a
commit
fd091c5c4b
|
@ -0,0 +1,85 @@
|
|||
package sqkv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// OpenMode for opening a DB
|
||||
type OpenMode string
|
||||
|
||||
const (
|
||||
OpenModeReadOnly OpenMode = "ro"
|
||||
OpenModeReadWrite OpenMode = "rw"
|
||||
OpenModeReadWriteCreate OpenMode = "rwc"
|
||||
OpenModeMemory OpenMode = "memory"
|
||||
)
|
||||
|
||||
// OpenCache for setting the cache mode
|
||||
type OpenCache string
|
||||
|
||||
const (
|
||||
OpenCacheShared OpenCache = "shared"
|
||||
OpenCachePrivate OpenCache = "private"
|
||||
)
|
||||
|
||||
// OpenJournalMode for setting the journal mode
|
||||
type OpenJournalMode string
|
||||
|
||||
const (
|
||||
OpenJournalModeDelete = "delete"
|
||||
OpenJournalModeTruncate = "truncate"
|
||||
OpenJournalModePersist = "persist"
|
||||
OpenJournalModeMemory = "memory"
|
||||
OpenJournalModeWAL = "wal"
|
||||
OpenJournalModeOff = "off"
|
||||
)
|
||||
|
||||
// OpenConfig is a configuration for opening a DB
|
||||
type OpenConfig struct {
|
||||
Mode OpenMode
|
||||
Cache OpenCache
|
||||
JournalMode OpenJournalMode
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer
|
||||
func (oc OpenConfig) String() string {
|
||||
var opts []string
|
||||
if oc.Mode != "" {
|
||||
opts = append(opts, "mode="+string(oc.Mode))
|
||||
}
|
||||
if oc.Cache != "" {
|
||||
opts = append(opts, "cache="+string(oc.Cache))
|
||||
}
|
||||
if oc.JournalMode != "" {
|
||||
opts = append(opts, fmt.Sprintf("_pragma=journal_mode(%s)", oc.JournalMode))
|
||||
}
|
||||
if len(opts) == 0 {
|
||||
return ""
|
||||
}
|
||||
return "?" + strings.Join(opts, "&")
|
||||
}
|
||||
|
||||
// OpenOption is a func for setting open config values
|
||||
type OpenOption func(*OpenConfig)
|
||||
|
||||
// WithMode sets the mode for opening the DB
|
||||
func WithMode(mode OpenMode) OpenOption {
|
||||
return func(oc *OpenConfig) {
|
||||
oc.Mode = mode
|
||||
}
|
||||
}
|
||||
|
||||
// WithCache sets the cache for opening the DB
|
||||
func WithCache(cache OpenCache) OpenOption {
|
||||
return func(oc *OpenConfig) {
|
||||
oc.Cache = cache
|
||||
}
|
||||
}
|
||||
|
||||
// WithJournalMode sets the journal mode for the DB
|
||||
func WithJournalMode(journalMode OpenJournalMode) OpenOption {
|
||||
return func(oc *OpenConfig) {
|
||||
oc.JournalMode = journalMode
|
||||
}
|
||||
}
|
20
sqkv.go
20
sqkv.go
|
@ -1,6 +1,7 @@
|
|||
package sqkv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
@ -14,8 +15,13 @@ type DB struct {
|
|||
}
|
||||
|
||||
// Open opens (or creates) a new SQKV database
|
||||
func Open(path string) (*DB, error) {
|
||||
dsn := fmt.Sprintf("file:%s?cache=shared&mode=rwc", path)
|
||||
func Open(path string, opts ...OpenOption) (*DB, error) {
|
||||
cfg := &OpenConfig{}
|
||||
for _, opt := range opts {
|
||||
opt(cfg)
|
||||
}
|
||||
|
||||
dsn := fmt.Sprintf("file:%s%s", path, cfg)
|
||||
db, err := sql.Open("sqlite", dsn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -28,6 +34,16 @@ func Open(path string) (*DB, error) {
|
|||
return sqkv, err
|
||||
}
|
||||
|
||||
// Close closes the connection to the database
|
||||
func (d *DB) Close() error {
|
||||
return d.db.Close()
|
||||
}
|
||||
|
||||
// Conn returns a direct DB connection
|
||||
func (d *DB) Conn() (*sql.Conn, error) {
|
||||
return d.db.Conn(context.Background())
|
||||
}
|
||||
|
||||
// Get returns a value from the default bucket
|
||||
func (d *DB) Get(key string) (string, error) {
|
||||
b, err := d.Bucket(DefaultBucket)
|
||||
|
|
29
sqkv_test.go
29
sqkv_test.go
|
@ -2,6 +2,7 @@ package sqkv
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
|
@ -16,6 +17,7 @@ func TestDefault(t *testing.T) {
|
|||
|
||||
db, err := Open(dbPath)
|
||||
assert.NoErr(err) // Should create database
|
||||
defer db.Close()
|
||||
|
||||
err = db.Put("foo", "bar")
|
||||
assert.NoErr(err) // Should put kv
|
||||
|
@ -39,6 +41,7 @@ func TestBucket(t *testing.T) {
|
|||
|
||||
db, err := Open(dbPath)
|
||||
assert.NoErr(err) // Should create database
|
||||
defer db.Close()
|
||||
|
||||
_, err = db.Bucket("honk")
|
||||
assert.True(errors.Is(err, ErrBucketDoesNotExist)) // Bucket does not exist; should error
|
||||
|
@ -65,3 +68,29 @@ func TestBucket(t *testing.T) {
|
|||
_, err = b.Get("foo")
|
||||
assert.True(errors.Is(err, ErrKeyDoesNotExist))
|
||||
}
|
||||
|
||||
func TestOptions(t *testing.T) {
|
||||
assert := is.New(t)
|
||||
|
||||
tmp := t.TempDir()
|
||||
dbPath := filepath.Join(tmp, "opt.db")
|
||||
|
||||
_, err := Open(dbPath, WithMode(OpenModeReadOnly))
|
||||
assert.True(err != nil) // Database should not be created
|
||||
|
||||
_, err = Open(dbPath, WithMode(OpenModeReadWrite))
|
||||
assert.True(err != nil) // Database should not be created
|
||||
|
||||
_, err = Open(dbPath, WithMode(OpenModeMemory))
|
||||
assert.NoErr(err) // Database should not be created, but no error
|
||||
_, err = os.Stat(dbPath)
|
||||
assert.True(err != nil) // Database should not be created on disk
|
||||
|
||||
db, err := Open(dbPath, WithJournalMode(OpenJournalModeWAL))
|
||||
defer db.Close()
|
||||
|
||||
var jm string
|
||||
row := db.db.QueryRow("PRAGMA journal_mode")
|
||||
assert.NoErr(row.Scan(&jm)) // Should return PRAGMA result
|
||||
assert.Equal(jm, "wal") // Journal mode should be WAL
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue