mirror of
https://github.com/logos-storage/nim-datastore.git
synced 2026-08-02 04:43:16 +00:00
make page size configurable in SQLiteDatastore.new
also make cache size and journal mode configurable closes #6 related to status-im/nim-codex#234
This commit is contained in:
parent
2769ce1de2
commit
b0241a7c57
@ -1,3 +1,6 @@
|
||||
import std/math
|
||||
import std/unicode
|
||||
|
||||
import pkg/questionable
|
||||
import pkg/questionable/results
|
||||
import pkg/sqlite3_abi
|
||||
@ -20,6 +23,10 @@ type
|
||||
|
||||
DataProc* = proc(s: RawStmtPtr) {.closure, gcsafe.}
|
||||
|
||||
# https://www.sqlite.org/pragma.html#pragma_journal_mode
|
||||
JournalMode* = enum
|
||||
DELETE, TRUNCATE, PERSIST, MEMORY, WAL, OFF
|
||||
|
||||
NoParams* = tuple # empty tuple
|
||||
|
||||
NoParamsStmt* = SQLiteStmt[NoParams, void]
|
||||
@ -172,9 +179,67 @@ proc sqlite3_column_text_not_null*(
|
||||
|
||||
text
|
||||
|
||||
template journalModePragmaStmt*(env: SQLite): RawStmtPtr =
|
||||
template pageSizePragmaStmt*(env: SQLite, pageSize: Positive): RawStmtPtr =
|
||||
# https://www.sqlite.org/pragma.html#pragma_page_size
|
||||
if not (isPowerOfTwo(pageSize) and pageSize >= 512 and pageSize <= 65536):
|
||||
return failure "pageSize must be a power of two between 512 and 65536 inclusive"
|
||||
|
||||
let
|
||||
s = prepare(env, "PRAGMA journal_mode = WAL;")
|
||||
s1 = prepare(env, "PRAGMA page_size = " & $pageSize & ";")
|
||||
|
||||
s1.dispose
|
||||
|
||||
let
|
||||
s2 = prepare(env, "PRAGMA page_size;")
|
||||
|
||||
if (let x = sqlite3_step(s2); x != SQLITE_ROW):
|
||||
s2.dispose
|
||||
return failure $sqlite3_errstr(x)
|
||||
|
||||
if (let x = sqlite3_column_type(s2, 0); x != SQLITE_INTEGER):
|
||||
s2.dispose
|
||||
return failure $sqlite3_errstr(x)
|
||||
|
||||
let
|
||||
x = sqlite3_column_int(s2, 0)
|
||||
|
||||
if x != pageSize:
|
||||
s2.dispose
|
||||
return failure "Unexpected page_size pragma result: " & $x
|
||||
|
||||
s2
|
||||
|
||||
template cacheSizePragmaStmt*(env: SQLite, cacheSize: int): RawStmtPtr =
|
||||
# https://www.sqlite.org/pragma.html#pragma_cache_size
|
||||
let
|
||||
s1 = prepare(env, "PRAGMA cache_size = " & $cacheSize & ";")
|
||||
|
||||
s1.dispose
|
||||
|
||||
let
|
||||
s2 = prepare(env, "PRAGMA cache_size;")
|
||||
|
||||
if (let x = sqlite3_step(s2); x != SQLITE_ROW):
|
||||
s2.dispose
|
||||
return failure $sqlite3_errstr(x)
|
||||
|
||||
if (let x = sqlite3_column_type(s2, 0); x != SQLITE_INTEGER):
|
||||
s2.dispose
|
||||
return failure $sqlite3_errstr(x)
|
||||
|
||||
let
|
||||
x = sqlite3_column_int(s2, 0)
|
||||
|
||||
if x != cacheSize:
|
||||
s2.dispose
|
||||
return failure "Unexpected cache_size pragma result: " & $x
|
||||
|
||||
s2
|
||||
|
||||
template journalModePragmaStmt*(env: SQLite, mode: JournalMode): RawStmtPtr =
|
||||
# https://www.sqlite.org/pragma.html#pragma_journal_mode
|
||||
let
|
||||
s = prepare(env, "PRAGMA journal_mode = " & $mode & ";")
|
||||
|
||||
if (let x = sqlite3_step(s); x != SQLITE_ROW):
|
||||
s.dispose
|
||||
@ -187,9 +252,9 @@ template journalModePragmaStmt*(env: SQLite): RawStmtPtr =
|
||||
let
|
||||
x = $sqlite3_column_text_not_null(s, 0)
|
||||
|
||||
if not (x in ["memory", "wal"]):
|
||||
if not (x in ["memory", ($mode).toLower]):
|
||||
s.dispose
|
||||
return failure "Invalid pragma result: \"" & x & "\""
|
||||
return failure "Unexpected journal_mode pragma result: \"" & x & "\""
|
||||
|
||||
s
|
||||
|
||||
|
||||
@ -176,13 +176,26 @@ proc new*(
|
||||
T: type SQLiteDatastore,
|
||||
basePath: string,
|
||||
filename = "store" & dbExt,
|
||||
readOnly = false): ?!T =
|
||||
readOnly = false,
|
||||
|
||||
# make it optional to enable WAL with it enabled being the default?
|
||||
|
||||
# make it possible to specify a custom page size?
|
||||
# SQLite's default page_size is 4096 bytes since v3.12.0 (2016-03-29)
|
||||
# https://www.sqlite.org/pragma.html#pragma_page_size
|
||||
# https://www.sqlite.org/intern-v-extern-blob.html
|
||||
# see also: https://www.sqlite.org/intern-v-extern-blob.html
|
||||
pageSize: Positive = 4096,
|
||||
|
||||
# SQLite's default cache_size is -2000 since v3.12.0 (2016-03-29)
|
||||
# a negative value translates to approximately "abs(cache_size*1024) bytes of memory"
|
||||
# a positive value translates to "cache_size*page_size bytes of memory"
|
||||
# docs for `PRAGMA cache_size` may need some clarification
|
||||
# https://www.sqlite.org/pragma.html#pragma_cache_size
|
||||
# https://www.sqlite.org/pgszchng2016.html
|
||||
# https://sqlite.org/forum/forumpost/096a95c0f9
|
||||
# NOTE: a system build may have used nonstandard compile-time options,
|
||||
# e.g. in recent versions of macOS the default cache_size is (positive) 2000
|
||||
cacheSize = -2000,
|
||||
|
||||
# https://www.sqlite.org/pragma.html#pragma_journal_mode
|
||||
journalMode = WAL): ?!T =
|
||||
|
||||
var
|
||||
env: AutoDisposed[SQLite]
|
||||
@ -225,9 +238,13 @@ proc new*(
|
||||
open(dbPath, env.val, flags)
|
||||
|
||||
let
|
||||
pragmaStmt = journalModePragmaStmt(env.val)
|
||||
pageSizePragmaStmt = pageSizePragmaStmt(env.val, pageSize)
|
||||
cacheSizePragmaStmt = cacheSizePragmaStmt(env.val, cacheSize)
|
||||
journalModePragmaStmt = journalModePragmaStmt(env.val, journalMode)
|
||||
|
||||
checkExec(pragmaStmt)
|
||||
checkExec(pageSizePragmaStmt)
|
||||
checkExec(cacheSizePragmaStmt)
|
||||
checkExec(journalModePragmaStmt)
|
||||
|
||||
var
|
||||
containsStmt: ContainsStmt
|
||||
|
||||
@ -42,7 +42,8 @@ suite "SQLiteDatastore":
|
||||
|
||||
check: dsRes.isErr
|
||||
|
||||
dsRes = SQLiteDatastore.new(basePathAbs, filename)
|
||||
dsRes = SQLiteDatastore.new(basePathAbs, filename, pageSize = 65536,
|
||||
cacheSize = 1600, journalMode = TRUNCATE)
|
||||
|
||||
check:
|
||||
dsRes.isOk
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user