From df1e05de5bd91626ebb4e6aedef0dce7327721a9 Mon Sep 17 00:00:00 2001 From: Tycho Andersen Date: Fri, 27 Jan 2017 09:30:25 -0700 Subject: [PATCH] switch rqlite to using cache=shared for in-memory databases This is a little hairy. Looking at things like [1], it's evident that golang's stdlib sql package doesn't work quite correctly with sqlite3's in-memory databases. In particular, the connection pooling causes problems, since there's no way to duplicate a connection to a particular in-memory database. So, we use cache=shared to force everything to point to the same in-memory database. However, this causes some problems (mostly that untill the last connection to this database is closed, the DB is not pruned). So we have to do a little cleanup after ourselves in this case. [1]: https://github.com/mattn/go-sqlite3/issues/204 Signed-off-by: Tycho Andersen --- db/db.go | 2 +- db/db_test.go | 2 +- store/store_test.go | 13 ++++++------- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/db/db.go b/db/db.go index 032006dad9..c37d2184b0 100644 --- a/db/db.go +++ b/db/db.go @@ -81,7 +81,7 @@ func OpenWithDSN(dbPath, dsn string) (*DB, error) { // OpenInMemory opens an in-memory database. func OpenInMemory() (*DB, error) { - return OpenInMemoryWithDSN("") + return OpenInMemoryWithDSN("mode=memory&cache=shared") } // OpenInMemoryWithDSN opens an in-memory database with a specific DSN. diff --git a/db/db_test.go b/db/db_test.go index 5318ae5604..9904105575 100644 --- a/db/db_test.go +++ b/db/db_test.go @@ -67,7 +67,7 @@ func Test_LoadInMemory(t *testing.T) { t.Fatalf("unexpected results for query, expected %s, got %s", exp, got) } - inmem, err := LoadInMemoryWithDSN(path, "") + inmem, err := LoadInMemoryWithDSN(path, "mode=memory&cache=shared") if err != nil { t.Fatalf("failed to create loaded in-memory database: %s", err.Error()) } diff --git a/store/store_test.go b/store/store_test.go index 015eb3bf69..b73d18f91d 100644 --- a/store/store_test.go +++ b/store/store_test.go @@ -216,10 +216,8 @@ func Test_SingleNodeLoad(t *testing.T) { s.WaitForLeader(10 * time.Second) dump := `PRAGMA foreign_keys=OFF; -BEGIN TRANSACTION; CREATE TABLE foo (id integer not null primary key, name text); INSERT INTO "foo" VALUES(1,'fiona'); -COMMIT; ` _, err := s.Execute([]string{dump}, false, false) if err != nil { @@ -250,7 +248,6 @@ func Test_SingleNodeSingleCommandTrigger(t *testing.T) { s.WaitForLeader(10 * time.Second) dump := `PRAGMA foreign_keys=OFF; -BEGIN TRANSACTION; CREATE TABLE foo (id integer primary key asc, name text); INSERT INTO "foo" VALUES(1,'bob'); INSERT INTO "foo" VALUES(2,'alice'); @@ -261,7 +258,6 @@ INSERT INTO "bar" VALUES(2,46); INSERT INTO "bar" VALUES(3,8); CREATE VIEW foobar as select name as Person, Age as age from foo inner join bar on foo.id == bar.nameid; CREATE TRIGGER new_foobar instead of insert on foobar begin insert into foo (name) values (new.Person); insert into bar (nameid, age) values ((select id from foo where name == new.Person), new.Age); end; -COMMIT; ` _, err := s.Execute([]string{dump}, false, false) if err != nil { @@ -289,8 +285,6 @@ func Test_SingleNodeLoadNoStatements(t *testing.T) { s.WaitForLeader(10 * time.Second) dump := `PRAGMA foreign_keys=OFF; -BEGIN TRANSACTION; -COMMIT; ` _, err := s.Execute([]string{dump}, false, false) if err != nil { @@ -681,7 +675,12 @@ func mustNewStore(inmem bool) *Store { path := mustTempDir() defer os.RemoveAll(path) - cfg := NewDBConfig("", inmem) + dsn := "" + if inmem { + dsn = "mode=memory&cache=shared" + } + + cfg := NewDBConfig(dsn, inmem) s := New(&StoreConfig{ DBConf: cfg, Dir: path,