abstract_adapter.rb 3.7 KB
Newer Older
D
Initial  
David Heinemeier Hansson 已提交
1 2 3
require 'benchmark'
require 'date'

4 5 6 7 8 9
require 'active_record/connection_adapters/abstract/schema_definitions'
require 'active_record/connection_adapters/abstract/schema_statements'
require 'active_record/connection_adapters/abstract/database_statements'
require 'active_record/connection_adapters/abstract/quoting'
require 'active_record/connection_adapters/abstract/connection_specification'

D
Initial  
David Heinemeier Hansson 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
# Method that requires a library, ensuring that rubygems is loaded
# This is used in the database adaptors to require DB drivers. Reasons:
# (1) database drivers are the only third-party library that Rails depend upon
# (2) they are often installed as gems
def require_library_or_gem(library_name)
  begin
    require library_name
  rescue LoadError => cannot_require
    # 1. Requiring the module is unsuccessful, maybe it's a gem and nobody required rubygems yet. Try.
    begin
      require 'rubygems'
    rescue LoadError => rubygems_not_installed
      raise cannot_require
    end
    # 2. Rubygems is installed and loaded. Try to load the library again
25
    begin
D
Initial  
David Heinemeier Hansson 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38
      require library_name
    rescue LoadError => gem_not_installed
      raise cannot_require
    end
  end
end

module ActiveRecord
  module ConnectionAdapters # :nodoc:
    # All the concrete database adapters follow the interface laid down in this class.
    # You can use this interface directly by borrowing the database connection from the Base with
    # Base.connection.
    class AbstractAdapter
39
      include Quoting, DatabaseStatements, SchemaStatements
D
Initial  
David Heinemeier Hansson 已提交
40 41
      @@row_even = true

42
      def initialize(connection, logger = nil) #:nodoc:
D
Initial  
David Heinemeier Hansson 已提交
43 44 45 46
        @connection, @logger = connection, logger
        @runtime = 0
      end

47
      # Returns the human-readable name of the adapter.  Use mixed case - one can always use downcase if needed.
48
      def adapter_name
49 50
        'Abstract'
      end
51
      
52
      # Returns true for database adapters that has implemented the schema statements.
53 54
      def supports_migrations?
        false
55
      end
56

57 58 59 60
      def reset_runtime #:nodoc:
        rt = @runtime
        @runtime = 0
        return rt
61
      end
62

63
      protected  
64
        def log(sql, name)
D
Initial  
David Heinemeier Hansson 已提交
65
          begin
66 67 68
            if block_given?
              if @logger and @logger.level <= Logger::INFO
                result = nil
69 70 71
                seconds = Benchmark.realtime { result = yield }
                @runtime += seconds
                log_info(sql, name, seconds)
72 73 74 75
                result
              else
                yield
              end
76 77 78
            else
              log_info(sql, name, 0)
              nil
D
Initial  
David Heinemeier Hansson 已提交
79
            end
80
          rescue Exception => e
D
Initial  
David Heinemeier Hansson 已提交
81 82 83 84 85 86
            log_info("#{e.message}: #{sql}", name, 0)
            raise ActiveRecord::StatementInvalid, "#{e.message}: #{sql}"
          end
        end

        def log_info(sql, name, runtime)
87
          return unless @logger
D
Initial  
David Heinemeier Hansson 已提交
88

89
          @logger.debug(
D
Initial  
David Heinemeier Hansson 已提交
90
            format_log_entry(
91
              "#{name.nil? ? "SQL" : name} (#{sprintf("%f", runtime)})",
D
Initial  
David Heinemeier Hansson 已提交
92 93 94 95 96 97
              sql.gsub(/ +/, " ")
            )
          )
        end

        def format_log_entry(message, dump = nil)
98 99 100 101 102 103
          if ActiveRecord::Base.colorize_logging
            if @@row_even then
              @@row_even = false; caller_color = "1;32"; message_color = "4;33"; dump_color = "1;37"
            else
              @@row_even = true; caller_color = "1;36"; message_color = "4;35"; dump_color = "0;37"
            end
104

105 106 107 108
            log_entry = "  \e[#{message_color}m#{message}\e[m"
            log_entry << "   \e[#{dump_color}m%s\e[m" % dump if dump.kind_of?(String) && !dump.nil?
            log_entry << "   \e[#{dump_color}m%p\e[m" % dump if !dump.kind_of?(String) && !dump.nil?
            log_entry
D
Initial  
David Heinemeier Hansson 已提交
109
          else
110
            "%s  %s" % [message, dump]
D
Initial  
David Heinemeier Hansson 已提交
111 112
          end
        end
113
    end
D
Initial  
David Heinemeier Hansson 已提交
114
  end
115
end