Skip to content

Commit 109b6b1

Browse files
masamitsu-muraseflavorjones
authored andcommitted
Support default transaction mode.
* Add "default_transaction_mode" to "options" parameter of SQLite3::Database.new. It is used as transaction mode when SQLite3::Database#transaction is called without "mode" argument.
1 parent 0c59601 commit 109b6b1

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

lib/sqlite3/database.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ def initialize file, options = {}, zvfs = nil
119119
@type_translation = options[:type_translation]
120120
@type_translator = make_type_translator @type_translation
121121
@readonly = mode & Constants::Open::READONLY != 0
122+
@default_transaction_mode = options[:default_transaction_mode] || :deferred
122123

123124
if block_given?
124125
begin
@@ -622,8 +623,10 @@ def finalize
622623
# by SQLite, so attempting to nest a transaction will result in a runtime
623624
# exception.
624625
#
625-
# The +mode+ parameter may be either <tt>:deferred</tt> (the default),
626+
# The +mode+ parameter may be either <tt>:deferred</tt>,
626627
# <tt>:immediate</tt>, or <tt>:exclusive</tt>.
628+
# If `nil` is specified, the default transaction mode, which was
629+
# passed to #initialize, is used.
627630
#
628631
# If a block is given, the database instance is yielded to it, and the
629632
# transaction is committed when the block terminates. If the block
@@ -634,7 +637,8 @@ def finalize
634637
# If a block is not given, it is the caller's responsibility to end the
635638
# transaction explicitly, either by calling #commit, or by calling
636639
# #rollback.
637-
def transaction( mode = :deferred )
640+
def transaction( mode = nil )
641+
mode = @default_transaction_mode if mode.nil?
638642
execute "begin #{mode.to_s} transaction"
639643

640644
if block_given?

test/test_database.rb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,5 +624,45 @@ def test_raw_float_infinity
624624
db.execute("insert into foo values (?)", Float::INFINITY)
625625
assert_equal Float::INFINITY, db.execute("select avg(temperature) from foo").first.first
626626
end
627+
628+
def test_default_transaction_mode
629+
tf = Tempfile.new 'database_default_transaction_mode'
630+
SQLite3::Database.new(tf.path) do |db|
631+
db.execute("create table foo (score int)")
632+
db.execute("insert into foo values (?)", 1)
633+
end
634+
635+
test_cases = [
636+
{mode: nil, read: true, write: true},
637+
{mode: :deferred, read: true, write: true},
638+
{mode: :immediate, read: true, write: false},
639+
{mode: :exclusive, read: false, write: false},
640+
]
641+
642+
test_cases.each do |item|
643+
db = SQLite3::Database.new tf.path, default_transaction_mode: item[:mode]
644+
db2 = SQLite3::Database.new tf.path
645+
db.transaction do
646+
sql_for_read_test = "select * from foo"
647+
if item[:read]
648+
assert_nothing_raised{ db2.execute(sql_for_read_test) }
649+
else
650+
assert_raises(SQLite3::BusyException){ db2.execute(sql_for_read_test) }
651+
end
652+
653+
sql_for_write_test = "insert into foo values (2)"
654+
if item[:write]
655+
assert_nothing_raised{ db2.execute(sql_for_write_test) }
656+
else
657+
assert_raises(SQLite3::BusyException){ db2.execute(sql_for_write_test) }
658+
end
659+
end
660+
ensure
661+
db.close if db && !db.closed?
662+
db2.close if db2 && !db2.closed?
663+
end
664+
ensure
665+
tf.unlink if tf
666+
end
627667
end
628668
end

0 commit comments

Comments
 (0)