Skip to content

Try to simplify pragma related constants #621

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

Merged
merged 3 commits into from
Mar 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/sqlite3/database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def initialize file, options = {}, zvfs = nil
#
# Fetch the encoding set on this database
def encoding
prepare("PRAGMA encoding") { |stmt| Encoding.find(stmt.first.first) }
Encoding.find super
end

# Installs (or removes) a block that will be invoked for every access
Expand Down
75 changes: 61 additions & 14 deletions lib/sqlite3/pragmas.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,20 @@ def get_enum_pragma(name)
# have duplicate values. See #synchronous, #default_synchronous,
# #temp_store, and #default_temp_store for usage examples.
def set_enum_pragma(name, mode, enums)
match = enums.find { |p| p.find { |i| i.to_s.downcase == mode.to_s.downcase } }
match = if enums.is_a?(Array)
# maybe deprecate this?
enums.find { |p| p.find { |i| i.to_s.downcase == mode.to_s.downcase } }
elsif mode.is_a?(String)
enums.fetch(mode.downcase)
else
mode
end

unless match
raise SQLite3::Exception, "unrecognized #{name} #{mode.inspect}"
end
execute("PRAGMA #{name}='#{match.first.upcase}'")

execute("PRAGMA #{name}='#{match}'")
end

# Returns the value of the given pragma as an integer.
Expand All @@ -79,26 +88,57 @@ def set_int_pragma(name, value)
end

# The enumeration of valid synchronous modes.
SYNCHRONOUS_MODES = [["full", 2], ["normal", 1], ["off", 0]].map(&:freeze).freeze
SYNCHRONOUS_MODES = {
"full" => 2,
"normal" => 1,
"off" => 0
}.freeze

# The enumeration of valid temp store modes.
TEMP_STORE_MODES = [["default", 0], ["file", 1], ["memory", 2]].map(&:freeze).freeze
TEMP_STORE_MODES = {
"default" => 0,
"file" => 1,
"memory" => 2
}.freeze

# The enumeration of valid auto vacuum modes.
AUTO_VACUUM_MODES = [["none", 0], ["full", 1], ["incremental", 2]].map(&:freeze).freeze
AUTO_VACUUM_MODES = {
"none" => 0,
"full" => 1,
"incremental" => 2
}.freeze

# The list of valid journaling modes.
JOURNAL_MODES = [["delete"], ["truncate"], ["persist"], ["memory"],
["wal"], ["off"]].map(&:freeze).freeze
JOURNAL_MODES = {
"delete" => "delete",
"truncate" => "truncate",
"persist" => "persist",
"memory" => "memory",
"wal" => "wal",
"off" => "off"
}.freeze

# The list of valid locking modes.
LOCKING_MODES = [["normal"], ["exclusive"]].map(&:freeze).freeze
LOCKING_MODES = {
"normal" => "normal",
"exclusive" => "exclusive"
}.freeze

# The list of valid encodings.
ENCODINGS = [["utf-8"], ["utf-16"], ["utf-16le"], ["utf-16be"]].map(&:freeze).freeze
ENCODINGS = {
"utf-8" => "utf-8",
"utf-16" => "utf-16",
"utf-16le" => "utf-16le",
"utf-16be" => "utf-16be"
}.freeze

# The list of valid WAL checkpoints.
WAL_CHECKPOINTS = [["passive"], ["full"], ["restart"], ["truncate"]].map(&:freeze).freeze
WAL_CHECKPOINTS = {
"passive" => "passive",
"full" => "full",
"restart" => "restart",
"truncate" => "truncate"
}.freeze

def application_id
get_int_pragma "application_id"
Expand Down Expand Up @@ -229,7 +269,7 @@ def encoding
end

def encoding=(mode)
set_enum_pragma "encoding", mode, ENCODINGS
set_string_pragma "encoding", mode, ENCODINGS
end

def foreign_key_check(*table, &block) # :yields: row
Expand Down Expand Up @@ -297,7 +337,7 @@ def journal_mode
end

def journal_mode=(mode)
set_enum_pragma "journal_mode", mode, JOURNAL_MODES
set_string_pragma "journal_mode", mode, JOURNAL_MODES
end

def journal_size_limit
Expand All @@ -321,7 +361,7 @@ def locking_mode
end

def locking_mode=(mode)
set_enum_pragma "locking_mode", mode, LOCKING_MODES
set_string_pragma "locking_mode", mode, LOCKING_MODES
end

def max_page_count
Expand Down Expand Up @@ -527,7 +567,7 @@ def wal_checkpoint
end

def wal_checkpoint=(mode)
set_enum_pragma "wal_checkpoint", mode, WAL_CHECKPOINTS
set_string_pragma "wal_checkpoint", mode, WAL_CHECKPOINTS
end

def writable_schema=(mode)
Expand Down Expand Up @@ -570,6 +610,13 @@ def table_info table

private

def set_string_pragma(pragma_name, value, valid_values)
valid_values.fetch(value.to_s.downcase) {
raise SQLite3::Exception, "unrecognized #{pragma_name} #{value.inspect}"
}
set_enum_pragma(pragma_name, value, valid_values)
end

# Compares two version strings
def version_compare(v1, v2)
v1 = v1.split(".").map { |i| i.to_i }
Expand Down
18 changes: 18 additions & 0 deletions test/test_pragmas.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ def teardown
@db.close
end

def test_temp_store_mode
@db.temp_store = "memory"
assert_equal 2, @db.temp_store
@db.temp_store = 1
assert_equal 1, @db.temp_store
end

def test_encoding
@db.encoding = "utf-16le"
assert_equal Encoding.find("utf-16le"), @db.encoding
end

def test_pragma_errors
assert_raises(SQLite3::Exception) do
@db.set_enum_pragma("foo", "bar", [])
Expand All @@ -41,6 +53,12 @@ def test_pragma_errors
end
end

def test_invalid_pragma
assert_raises(SQLite3::Exception) do
@db.journal_mode = 0
end
end

def test_get_boolean_pragma
refute(@db.get_boolean_pragma("read_uncommitted"))
end
Expand Down