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.
This commit is contained in:
Luis Lavena 2023-02-11 19:01:52 +01:00
parent a77b14bcea
commit 6a73d4f64d
3 changed files with 54 additions and 46 deletions

View file

@ -67,12 +67,12 @@ The following is the list of supported options:
| Name | Connection key |
|---------------------------|-----------------|
| [Busy Timeout][pragma-to] | `_busy_timeout` |
| [Cache Size][pragma-cs] | `_cache_size` |
| [Foreign Keys][pragma-fk] | `_foreign_keys` |
| [Journal Mode][pragma-jm] | `_journal_mode` |
| [Synchronous][pragma-sync] | `_synchronous` |
| [WAL autocheckoint][pragma-walck] | `_wal_autocheckpoint` |
| [Busy Timeout][pragma-to] | `busy_timeout` |
| [Cache Size][pragma-cs] | `cache_size` |
| [Foreign Keys][pragma-fk] | `foreign_keys` |
| [Journal Mode][pragma-jm] | `journal_mode` |
| [Synchronous][pragma-sync] | `synchronous` |
| [WAL autocheckoint][pragma-walck] | `wal_autocheckpoint` |
Please note there values passed using these connection keys are passed
directly to SQLite3 without check or evaluation. Using incorrect values result

View file

@ -10,9 +10,9 @@ private def dump(source, target)
end
end
private def it_sets_pragma_on_connection(pragma : String, option : String, value : String, expected, file = __FILE__, line = __LINE__)
it "sets pragma '#{pragma}' to #{expected} using '#{option}'", file, line do
with_db("#{DB_FILENAME}?#{option}=#{value}") do |db|
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
@ -78,32 +78,32 @@ describe Connection do
end
# adjust busy_timeout pragma (default is 0)
it_sets_pragma_on_connection "busy_timeout", "_busy_timeout", "1000", 1000
it_sets_pragma_on_connection "busy_timeout", "1000", 1000
# adjust cache_size pragma (default is -2000, 2MB)
it_sets_pragma_on_connection "cache_size", "_cache_size", "-4000", -4000
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", "_foreign_keys", "1", 1
it_sets_pragma_on_connection "foreign_keys", "_foreign_keys", "yes", 1
it_sets_pragma_on_connection "foreign_keys", "_foreign_keys", "true", 1
it_sets_pragma_on_connection "foreign_keys", "_foreign_keys", "on", 1
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", "_journal_mode", "delete", "delete"
it_sets_pragma_on_connection "journal_mode", "_journal_mode", "truncate", "truncate"
it_sets_pragma_on_connection "journal_mode", "_journal_mode", "persist", "persist"
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", "_synchronous", "0", 0
it_sets_pragma_on_connection "synchronous", "_synchronous", "off", 0
it_sets_pragma_on_connection "synchronous", "_synchronous", "1", 1
it_sets_pragma_on_connection "synchronous", "_synchronous", "normal", 1
it_sets_pragma_on_connection "synchronous", "_synchronous", "2", 2
it_sets_pragma_on_connection "synchronous", "_synchronous", "full", 2
it_sets_pragma_on_connection "synchronous", "_synchronous", "3", 3
it_sets_pragma_on_connection "synchronous", "_synchronous", "extra", 3
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", "_wal_autocheckpoint", "0", 0
it_sets_pragma_on_connection "wal_autocheckpoint", "0", 0
end

View file

@ -93,32 +93,40 @@ class SQLite3::Connection < DB::Connection
private def process_query_params(uri : URI)
return unless query = uri.query
pragmas = Hash(String, String).new
URI::Params.parse(query) do |key, value|
case key
when "_busy_timeout"
pragmas["busy_timeout"] = value
when "_cache_size"
pragmas["cache_size"] = value
when "_foreign_keys"
pragmas["foreign_keys"] = value
when "_journal_mode"
pragmas["journal_mode"] = value
when "_synchronous"
pragmas["synchronous"] = value
when "_wal_autocheckpoint"
pragmas["wal_autocheckpoint"] = value
end
end
detected_pragmas = extract_params(query,
busy_timeout: nil,
cache_size: nil,
foreign_keys: nil,
journal_mode: nil,
synchronous: nil,
wal_autocheckpoint: nil,
)
# concatenate all into a single SQL string
sql = String.build do |str|
pragmas.each do |key, value|
detected_pragmas.each do |key, value|
next unless value
str << "PRAGMA #{key}=#{value};"
end
end
check LibSQLite3.exec(@db, sql, nil, nil, nil)
end
private def extract_params(query : String, **default : **T) forall T
res = default
URI::Params.parse(query) do |key, value|
{% begin %}
case key
{% for key in T %}
when {{ key.stringify }}
res = res.merge({{key.id}}: value)
{% end %}
end
{% end %}
end
res
end
end