activerecord 1.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (178) hide show
  1. data/CHANGELOG +5518 -76
  2. data/README.rdoc +222 -0
  3. data/examples/performance.rb +162 -0
  4. data/examples/simple.rb +14 -0
  5. data/lib/active_record/aggregations.rb +192 -80
  6. data/lib/active_record/association_preload.rb +403 -0
  7. data/lib/active_record/associations/association_collection.rb +545 -53
  8. data/lib/active_record/associations/association_proxy.rb +295 -0
  9. data/lib/active_record/associations/belongs_to_association.rb +91 -0
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +78 -0
  11. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +127 -36
  12. data/lib/active_record/associations/has_many_association.rb +108 -84
  13. data/lib/active_record/associations/has_many_through_association.rb +116 -0
  14. data/lib/active_record/associations/has_one_association.rb +143 -0
  15. data/lib/active_record/associations/has_one_through_association.rb +40 -0
  16. data/lib/active_record/associations/through_association_scope.rb +154 -0
  17. data/lib/active_record/associations.rb +2086 -368
  18. data/lib/active_record/attribute_methods/before_type_cast.rb +33 -0
  19. data/lib/active_record/attribute_methods/dirty.rb +95 -0
  20. data/lib/active_record/attribute_methods/primary_key.rb +50 -0
  21. data/lib/active_record/attribute_methods/query.rb +39 -0
  22. data/lib/active_record/attribute_methods/read.rb +116 -0
  23. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -0
  24. data/lib/active_record/attribute_methods/write.rb +37 -0
  25. data/lib/active_record/attribute_methods.rb +60 -0
  26. data/lib/active_record/autosave_association.rb +369 -0
  27. data/lib/active_record/base.rb +1603 -721
  28. data/lib/active_record/callbacks.rb +176 -225
  29. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +365 -0
  30. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +113 -0
  31. data/lib/active_record/connection_adapters/abstract/database_limits.rb +57 -0
  32. data/lib/active_record/connection_adapters/abstract/database_statements.rb +329 -0
  33. data/lib/active_record/connection_adapters/abstract/query_cache.rb +81 -0
  34. data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -0
  35. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +739 -0
  36. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +543 -0
  37. data/lib/active_record/connection_adapters/abstract_adapter.rb +165 -279
  38. data/lib/active_record/connection_adapters/mysql_adapter.rb +594 -82
  39. data/lib/active_record/connection_adapters/postgresql_adapter.rb +988 -135
  40. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +53 -0
  41. data/lib/active_record/connection_adapters/sqlite_adapter.rb +365 -71
  42. data/lib/active_record/counter_cache.rb +115 -0
  43. data/lib/active_record/dynamic_finder_match.rb +53 -0
  44. data/lib/active_record/dynamic_scope_match.rb +32 -0
  45. data/lib/active_record/errors.rb +172 -0
  46. data/lib/active_record/fixtures.rb +941 -105
  47. data/lib/active_record/locale/en.yml +40 -0
  48. data/lib/active_record/locking/optimistic.rb +172 -0
  49. data/lib/active_record/locking/pessimistic.rb +55 -0
  50. data/lib/active_record/log_subscriber.rb +48 -0
  51. data/lib/active_record/migration.rb +617 -0
  52. data/lib/active_record/named_scope.rb +138 -0
  53. data/lib/active_record/nested_attributes.rb +417 -0
  54. data/lib/active_record/observer.rb +105 -36
  55. data/lib/active_record/persistence.rb +291 -0
  56. data/lib/active_record/query_cache.rb +36 -0
  57. data/lib/active_record/railtie.rb +91 -0
  58. data/lib/active_record/railties/controller_runtime.rb +38 -0
  59. data/lib/active_record/railties/databases.rake +512 -0
  60. data/lib/active_record/reflection.rb +364 -87
  61. data/lib/active_record/relation/batches.rb +89 -0
  62. data/lib/active_record/relation/calculations.rb +286 -0
  63. data/lib/active_record/relation/finder_methods.rb +355 -0
  64. data/lib/active_record/relation/predicate_builder.rb +41 -0
  65. data/lib/active_record/relation/query_methods.rb +261 -0
  66. data/lib/active_record/relation/spawn_methods.rb +112 -0
  67. data/lib/active_record/relation.rb +393 -0
  68. data/lib/active_record/schema.rb +59 -0
  69. data/lib/active_record/schema_dumper.rb +195 -0
  70. data/lib/active_record/serialization.rb +60 -0
  71. data/lib/active_record/serializers/xml_serializer.rb +244 -0
  72. data/lib/active_record/session_store.rb +340 -0
  73. data/lib/active_record/test_case.rb +67 -0
  74. data/lib/active_record/timestamp.rb +88 -0
  75. data/lib/active_record/transactions.rb +329 -75
  76. data/lib/active_record/validations/associated.rb +48 -0
  77. data/lib/active_record/validations/uniqueness.rb +185 -0
  78. data/lib/active_record/validations.rb +58 -179
  79. data/lib/active_record/version.rb +9 -0
  80. data/lib/active_record.rb +100 -24
  81. data/lib/rails/generators/active_record/migration/migration_generator.rb +25 -0
  82. data/lib/rails/generators/active_record/migration/templates/migration.rb +17 -0
  83. data/lib/rails/generators/active_record/model/model_generator.rb +38 -0
  84. data/lib/rails/generators/active_record/model/templates/migration.rb +16 -0
  85. data/lib/rails/generators/active_record/model/templates/model.rb +5 -0
  86. data/lib/rails/generators/active_record/model/templates/module.rb +5 -0
  87. data/lib/rails/generators/active_record/observer/observer_generator.rb +15 -0
  88. data/lib/rails/generators/active_record/observer/templates/observer.rb +2 -0
  89. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +24 -0
  90. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +16 -0
  91. data/lib/rails/generators/active_record.rb +27 -0
  92. metadata +216 -158
  93. data/README +0 -361
  94. data/RUNNING_UNIT_TESTS +0 -36
  95. data/dev-utils/eval_debugger.rb +0 -9
  96. data/examples/associations.rb +0 -87
  97. data/examples/shared_setup.rb +0 -15
  98. data/examples/validation.rb +0 -88
  99. data/install.rb +0 -60
  100. data/lib/active_record/deprecated_associations.rb +0 -70
  101. data/lib/active_record/support/class_attribute_accessors.rb +0 -43
  102. data/lib/active_record/support/class_inheritable_attributes.rb +0 -37
  103. data/lib/active_record/support/clean_logger.rb +0 -10
  104. data/lib/active_record/support/inflector.rb +0 -70
  105. data/lib/active_record/vendor/mysql.rb +0 -1117
  106. data/lib/active_record/vendor/simple.rb +0 -702
  107. data/lib/active_record/wrappers/yaml_wrapper.rb +0 -15
  108. data/lib/active_record/wrappings.rb +0 -59
  109. data/rakefile +0 -122
  110. data/test/abstract_unit.rb +0 -16
  111. data/test/aggregations_test.rb +0 -34
  112. data/test/all.sh +0 -8
  113. data/test/associations_test.rb +0 -477
  114. data/test/base_test.rb +0 -513
  115. data/test/class_inheritable_attributes_test.rb +0 -33
  116. data/test/connections/native_mysql/connection.rb +0 -24
  117. data/test/connections/native_postgresql/connection.rb +0 -24
  118. data/test/connections/native_sqlite/connection.rb +0 -24
  119. data/test/deprecated_associations_test.rb +0 -336
  120. data/test/finder_test.rb +0 -67
  121. data/test/fixtures/accounts/signals37 +0 -3
  122. data/test/fixtures/accounts/unknown +0 -2
  123. data/test/fixtures/auto_id.rb +0 -4
  124. data/test/fixtures/column_name.rb +0 -3
  125. data/test/fixtures/companies/first_client +0 -6
  126. data/test/fixtures/companies/first_firm +0 -4
  127. data/test/fixtures/companies/second_client +0 -6
  128. data/test/fixtures/company.rb +0 -37
  129. data/test/fixtures/company_in_module.rb +0 -33
  130. data/test/fixtures/course.rb +0 -3
  131. data/test/fixtures/courses/java +0 -2
  132. data/test/fixtures/courses/ruby +0 -2
  133. data/test/fixtures/customer.rb +0 -30
  134. data/test/fixtures/customers/david +0 -6
  135. data/test/fixtures/db_definitions/mysql.sql +0 -96
  136. data/test/fixtures/db_definitions/mysql2.sql +0 -4
  137. data/test/fixtures/db_definitions/postgresql.sql +0 -113
  138. data/test/fixtures/db_definitions/postgresql2.sql +0 -4
  139. data/test/fixtures/db_definitions/sqlite.sql +0 -85
  140. data/test/fixtures/db_definitions/sqlite2.sql +0 -4
  141. data/test/fixtures/default.rb +0 -2
  142. data/test/fixtures/developer.rb +0 -8
  143. data/test/fixtures/developers/david +0 -2
  144. data/test/fixtures/developers/jamis +0 -2
  145. data/test/fixtures/developers_projects/david_action_controller +0 -2
  146. data/test/fixtures/developers_projects/david_active_record +0 -2
  147. data/test/fixtures/developers_projects/jamis_active_record +0 -2
  148. data/test/fixtures/entrant.rb +0 -3
  149. data/test/fixtures/entrants/first +0 -3
  150. data/test/fixtures/entrants/second +0 -3
  151. data/test/fixtures/entrants/third +0 -3
  152. data/test/fixtures/fixture_database.sqlite +0 -0
  153. data/test/fixtures/fixture_database_2.sqlite +0 -0
  154. data/test/fixtures/movie.rb +0 -5
  155. data/test/fixtures/movies/first +0 -2
  156. data/test/fixtures/movies/second +0 -2
  157. data/test/fixtures/project.rb +0 -3
  158. data/test/fixtures/projects/action_controller +0 -2
  159. data/test/fixtures/projects/active_record +0 -2
  160. data/test/fixtures/reply.rb +0 -21
  161. data/test/fixtures/subscriber.rb +0 -5
  162. data/test/fixtures/subscribers/first +0 -2
  163. data/test/fixtures/subscribers/second +0 -2
  164. data/test/fixtures/topic.rb +0 -20
  165. data/test/fixtures/topics/first +0 -9
  166. data/test/fixtures/topics/second +0 -8
  167. data/test/fixtures_test.rb +0 -20
  168. data/test/inflector_test.rb +0 -104
  169. data/test/inheritance_test.rb +0 -125
  170. data/test/lifecycle_test.rb +0 -110
  171. data/test/modules_test.rb +0 -21
  172. data/test/multiple_db_test.rb +0 -46
  173. data/test/pk_test.rb +0 -57
  174. data/test/reflection_test.rb +0 -78
  175. data/test/thread_safety_test.rb +0 -33
  176. data/test/transactions_test.rb +0 -83
  177. data/test/unconnected_test.rb +0 -24
  178. data/test/validations_test.rb +0 -126
@@ -1,326 +1,212 @@
1
- require 'benchmark'
2
1
  require 'date'
2
+ require 'bigdecimal'
3
+ require 'bigdecimal/util'
4
+ require 'active_support/core_ext/benchmark'
5
+
6
+ # TODO: Autoload these files
7
+ require 'active_record/connection_adapters/abstract/schema_definitions'
8
+ require 'active_record/connection_adapters/abstract/schema_statements'
9
+ require 'active_record/connection_adapters/abstract/database_statements'
10
+ require 'active_record/connection_adapters/abstract/quoting'
11
+ require 'active_record/connection_adapters/abstract/connection_pool'
12
+ require 'active_record/connection_adapters/abstract/connection_specification'
13
+ require 'active_record/connection_adapters/abstract/query_cache'
14
+ require 'active_record/connection_adapters/abstract/database_limits'
3
15
 
4
16
  module ActiveRecord
5
- class Base
6
- class ConnectionSpecification #:nodoc:
7
- attr_reader :config, :adapter_method
8
- def initialize (config, adapter_method)
9
- @config, @adapter_method = config, adapter_method
10
- end
11
- end
12
-
13
- # The class -> [adapter_method, config] map
14
- @@defined_connections = {}
15
-
16
- # Establishes the connection to the database. Accepts a hash as input where
17
- # the :adapter key must be specified with the name of a database adapter (in lower-case)
18
- # example for regular databases (MySQL, Postgresql, etc):
19
- #
20
- # ActiveRecord::Base.establish_connection(
21
- # :adapter => "mysql",
22
- # :host => "localhost",
23
- # :username => "myuser",
24
- # :password => "mypass",
25
- # :database => "somedatabase"
26
- # )
27
- #
28
- # Example for SQLite database:
29
- #
30
- # ActiveRecord::Base.establish_connection(
31
- # :adapter => "sqlite",
32
- # :dbfile => "path/to/dbfile"
33
- # )
34
- #
35
- # Also accepts keys as strings (for parsing from yaml for example):
36
- # ActiveRecord::Base.establish_connection(
37
- # "adapter" => "sqlite",
38
- # "dbfile" => "path/to/dbfile"
39
- # )
40
- #
41
- # The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
42
- # may be returned on an error.
43
- #
44
- # == Connecting to another database for a single model
45
- #
46
- # To support different connections for different classes, you can
47
- # simply call establish_connection with the classes you wish to have
48
- # different connections for:
17
+ module ConnectionAdapters # :nodoc:
18
+ # Active Record supports multiple database systems. AbstractAdapter and
19
+ # related classes form the abstraction layer which makes this possible.
20
+ # An AbstractAdapter represents a connection to a database, and provides an
21
+ # abstract interface for database-specific functionality such as establishing
22
+ # a connection, escaping values, building the right SQL fragments for ':offset'
23
+ # and ':limit' options, etc.
49
24
  #
50
- # class Courses < ActiveRecord::Base
51
- # ...
52
- # end
25
+ # All the concrete database adapters follow the interface laid down in this class.
26
+ # ActiveRecord::Base.connection returns an AbstractAdapter object, which
27
+ # you can use.
53
28
  #
54
- # Courses.establish_connection( ... )
55
- def self.establish_connection(spec)
56
- if spec.instance_of? ConnectionSpecification
57
- @@defined_connections[self] = spec
58
- else
59
- if spec.nil? then raise AdapterNotSpecified end
60
- symbolize_strings_in_hash(spec)
61
- unless spec.key?(:adapter) then raise AdapterNotSpecified end
62
-
63
- adapter_method = "#{spec[:adapter]}_connection"
64
- unless methods.include?(adapter_method) then raise AdapterNotFound end
65
- remove_connection
66
- @@defined_connections[self] = ConnectionSpecification.new(spec, adapter_method)
29
+ # Most of the methods in the adapter are useful during migrations. Most
30
+ # notably, the instance methods provided by SchemaStatement are very useful.
31
+ class AbstractAdapter
32
+ include Quoting, DatabaseStatements, SchemaStatements
33
+ include DatabaseLimits
34
+ include QueryCache
35
+ include ActiveSupport::Callbacks
36
+
37
+ define_callbacks :checkout, :checkin
38
+
39
+ def initialize(connection, logger = nil) #:nodoc:
40
+ @active = nil
41
+ @connection, @logger = connection, logger
42
+ @query_cache_enabled = false
43
+ @query_cache = {}
44
+ @instrumenter = ActiveSupport::Notifications.instrumenter
67
45
  end
68
- end
69
-
70
- # Locate the connection of the nearest super class. This can be an
71
- # active or defined connections: if it is the latter, it will be
72
- # opened and set as the active connection for the class it was defined
73
- # for (not necessarily the current class).
74
- def self.retrieve_connection #:nodoc:
75
- klass = self
76
- until klass == ActiveRecord::Base.superclass
77
- Thread.current['active_connections'] ||= {}
78
- if Thread.current['active_connections'][klass]
79
- return Thread.current['active_connections'][klass]
80
- elsif @@defined_connections[klass]
81
- klass.connection = @@defined_connections[klass]
82
- return self.connection
83
- end
84
- klass = klass.superclass
46
+
47
+ # Returns the human-readable name of the adapter. Use mixed case - one
48
+ # can always use downcase if needed.
49
+ def adapter_name
50
+ 'Abstract'
85
51
  end
86
- raise ConnectionNotEstablished
87
- end
88
-
89
- # Returns true if a connection that's accessible to this class have already been opened.
90
- def self.connected?
91
- klass = self
92
- until klass == ActiveRecord::Base.superclass
93
- if Thread.current['active_connections'].is_a?(Hash) && Thread.current['active_connections'][klass]
94
- return true
95
- else
96
- klass = klass.superclass
97
- end
52
+
53
+ # Does this adapter support migrations? Backend specific, as the
54
+ # abstract adapter always returns +false+.
55
+ def supports_migrations?
56
+ false
98
57
  end
99
- return false
100
- end
101
-
102
- # Remove the connection for this class. This will close the active
103
- # connection and the defined connection (if they exist). The result
104
- # can be used as argument for establish_connection, for easy
105
- # re-establishing of the connection.
106
- def self.remove_connection(klass=self)
107
- conn = @@defined_connections[klass]
108
- @@defined_connections.delete(klass)
109
- Thread.current['active_connections'] ||= {}
110
- Thread.current['active_connections'][klass] = nil
111
- conn.config if conn
112
- end
113
-
114
- # Set the connection for the class.
115
- def self.connection=(spec)
116
- raise ConnectionNotEstablished unless spec
117
- conn = self.send(spec.adapter_method, spec.config)
118
- Thread.current['active_connections'] ||= {}
119
- Thread.current['active_connections'][self] = conn
120
- end
121
58
 
122
- # Converts all strings in a hash to symbols.
123
- def self.symbolize_strings_in_hash(hash)
124
- hash.each do |key, value|
125
- if key.class == String
126
- hash.delete key
127
- hash[key.intern] = value
128
- end
59
+ # Can this adapter determine the primary key for tables not attached
60
+ # to an Active Record class, such as join tables? Backend specific, as
61
+ # the abstract adapter always returns +false+.
62
+ def supports_primary_key?
63
+ false
129
64
  end
130
- end
131
- end
132
65
 
133
- module ConnectionAdapters # :nodoc:
134
- class Column # :nodoc:
135
- attr_reader :name, :default, :type, :limit
136
- # The name should contain the name of the column, such as "name" in "name varchar(250)"
137
- # The default should contain the type-casted default of the column, such as 1 in "count int(11) DEFAULT 1"
138
- # The type parameter should either contain :integer, :float, :datetime, :date, :text, or :string
139
- # The sql_type is just used for extracting the limit, such as 10 in "varchar(10)"
140
- def initialize(name, default, sql_type = nil)
141
- @name, @default, @type = name, default, simplified_type(sql_type)
142
- @limit = extract_limit(sql_type) unless sql_type.nil?
66
+ # Does this adapter support using DISTINCT within COUNT? This is +true+
67
+ # for all adapters except sqlite.
68
+ def supports_count_distinct?
69
+ true
143
70
  end
144
71
 
145
- def default
146
- type_cast(@default)
72
+ # Does this adapter support DDL rollbacks in transactions? That is, would
73
+ # CREATE TABLE or ALTER TABLE get rolled back by a transaction? PostgreSQL,
74
+ # SQL Server, and others support this. MySQL and others do not.
75
+ def supports_ddl_transactions?
76
+ false
147
77
  end
148
78
 
149
- def klass
150
- case type
151
- when :integer then Fixnum
152
- when :float then Float
153
- when :datetime then Time
154
- when :date then Date
155
- when :text, :string then String
156
- when :boolean then Object
157
- end
79
+ # Does this adapter support savepoints? PostgreSQL and MySQL do, SQLite
80
+ # does not.
81
+ def supports_savepoints?
82
+ false
158
83
  end
159
-
160
- def type_cast(value)
161
- if value.nil? then return nil end
162
- case type
163
- when :string then value
164
- when :text then value
165
- when :integer then value.to_i
166
- when :float then value.to_f
167
- when :datetime then string_to_time(value)
168
- when :date then string_to_date(value)
169
- when :boolean then (value == "t" or value == true ? true : false)
170
- else value
171
- end
84
+
85
+ # Should primary key values be selected from their corresponding
86
+ # sequence before the insert statement? If true, next_sequence_value
87
+ # is called before each insert to set the record's primary key.
88
+ # This is false for all adapters but Firebird.
89
+ def prefetch_primary_key?(table_name = nil)
90
+ false
172
91
  end
173
-
174
- def human_name
175
- Base.human_attribute_name(@name)
92
+
93
+ # QUOTING ==================================================
94
+
95
+ # Override to return the quoted table name. Defaults to column quoting.
96
+ def quote_table_name(name)
97
+ quote_column_name(name)
176
98
  end
177
99
 
178
- private
179
- def string_to_date(string)
180
- return string if Date === string
181
- date_array = ParseDate.parsedate(string)
182
- # treat 0000-00-00 as nil
183
- Date.new(date_array[0], date_array[1], date_array[2]) rescue nil
184
- end
185
-
186
- def string_to_time(string)
187
- return string if Time === string
188
- time_array = ParseDate.parsedate(string).compact
189
- # treat 0000-00-00 00:00:00 as nil
190
- Time.local(*time_array) rescue nil
191
- end
100
+ # REFERENTIAL INTEGRITY ====================================
192
101
 
193
- def extract_limit(sql_type)
194
- $1.to_i if sql_type =~ /\((.*)\)/
195
- end
102
+ # Override to turn off referential integrity while executing <tt>&block</tt>.
103
+ def disable_referential_integrity
104
+ yield
105
+ end
196
106
 
197
- def simplified_type(field_type)
198
- case field_type
199
- when /int/i
200
- :integer
201
- when /float|double|decimal|numeric/i
202
- :float
203
- when /time/i
204
- :datetime
205
- when /date/i
206
- :date
207
- when /(c|b)lob/i, /text/i
208
- :text
209
- when /char/i, /string/i
210
- :string
211
- when /boolean/i
212
- :boolean
213
- end
214
- end
215
- end
107
+ # CONNECTION MANAGEMENT ====================================
216
108
 
217
- # All the concrete database adapters follow the interface laid down in this class.
218
- # You can use this interface directly by borrowing the database connection from the Base with
219
- # Base.connection.
220
- class AbstractAdapter
221
- @@row_even = true
109
+ # Checks whether the connection to the database is still active. This includes
110
+ # checking whether the database is actually capable of responding, i.e. whether
111
+ # the connection isn't stale.
112
+ def active?
113
+ @active != false
114
+ end
222
115
 
223
- include Benchmark
116
+ # Disconnects from the database if already connected, and establishes a
117
+ # new connection with the database.
118
+ def reconnect!
119
+ @active = true
120
+ end
224
121
 
225
- def initialize(connection, logger = nil) # :nodoc:
226
- @connection, @logger = connection, logger
227
- @runtime = 0
122
+ # Disconnects from the database if already connected. Otherwise, this
123
+ # method does nothing.
124
+ def disconnect!
125
+ @active = false
126
+ end
127
+
128
+ # Reset the state of this connection, directing the DBMS to clear
129
+ # transactions and other connection-related server-side state. Usually a
130
+ # database-dependent operation.
131
+ #
132
+ # The default implementation does nothing; the implementation should be
133
+ # overridden by concrete adapters.
134
+ def reset!
135
+ # this should be overridden by concrete adapters
228
136
  end
229
137
 
230
- # Returns an array of record hashes with the column names as a keys and fields as values.
231
- def select_all(sql, name = nil) end
232
-
233
- # Returns a record hash with the column names as a keys and fields as values.
234
- def select_one(sql, name = nil) end
138
+ # Returns true if its required to reload the connection between requests for development mode.
139
+ # This is not the case for Ruby/MySQL and it's not necessary for any adapters except SQLite.
140
+ def requires_reloading?
141
+ false
142
+ end
235
143
 
236
- # Returns an array of column objects for the table specified by +table_name+.
237
- def columns(table_name, name = nil) end
144
+ # Checks whether the connection to the database is still active (i.e. not stale).
145
+ # This is done under the hood by calling <tt>active?</tt>. If the connection
146
+ # is no longer active, then this method will reconnect to the database.
147
+ def verify!(*ignored)
148
+ reconnect! unless active?
149
+ end
238
150
 
239
- # Returns the last auto-generated ID from the affected table.
240
- def insert(sql, name = nil, pk = nil, id_value = nil) end
151
+ # Provides access to the underlying database driver for this adapter. For
152
+ # example, this method returns a Mysql object in case of MysqlAdapter,
153
+ # and a PGconn object in case of PostgreSQLAdapter.
154
+ #
155
+ # This is useful for when you need to call a proprietary method such as
156
+ # PostgreSQL's lo_* methods.
157
+ def raw_connection
158
+ @connection
159
+ end
241
160
 
242
- # Executes the update statement.
243
- def update(sql, name = nil) end
161
+ def open_transactions
162
+ @open_transactions ||= 0
163
+ end
244
164
 
245
- # Executes the delete statement.
246
- def delete(sql, name = nil) end
165
+ def increment_open_transactions
166
+ @open_transactions ||= 0
167
+ @open_transactions += 1
168
+ end
247
169
 
248
- def reset_runtime # :nodoc:
249
- rt = @runtime
250
- @runtime = 0
251
- return rt
170
+ def decrement_open_transactions
171
+ @open_transactions -= 1
252
172
  end
253
173
 
254
- # Begins the transaction (and turns off auto-committing).
255
- def begin_db_transaction() end
256
-
257
- # Commits the transaction (and turns on auto-committing).
258
- def commit_db_transaction() end
259
-
260
- # Rollsback the transaction (and turns on auto-committing). Must be done if the transaction block
261
- # raises an exception or returns false.
262
- def rollback_db_transaction() end
263
-
264
- def quote(value, column = nil)
265
- case value
266
- when String then "'#{value.gsub(/\\/,'\&\&').gsub(/'/, "''")}'" # ' (for ruby-mode)
267
- when NilClass then "NULL"
268
- when TrueClass then (column && column.type == :boolean ? "'t'" : "1")
269
- when FalseClass then (column && column.type == :boolean ? "'f'" : "0")
270
- when Float, Fixnum, Bignum, Date then "'#{value.to_s}'"
271
- when Time, DateTime then "'#{value.strftime("%Y-%m-%d %H:%M:%S")}'"
272
- else "'#{value.to_yaml.gsub(/'/, "''")}'"
273
- end
174
+ def transaction_joinable=(joinable)
175
+ @transaction_joinable = joinable
176
+ end
177
+
178
+ def create_savepoint
179
+ end
180
+
181
+ def rollback_to_savepoint
274
182
  end
275
183
 
276
- def quote_column_name(name)
277
- return name
184
+ def release_savepoint
278
185
  end
279
186
 
280
- # Returns a string of the CREATE TABLE SQL statements for recreating the entire structure of the database.
281
- def structure_dump() end
187
+ def current_savepoint_name
188
+ "active_record_#{open_transactions}"
189
+ end
282
190
 
283
191
  protected
284
- def log(sql, name, connection, &action)
285
- begin
286
- if @logger.nil?
287
- action.call(connection)
288
- else
289
- result = nil
290
- bm = measure { result = action.call(connection) }
291
- @runtime += bm.real
292
- log_info(sql, name, bm.real)
293
- result
294
- end
295
- rescue => e
296
- log_info("#{e.message}: #{sql}", name, 0)
297
- raise ActiveRecord::StatementInvalid, "#{e.message}: #{sql}"
192
+
193
+ def log(sql, name)
194
+ name ||= "SQL"
195
+ @instrumenter.instrument("sql.active_record",
196
+ :sql => sql, :name => name, :connection_id => object_id) do
197
+ yield
298
198
  end
199
+ rescue Exception => e
200
+ message = "#{e.class.name}: #{e.message}: #{sql}"
201
+ @logger.debug message if @logger
202
+ raise translate_exception(e, message)
299
203
  end
300
204
 
301
- def log_info(sql, name, runtime)
302
- if @logger.nil? then return end
303
-
304
- @logger.info(
305
- format_log_entry(
306
- "#{name.nil? ? "SQL" : name} (#{sprintf("%f", runtime)})",
307
- sql.gsub(/ +/, " ")
308
- )
309
- )
205
+ def translate_exception(e, message)
206
+ # override in derived class
207
+ ActiveRecord::StatementInvalid.new(message)
310
208
  end
311
209
 
312
- def format_log_entry(message, dump = nil)
313
- if @@row_even then
314
- @@row_even = false; caller_color = "1;32"; message_color = "4;33"; dump_color = "1;37"
315
- else
316
- @@row_even = true; caller_color = "1;36"; message_color = "4;35"; dump_color = "0;37"
317
- end
318
-
319
- log_entry = " \e[#{message_color}m#{message}\e[m"
320
- log_entry << " \e[#{dump_color}m%s\e[m" % dump if dump.kind_of?(String) && !dump.nil?
321
- log_entry << " \e[#{dump_color}m%p\e[m" % dump if !dump.kind_of?(String) && !dump.nil?
322
- log_entry
323
- end
324
210
  end
325
211
  end
326
212
  end