Support explicit SQLite path at Store level

This commit is contained in:
Philip O'Toole
2021-08-25 12:54:34 -04:00
parent 81a234abd0
commit 105a894fe5
4 changed files with 57 additions and 7 deletions

View File

@@ -198,6 +198,7 @@ func main() {
}
dbConf := store.NewDBConfig(!onDisk)
dbConf.FKConstraints = fkConstraints
dbConf.OnDiskPath = onDiskPath
str := store.New(raftTn, &store.StoreConfig{
DBConf: dbConf,

View File

@@ -5,6 +5,9 @@ type DBConfig struct {
// Whether the database is in-memory only.
Memory bool `json:"memory"`
// SQLite on-disk path
OnDiskPath string `json:"on_disk_path,omitempty"`
// Enforce Foreign Key constraints
FKConstraints bool `json:"fk_constraints"`
}

View File

@@ -185,12 +185,17 @@ func New(ln Listener, c *StoreConfig) *Store {
logger = log.New(os.Stderr, "[store] ", log.LstdFlags)
}
dbPath := filepath.Join(c.Dir, sqliteFile)
if c.DBConf.OnDiskPath != "" {
dbPath = c.DBConf.OnDiskPath
}
return &Store{
ln: ln,
raftDir: c.Dir,
raftID: c.ID,
dbConf: c.DBConf,
dbPath: filepath.Join(c.Dir, sqliteFile),
dbPath: dbPath,
reqMarshaller: command.NewRequestMarshaler(),
logger: logger,
ApplyTimeout: applyTimeout,
@@ -209,7 +214,7 @@ func (s *Store) Open(enableBootstrap bool) error {
if !s.dbConf.Memory {
dbType = "on-disk"
}
s.logger.Printf("configured for an %s database", dbType)
s.logger.Printf("configured for an %s database at %s", dbType, s.dbPath)
s.logger.Printf("ensuring directory at %s exists", s.raftDir)
err := os.MkdirAll(s.raftDir, 0755)

View File

@@ -226,6 +226,7 @@ func Test_SingleNodeExecuteQueryTx(t *testing.T) {
}
}
// Test_SingleNodeInMemFK tests that basic foreign-key related functionality works.
func Test_SingleNodeInMemFK(t *testing.T) {
s := mustNewStoreFK(true)
defer os.RemoveAll(s.Path())
@@ -251,6 +252,41 @@ func Test_SingleNodeInMemFK(t *testing.T) {
}
}
// Test_SingleNodeSQLitePath ensures that basic functionality works when the SQLite database path
// is explicitly specificed.
func Test_SingleNodeSQLitePath(t *testing.T) {
s := mustNewStoreSQLitePath()
defer os.RemoveAll(s.Path())
if err := s.Open(true); err != nil {
t.Fatalf("failed to open single-node store: %s", err.Error())
}
defer s.Close(true)
s.WaitForLeader(10 * time.Second)
er := executeRequestFromStrings([]string{
`CREATE TABLE foo (id INTEGER NOT NULL PRIMARY KEY, name TEXT)`,
`INSERT INTO foo(id, name) VALUES(1, "fiona")`,
}, false, false)
_, err := s.Execute(er)
if err != nil {
t.Fatalf("failed to execute on single node: %s", err.Error())
}
qr := queryRequestFromString("SELECT * FROM foo", false, false)
qr.Level = command.QueryRequest_QUERY_REQUEST_LEVEL_NONE
r, err := s.Query(qr)
if err != nil {
t.Fatalf("failed to query single node: %s", err.Error())
}
if exp, got := `["id","name"]`, asJSON(r[0].Columns); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
if exp, got := `[[1,"fiona"]]`, asJSON(r[0].Values); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
}
func Test_SingleNodeBackupBinary(t *testing.T) {
t.Parallel()
@@ -1191,14 +1227,15 @@ func Test_State(t *testing.T) {
}
}
func mustNewStoreAtPath(path string, inmem, fk bool) *Store {
func mustNewStoreAtPaths(dataPath, sqlitePath string, inmem, fk bool) *Store {
cfg := NewDBConfig(inmem)
cfg.FKConstraints = fk
cfg.OnDiskPath = sqlitePath
s := New(mustMockLister("localhost:0"), &StoreConfig{
DBConf: cfg,
Dir: path,
ID: path, // Could be any unique string.
Dir: dataPath,
ID: dataPath, // Could be any unique string.
})
if s == nil {
panic("failed to create new store")
@@ -1207,11 +1244,15 @@ func mustNewStoreAtPath(path string, inmem, fk bool) *Store {
}
func mustNewStore(inmem bool) *Store {
return mustNewStoreAtPath(mustTempDir(), inmem, false)
return mustNewStoreAtPaths(mustTempDir(), "", inmem, false)
}
func mustNewStoreFK(inmem bool) *Store {
return mustNewStoreAtPath(mustTempDir(), inmem, true)
return mustNewStoreAtPaths(mustTempDir(), "", inmem, true)
}
func mustNewStoreSQLitePath() *Store {
return mustNewStoreAtPaths(mustTempDir(), filepath.Join(mustTempDir(), "explicit-path.db"), false, true)
}
type mockSnapshotSink struct {