Skip to content

Commit

Permalink
Merge pull request #426 from masamitsu-murase/support_default_transac…
Browse files Browse the repository at this point in the history
…tion_mode

Support default transaction mode.
  • Loading branch information
flavorjones committed Nov 26, 2023
2 parents 0c59601 + f140292 commit ad93a6b
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

- Vendored sqlite is update to [v3.44.2](https://sqlite.org/releaselog/3_44_2.html). @flavorjones

### Added

- `Database.new` now accepts a `:default_transaction_mode` option (defaulting to `:deferred`), and `Database#transaction` no longer requires a transaction mode to be specified. This should allow higher-level adapters to more easily choose a transaction mode for a database connection. [#426] @masamitsu-murase


## 1.6.8 / 2023-11-01

Expand Down
29 changes: 22 additions & 7 deletions lib/sqlite3/database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,23 @@ def quote( string )

# call-seq: SQLite3::Database.new(file, options = {})
#
# Create a new Database object that opens the given file. If utf16
# is +true+, the filename is interpreted as a UTF-16 encoded string.
# Create a new Database object that opens the given file.
#
# Supported permissions +options+:
# - the default mode is <tt>READWRITE | CREATE</tt>
# - +:readonly+: boolean (default false), true to set the mode to +READONLY+
# - +:readwrite+: boolean (default false), true to set the mode to +READWRITE+
# - +:flags+: set the mode to a combination of SQLite3::Constants::Open flags.
#
# Supported encoding +options+:
# - +:utf16+: boolean (default false), is the filename's encoding UTF-16 (only needed if the filename encoding is not UTF_16LE or BE)
#
# Other supported +options+:
# - +:strict+: boolean (default false), disallow the use of double-quoted string literals (see https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted)
# - +:results_as_hash+: boolean (default false), return rows as hashes instead of arrays
# - +:type_translation+: boolean (default false), enable type translation
# - +:default_transaction_mode+: one of +:deferred+ (default), +:immediate+, or +:exclusive+. If a mode is not specified in a call to #transaction, this will be the default transaction mode.
#
# By default, the new database will return result rows as arrays
# (#results_as_hash) and has type translation disabled (#type_translation=).

def initialize file, options = {}, zvfs = nil
mode = Constants::Open::READWRITE | Constants::Open::CREATE

Expand Down Expand Up @@ -119,6 +130,7 @@ def initialize file, options = {}, zvfs = nil
@type_translation = options[:type_translation]
@type_translator = make_type_translator @type_translation
@readonly = mode & Constants::Open::READONLY != 0
@default_transaction_mode = options[:default_transaction_mode] || :deferred

if block_given?
begin
Expand Down Expand Up @@ -622,8 +634,10 @@ def finalize
# by SQLite, so attempting to nest a transaction will result in a runtime
# exception.
#
# The +mode+ parameter may be either <tt>:deferred</tt> (the default),
# The +mode+ parameter may be either <tt>:deferred</tt>,
# <tt>:immediate</tt>, or <tt>:exclusive</tt>.
# If `nil` is specified, the default transaction mode, which was
# passed to #initialize, is used.
#
# If a block is given, the database instance is yielded to it, and the
# transaction is committed when the block terminates. If the block
Expand All @@ -634,7 +648,8 @@ def finalize
# If a block is not given, it is the caller's responsibility to end the
# transaction explicitly, either by calling #commit, or by calling
# #rollback.
def transaction( mode = :deferred )
def transaction( mode = nil )
mode = @default_transaction_mode if mode.nil?
execute "begin #{mode.to_s} transaction"

if block_given?
Expand Down
40 changes: 40 additions & 0 deletions test/test_database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -624,5 +624,45 @@ def test_raw_float_infinity
db.execute("insert into foo values (?)", Float::INFINITY)
assert_equal Float::INFINITY, db.execute("select avg(temperature) from foo").first.first
end

def test_default_transaction_mode
tf = Tempfile.new 'database_default_transaction_mode'
SQLite3::Database.new(tf.path) do |db|
db.execute("create table foo (score int)")
db.execute("insert into foo values (?)", 1)
end

test_cases = [
{mode: nil, read: true, write: true},
{mode: :deferred, read: true, write: true},
{mode: :immediate, read: true, write: false},
{mode: :exclusive, read: false, write: false},
]

test_cases.each do |item|
db = SQLite3::Database.new tf.path, default_transaction_mode: item[:mode]
db2 = SQLite3::Database.new tf.path
db.transaction do
sql_for_read_test = "select * from foo"
if item[:read]
assert_nothing_raised{ db2.execute(sql_for_read_test) }
else
assert_raises(SQLite3::BusyException){ db2.execute(sql_for_read_test) }
end

sql_for_write_test = "insert into foo values (2)"
if item[:write]
assert_nothing_raised{ db2.execute(sql_for_write_test) }
else
assert_raises(SQLite3::BusyException){ db2.execute(sql_for_write_test) }
end
end
ensure
db.close if db && !db.closed?
db2.close if db2 && !db2.closed?
end
ensure
tf.unlink if tf
end
end
end

0 comments on commit ad93a6b

Please sign in to comment.