# The before_commit extension adds a Database#before_commit hook that you can
# use to defer operations until immediately before a transaction is committed.
#
# To load the extension into the database:
#
#   DB.extension :before_commit
module Sequel
  module Database::BeforeCommit
    def before_commit(opts=OPTS, &block)
      raise Error, "must provide block to before_commit" unless block
      synchronize(opts[:server]) do |conn|
        raise Error, "must be inside a transaction" unless already_in_transaction?(conn, opts)
        (_trans(conn)[:before_commit] ||= []) << block
      end
    end

    def commit_transaction(conn, opts=OPTS)
      if !supports_savepoints? or savepoint_level(conn) == 1
        begin
          if ary = _trans(conn)[:before_commit]
            ary.each{|b| b.call}
          end
        rescue Exception => e
          begin
            rollback_transaction(conn, opts)
          rescue Exception
          end
          transaction_error(e, :conn=>conn, :rollback=>opts[:rollback])
        else
          super
        end
      else
        super
      end
    end
  end

  Database.register_extension(:before_commit, Database::BeforeCommit)
end

