# File lib/flexirecord.rb, line 1383
1383:     def transaction(*arguments)
1384:       isolation_level = nil
1385:       records = []
1386:       unless_open_mode = false
1387:       arguments.flatten.each do |argument|
1388:         if argument.kind_of? FlexiRecord::IsolationLevel
1389:           isolation_level_argument = argument
1390:         elsif argument.respond_to? :to_sym
1391:           isolation_level_argument = FlexiRecord::IsolationLevel.by_symbol(argument)
1392:         end
1393:         if argument.nil?
1394:           # nothing
1395:         elsif argument == :unless_open
1396:           unless_open_mode = true
1397:         elsif isolation_level_argument
1398:           unless isolation_level.nil?
1399:             raise ArgumentError, "Multiple isolation levels given."
1400:           end
1401:           isolation_level = isolation_level_argument
1402:         elsif argument.kind_of? Symbol
1403:           raise ArgumentError, "Unknown symbol #{argument.inspect} given as argument to transaction method."
1404:         else
1405:           records << argument
1406:         end
1407:       end
1408:       if unless_open_mode and not records.empty?
1409:         raise ArgumentError, "No records may be specified, if a transaction is started 'unless_open'."
1410:       end
1411:       synchronize do
1412:         if unless_open_mode and transaction?
1413:           return yield
1414:         end
1415:         backup = records.collect { |record| record.dup }
1416:         old_stacklevel = @transaction_stacklevel
1417:         success = true
1418:         begin
1419:           if @transaction_stacklevel == 0
1420:             @isolation_level = isolation_level
1421:             if isolation_level
1422:               execute("BEGIN TRANSACTION ISOLATION LEVEL #{isolation_level}")
1423:             else
1424:               execute('BEGIN TRANSACTION')
1425:             end
1426:           else
1427:             execute('SAVEPOINT "FlexiRecord_' << @transaction_stacklevel.to_s << '"')
1428:           end
1429:           @transaction_stacklevel += 1
1430:           return yield
1431:         rescue StandardError
1432:           success = false
1433:           raise $!
1434:         ensure
1435:           @transaction_stacklevel = old_stacklevel
1436:           if success
1437:             if old_stacklevel == 0
1438:               execute('COMMIT TRANSACTION')
1439:             else
1440:               execute('RELEASE SAVEPOINT "FlexiRecord_' << @transaction_stacklevel.to_s << '"')
1441:             end
1442:           else
1443:             if old_stacklevel == 0
1444:               @isolation_level = 0
1445:               execute('ROLLBACK TRANSACTION')
1446:             else
1447:               execute('ROLLBACK TO SAVEPOINT "FlexiRecord_' << @transaction_stacklevel.to_s << '"')
1448:               execute('RELEASE SAVEPOINT "FlexiRecord_' << @transaction_stacklevel.to_s << '"')
1449:             end
1450:             backup.each_index do |record_index|
1451:               records[record_index].replace(backup[record_index])
1452:             end
1453:           end
1454:         end
1455:       end
1456:     end