-
-
Notifications
You must be signed in to change notification settings - Fork 31
Update NewPool logic in regards to poolsize > 1 with inmemory set #125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
87ed9fc
72a53a5
8207421
90d5052
e090ab4
2719375
9d87a78
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ package sqlitex | |
import ( | ||
"context" | ||
"fmt" | ||
"strings" | ||
"sync" | ||
|
||
"zombiezen.com/go/sqlite" | ||
|
@@ -69,11 +70,18 @@ func Open(uri string, flags sqlite.OpenFlags, poolSize int) (pool *Pool, err err | |
|
||
// NewPool opens a fixed-size pool of SQLite connections. | ||
func NewPool(uri string, opts PoolOptions) (pool *Pool, err error) { | ||
if uri == ":memory:" { | ||
return nil, strerror{msg: `sqlite: ":memory:" does not work with multiple connections, use "file::memory:?mode=memory&cache=shared"`} | ||
poolSize := opts.PoolSize | ||
|
||
if poolSize != 1 { | ||
uriLower := strings.ToLower(uri) | ||
inMemory := uri == ":memory:" || opts.Flags&sqlite.OpenMemory != 0 | ||
sharedCache := strings.Contains(uriLower, "cache=shared") || opts.Flags&sqlite.OpenSharedCache != 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Although unlikely, the |
||
|
||
if inMemory && !sharedCache { | ||
return nil, strerror{msg: `sqlite: uri==":memory:" or flag sqlite.OpenMemory does not work with multiple connections, use "file::memory:?mode=memory&cache=shared"`} | ||
} | ||
} | ||
|
||
poolSize := opts.PoolSize | ||
if poolSize < 1 { | ||
poolSize = 10 | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -95,6 +95,72 @@ func TestPool(t *testing.T) { | |
stmt.Reset() | ||
} | ||
|
||
func TestInvalidPoolOptions(t *testing.T) { | ||
dir, err := os.MkdirTemp("", "sqlite-test-") | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
defer os.RemoveAll(dir) | ||
|
||
dbFile := filepath.Join(dir, "awal.db") | ||
dbFileShared := filepath.Join(dir, "awal.db?cache=shared") | ||
|
||
tests := []struct { | ||
name string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Names aren't being used and aren't helpful here. Remove, please. |
||
uri string | ||
flags sqlite.OpenFlags | ||
wantErr bool | ||
}{ | ||
{ | ||
name: "Error: uri is set to :memory: with poolsize > 1", | ||
uri: ":memory:", | ||
flags: sqlite.OpenReadWrite | sqlite.OpenCreate | sqlite.OpenURI, | ||
wantErr: true, | ||
}, | ||
{ | ||
name: "Error: OpenMemory flag set with poolsize > 1", | ||
uri: dbFile, | ||
flags: sqlite.OpenMemory | sqlite.OpenReadWrite | sqlite.OpenCreate | sqlite.OpenURI, | ||
wantErr: true, | ||
}, | ||
{ | ||
name: "Success: uri is :memory: but cache is shared via flag with poolsize > 1", | ||
uri: ":memory:", | ||
flags: sqlite.OpenSharedCache | sqlite.OpenReadWrite | sqlite.OpenCreate | sqlite.OpenURI, | ||
}, | ||
{ | ||
name: "Succes: uri has cached=shared and sqlite.OpenMemory flag is set with poolsize > 1", | ||
uri: dbFileShared, | ||
flags: sqlite.OpenMemory | sqlite.OpenReadWrite | sqlite.OpenCreate | sqlite.OpenURI, | ||
}, | ||
{ | ||
name: "Success: uri is dbFile, flag is set to sqlite.OpenMemory && sqlite.OpenSharedCache with poolsize > 1", | ||
uri: dbFile, | ||
flags: sqlite.OpenMemory | sqlite.OpenReadWrite | sqlite.OpenCreate | sqlite.OpenSharedCache | sqlite.OpenURI, | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
dbpool, err := sqlitex.NewPool(test.uri, sqlitex.PoolOptions{ | ||
Flags: test.flags, | ||
PoolSize: 2, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should vary the pool size for some of these tests. |
||
}) | ||
if err == nil { | ||
dbpool.Close() | ||
} | ||
|
||
switch { | ||
case err == nil && test.wantErr: | ||
t.Errorf("TestInvalidPoolOptions(%s): got err == nil, want err != nil", test.name) | ||
continue | ||
case err != nil && !test.wantErr: | ||
t.Errorf("TestInvalidPoolOptions(%s): got err == %s, want err == nil", test.name, err) | ||
continue | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For error tests like these, I like including a case that logs the error message in successful cases without failing. This allows manual inspection to see whether there's a case that's failing for an unrelated error cause. |
||
} | ||
|
||
} | ||
|
||
const insertCount = 120 | ||
|
||
func testInsert(t *testing.T, id string, dbpool *sqlitex.Pool) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mode=memory
is another way this condition can be triggered.