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 | | Name | Connection key |
|---------------------------|-----------------| |---------------------------|-----------------|
| [Busy Timeout][pragma-to] | `_busy_timeout` | | [Busy Timeout][pragma-to] | `busy_timeout` |
| [Cache Size][pragma-cs] | `_cache_size` | | [Cache Size][pragma-cs] | `cache_size` |
| [Foreign Keys][pragma-fk] | `_foreign_keys` | | [Foreign Keys][pragma-fk] | `foreign_keys` |
| [Journal Mode][pragma-jm] | `_journal_mode` | | [Journal Mode][pragma-jm] | `journal_mode` |
| [Synchronous][pragma-sync] | `_synchronous` | | [Synchronous][pragma-sync] | `synchronous` |
| [WAL autocheckoint][pragma-walck] | `_wal_autocheckpoint` | | [WAL autocheckoint][pragma-walck] | `wal_autocheckpoint` |
Please note there values passed using these connection keys are passed Please note there values passed using these connection keys are passed
directly to SQLite3 without check or evaluation. Using incorrect values result directly to SQLite3 without check or evaluation. Using incorrect values result

View file

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

View file

@ -93,32 +93,40 @@ class SQLite3::Connection < DB::Connection
private def process_query_params(uri : URI) private def process_query_params(uri : URI)
return unless query = uri.query return unless query = uri.query
pragmas = Hash(String, String).new detected_pragmas = extract_params(query,
busy_timeout: nil,
URI::Params.parse(query) do |key, value| cache_size: nil,
case key foreign_keys: nil,
when "_busy_timeout" journal_mode: nil,
pragmas["busy_timeout"] = value synchronous: nil,
when "_cache_size" wal_autocheckpoint: nil,
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
# concatenate all into a single SQL string # concatenate all into a single SQL string
sql = String.build do |str| sql = String.build do |str|
pragmas.each do |key, value| detected_pragmas.each do |key, value|
next unless value
str << "PRAGMA #{key}=#{value};" str << "PRAGMA #{key}=#{value};"
end end
end end
check LibSQLite3.exec(@db, sql, nil, nil, nil) check LibSQLite3.exec(@db, sql, nil, nil, nil)
end 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 end