Froze rails gems
[depot.git] / vendor / rails / activerecord / lib / active_record / connection_adapters / abstract_adapter.rb
1 require 'benchmark'
2 require 'date'
3 require 'bigdecimal'
4 require 'bigdecimal/util'
5
6 require 'active_record/connection_adapters/abstract/schema_definitions'
7 require 'active_record/connection_adapters/abstract/schema_statements'
8 require 'active_record/connection_adapters/abstract/database_statements'
9 require 'active_record/connection_adapters/abstract/quoting'
10 require 'active_record/connection_adapters/abstract/connection_pool'
11 require 'active_record/connection_adapters/abstract/connection_specification'
12 require 'active_record/connection_adapters/abstract/query_cache'
13
14 module ActiveRecord
15 module ConnectionAdapters # :nodoc:
16 # ActiveRecord supports multiple database systems. AbstractAdapter and
17 # related classes form the abstraction layer which makes this possible.
18 # An AbstractAdapter represents a connection to a database, and provides an
19 # abstract interface for database-specific functionality such as establishing
20 # a connection, escaping values, building the right SQL fragments for ':offset'
21 # and ':limit' options, etc.
22 #
23 # All the concrete database adapters follow the interface laid down in this class.
24 # ActiveRecord::Base.connection returns an AbstractAdapter object, which
25 # you can use.
26 #
27 # Most of the methods in the adapter are useful during migrations. Most
28 # notably, the instance methods provided by SchemaStatement are very useful.
29 class AbstractAdapter
30 include Quoting, DatabaseStatements, SchemaStatements
31 include QueryCache
32 include ActiveSupport::Callbacks
33 define_callbacks :checkout, :checkin
34
35 @@row_even = true
36
37 def initialize(connection, logger = nil) #:nodoc:
38 @connection, @logger = connection, logger
39 @runtime = 0
40 @last_verification = 0
41 @query_cache_enabled = false
42 end
43
44 # Returns the human-readable name of the adapter. Use mixed case - one
45 # can always use downcase if needed.
46 def adapter_name
47 'Abstract'
48 end
49
50 # Does this adapter support migrations? Backend specific, as the
51 # abstract adapter always returns +false+.
52 def supports_migrations?
53 false
54 end
55
56 # Does this adapter support using DISTINCT within COUNT? This is +true+
57 # for all adapters except sqlite.
58 def supports_count_distinct?
59 true
60 end
61
62 # Does this adapter support DDL rollbacks in transactions? That is, would
63 # CREATE TABLE or ALTER TABLE get rolled back by a transaction? PostgreSQL,
64 # SQL Server, and others support this. MySQL and others do not.
65 def supports_ddl_transactions?
66 false
67 end
68
69 # Should primary key values be selected from their corresponding
70 # sequence before the insert statement? If true, next_sequence_value
71 # is called before each insert to set the record's primary key.
72 # This is false for all adapters but Firebird.
73 def prefetch_primary_key?(table_name = nil)
74 false
75 end
76
77 def reset_runtime #:nodoc:
78 rt, @runtime = @runtime, 0
79 rt
80 end
81
82 # QUOTING ==================================================
83
84 # Override to return the quoted table name. Defaults to column quoting.
85 def quote_table_name(name)
86 quote_column_name(name)
87 end
88
89 # REFERENTIAL INTEGRITY ====================================
90
91 # Override to turn off referential integrity while executing <tt>&block</tt>.
92 def disable_referential_integrity(&block)
93 yield
94 end
95
96 # CONNECTION MANAGEMENT ====================================
97
98 # Checks whether the connection to the database is still active. This includes
99 # checking whether the database is actually capable of responding, i.e. whether
100 # the connection isn't stale.
101 def active?
102 @active != false
103 end
104
105 # Disconnects from the database if already connected, and establishes a
106 # new connection with the database.
107 def reconnect!
108 @active = true
109 end
110
111 # Disconnects from the database if already connected. Otherwise, this
112 # method does nothing.
113 def disconnect!
114 @active = false
115 end
116
117 # Reset the state of this connection, directing the DBMS to clear
118 # transactions and other connection-related server-side state. Usually a
119 # database-dependent operation.
120 #
121 # The default implementation does nothing; the implementation should be
122 # overridden by concrete adapters.
123 def reset!
124 # this should be overridden by concrete adapters
125 end
126
127 # Returns true if its safe to reload the connection between requests for development mode.
128 def requires_reloading?
129 true
130 end
131
132 # Checks whether the connection to the database is still active (i.e. not stale).
133 # This is done under the hood by calling <tt>active?</tt>. If the connection
134 # is no longer active, then this method will reconnect to the database.
135 def verify!(*ignored)
136 reconnect! unless active?
137 end
138
139 # Provides access to the underlying database driver for this adapter. For
140 # example, this method returns a Mysql object in case of MysqlAdapter,
141 # and a PGconn object in case of PostgreSQLAdapter.
142 #
143 # This is useful for when you need to call a proprietary method such as
144 # PostgreSQL's lo_* methods.
145 def raw_connection
146 @connection
147 end
148
149 def open_transactions
150 @open_transactions ||= 0
151 end
152
153 def increment_open_transactions
154 @open_transactions ||= 0
155 @open_transactions += 1
156 end
157
158 def decrement_open_transactions
159 @open_transactions -= 1
160 end
161
162 def log_info(sql, name, seconds)
163 if @logger && @logger.debug?
164 name = "#{name.nil? ? "SQL" : name} (#{sprintf("%.1f", seconds * 1000)}ms)"
165 @logger.debug(format_log_entry(name, sql.squeeze(' ')))
166 end
167 end
168
169 protected
170 def log(sql, name)
171 if block_given?
172 result = nil
173 seconds = Benchmark.realtime { result = yield }
174 @runtime += seconds
175 log_info(sql, name, seconds)
176 result
177 else
178 log_info(sql, name, 0)
179 nil
180 end
181 rescue Exception => e
182 # Log message and raise exception.
183 # Set last_verification to 0, so that connection gets verified
184 # upon reentering the request loop
185 @last_verification = 0
186 message = "#{e.class.name}: #{e.message}: #{sql}"
187 log_info(message, name, 0)
188 raise ActiveRecord::StatementInvalid, message
189 end
190
191 def format_log_entry(message, dump = nil)
192 if ActiveRecord::Base.colorize_logging
193 if @@row_even
194 @@row_even = false
195 message_color, dump_color = "4;36;1", "0;1"
196 else
197 @@row_even = true
198 message_color, dump_color = "4;35;1", "0"
199 end
200
201 log_entry = " \e[#{message_color}m#{message}\e[0m "
202 log_entry << "\e[#{dump_color}m%#{String === dump ? 's' : 'p'}\e[0m" % dump if dump
203 log_entry
204 else
205 "%s %s" % [message, dump]
206 end
207 end
208 end
209 end
210 end