Automatically set PRAGMAs using connection query params (#85)

* Automatically set PRAGMAs using connection query params

Introduce the flexibility to adjust certain PRAGMAs of the SQLite3
connection without having to hardcode those in your codebase (and wait
for compilation).

This allows applications to use `DATABASE_URL` to dynamically fine tune
their SQLite3 configuration.

The change complements `#setup_connection` that offers, via code, the
option to perform queries on setup of each connection.

Only a few PRAGMAs necessary to allow more performant concurrent reads
and reduce write locking.

These pragmas are detected and combined in a single SQL string to reduce
to 1 the number of calls to `sqlite3_exec` C function.

There is no validation of supplied values as SQLite3 automatically
ignores incorrect values for these pragmas.

Closes #84

References:
- https://www.sqlite.org/pragma.html

* Simplify PRAGMA mapping and detection

No longer prefix PRAGMAS with `_`, so the mapping between the real
SQLite3 pragmas and the usage in the URI is more direct.

Use macros instead of case to detect pragmas from URI params and return
those as NamedTuple.

* Update README.md

---------

Co-authored-by: Brian J. Cardiff <bcardiff@gmail.com>
This commit is contained in:
Luis Lavena 2023-02-18 21:06:09 +01:00 committed by GitHub
parent d15a8da05c
commit 84857724c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 117 additions and 1 deletions

View file

@ -10,6 +10,14 @@ private def dump(source, target)
end
end
private def it_sets_pragma_on_connection(pragma : String, value : String, expected, file = __FILE__, line = __LINE__)
it "sets pragma '#{pragma}' to #{expected}", file, line do
with_db("#{DB_FILENAME}?#{pragma}=#{value}") do |db|
db.scalar("PRAGMA #{pragma}").should eq(expected)
end
end
end
describe Connection do
it "opens a database and then backs it up to another db" do
with_db do |db|
@ -68,4 +76,34 @@ describe Connection do
cnn.scalar("select count(*) from person").should eq(1)
end
end
# adjust busy_timeout pragma (default is 0)
it_sets_pragma_on_connection "busy_timeout", "1000", 1000
# adjust cache_size pragma (default is -2000, 2MB)
it_sets_pragma_on_connection "cache_size", "-4000", -4000
# enable foreign_keys, no need to test off (is the default)
it_sets_pragma_on_connection "foreign_keys", "1", 1
it_sets_pragma_on_connection "foreign_keys", "yes", 1
it_sets_pragma_on_connection "foreign_keys", "true", 1
it_sets_pragma_on_connection "foreign_keys", "on", 1
# change journal_mode (default is delete)
it_sets_pragma_on_connection "journal_mode", "delete", "delete"
it_sets_pragma_on_connection "journal_mode", "truncate", "truncate"
it_sets_pragma_on_connection "journal_mode", "persist", "persist"
# change synchronous mode (default is 2, FULL)
it_sets_pragma_on_connection "synchronous", "0", 0
it_sets_pragma_on_connection "synchronous", "off", 0
it_sets_pragma_on_connection "synchronous", "1", 1
it_sets_pragma_on_connection "synchronous", "normal", 1
it_sets_pragma_on_connection "synchronous", "2", 2
it_sets_pragma_on_connection "synchronous", "full", 2
it_sets_pragma_on_connection "synchronous", "3", 3
it_sets_pragma_on_connection "synchronous", "extra", 3
# change wal_autocheckpoint (default is 1000)
it_sets_pragma_on_connection "wal_autocheckpoint", "0", 0
end