require 'test/unit' require 'test/FbTestCases' require 'fb.so' include Fb class TransactionTestCases < Test::Unit::TestCase include FbTestCases def test_transaction Database.create(@parms) do |connection| n = 0 assert !connection.transaction_started connection.transaction assert connection.transaction_started connection.commit assert !connection.transaction_started connection.transaction assert connection.transaction_started connection.rollback assert !connection.transaction_started connection.drop end end def test_transaction_block Database.create(@parms) do |connection| n = 0 assert !connection.transaction_started connection.transaction do assert connection.transaction_started end assert !connection.transaction_started assert_raise RuntimeError do connection.transaction do assert connection.transaction_started raise "generic exception" end end assert !connection.transaction_started connection.drop end end def test_auto_transaction_select_with_exception sql_select = "SELECT * FROM RDB$DATABASE" Database.create(@parms) do |connection| assert !connection.transaction_started assert_raise RuntimeError do connection.execute(sql_select) do |cursor| assert connection.transaction_started raise "abort" end end assert !connection.transaction_started connection.drop end end def test_auto_transaction_insert_with_exception sql_schema = "CREATE TABLE TEST (ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(20))" sql_insert = "INSERT INTO TEST (ID, NAME) VALUES (?, ?)" Database.create(@parms) do |connection| connection.execute(sql_schema) assert !connection.transaction_started connection.execute(sql_insert, 1, "one") assert !connection.transaction_started assert_raise Error do connection.execute(sql_insert, 1, "two") end assert !connection.transaction_started, "transaction is active" connection.drop end end def test_auto_transaction_query Database.create(@parms) do |connection| assert !connection.transaction_started rs = connection.query("select * from rdb$database") assert !connection.transaction_started connection.drop end end def test_query_in_transaction Database.create(@parms) do |connection| assert !connection.transaction_started connection.transaction do assert connection.transaction_started rs = connection.query("select * from rdb$database") assert connection.transaction_started end assert !connection.transaction_started connection.drop end end def test_insert_commit sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20))" sql_insert = "INSERT INTO TEST (ID, NAME) VALUES (?, ?)" sql_select = "SELECT * FROM TEST ORDER BY ID" Database.create(@parms) do |connection| connection.execute(sql_schema); connection.transaction 10.times do |i| connection.execute(sql_insert, i, i.to_s); end connection.commit connection.execute(sql_select) do |cursor| rows = cursor.fetchall assert_equal 10, rows.size 10.times do |i| assert_equal i, rows[i][0] assert_equal i.to_s, rows[i][1] end end connection.drop end end def test_insert_rollback sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20))" sql_insert = "INSERT INTO TEST (ID, NAME) VALUES (?, ?)" sql_select = "SELECT * FROM TEST ORDER BY ID" Database.create(@parms) do |connection| connection.execute(sql_schema) connection.transaction 10.times do |i| connection.execute(sql_insert, i, i.to_s); end connection.rollback rows = connection.execute(sql_select) do |cursor| cursor.fetchall end assert_equal 0, rows.size connection.drop end end def test_transaction_block_insert_commit sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20))" sql_insert = "INSERT INTO TEST (ID, NAME) VALUES (?, ?)" sql_select = "SELECT * FROM TEST ORDER BY ID" Database.create(@parms) do |connection| connection.execute(sql_schema); assert !connection.transaction_started result = connection.transaction do assert connection.transaction_started 10.times do |i| connection.execute(sql_insert, i, i.to_s); end assert connection.transaction_started "transaction block result" end assert_equal "transaction block result", result assert !connection.transaction_started connection.execute(sql_select) do |cursor| assert_equal 10, cursor.fetchall.size end connection.drop end end def test_transaction_block_insert_rollback sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20))" sql_insert = "INSERT INTO TEST (ID, NAME) VALUES (?, ?)" sql_select = "SELECT * FROM TEST ORDER BY ID" Database.create(@parms) do |connection| connection.execute(sql_schema) assert !connection.transaction_started assert_raise RuntimeError do connection.transaction do 10.times do |i| connection.execute(sql_insert, i, i.to_s); end raise "Raise an exception, causing the transaction to be rolled back." end end rows = connection.execute(sql_select) do |cursor| cursor.fetchall end assert_equal 0, rows.size connection.drop end end def test_simultaneous_transactions db_file1 = "#{@db_file}1" db_file2 = "#{@db_file}2" rm_rf db_file1 rm_rf db_file2 parms1 = @parms.merge(:database => "#{@db_host}:#{db_file1}") parms2 = @parms.merge(:database => "#{@db_host}:#{db_file2}") Database.create(parms1) do |conn1| Database.create(parms2) do |conn2| assert !conn1.transaction_started, "conn1 transaction is started" assert !conn2.transaction_started, "conn2 transaction is started" conn1.transaction do assert conn1.transaction_started, "conn1 transaction is not started" assert !conn2.transaction_started, "conn2 transaction is started" conn2.transaction do assert conn2.transaction_started, "conn2 transaction is not started" assert conn1.transaction_started, "conn1 transaction is not started" end assert !conn2.transaction_started, "conn2 transaction is still active" assert conn1.transaction_started, "conn1 transaction is not still active" end assert !conn1.transaction_started, "conn1 transaction is still active" conn2.drop end conn1.drop end end def test_transaction_options_snapshot sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20))" sql_insert = "INSERT INTO TEST (ID, NAME) VALUES (?, ?)" sql_select = "SELECT * FROM TEST ORDER BY ID" sql_delete = "DELETE FROM TEST WHERE ID < ?" Database.create(@parms) do |conn1| conn1.execute(sql_schema) conn1.transaction do 10.times do |i| conn1.execute(sql_insert, i, "NAME#{i}") end end Database.connect(@parms) do |conn2| conn2.transaction("SNAPSHOT") do affected = conn1.execute(sql_delete, 5) assert_equal 5, affected rs1 = conn2.query(sql_select) assert_equal 10, rs1.size end rs2 = conn2.query(sql_select) assert_equal 5, rs2.size end end end def test_transaction_options_read_committed sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20))" sql_insert = "INSERT INTO TEST (ID, NAME) VALUES (?, ?)" sql_select = "SELECT * FROM TEST ORDER BY ID" sql_delete = "DELETE FROM TEST WHERE ID < ?" Database.create(@parms) do |conn1| conn1.execute(sql_schema) conn1.transaction do 10.times do |i| conn1.execute(sql_insert, i, "NAME#{i}") end end Database.connect(@parms) do |conn2| conn2.transaction("READ COMMITTED") do affected = conn1.execute(sql_delete, 5) assert_equal 5, affected rs1 = conn2.query(sql_select) assert_equal 5, rs1.size end rs2 = conn2.query(sql_select) assert_equal 5, rs2.size end end end end