activerecord 3.0.0 → 4.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 (181) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +2102 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +35 -44
  5. data/examples/performance.rb +110 -100
  6. data/lib/active_record/aggregations.rb +59 -75
  7. data/lib/active_record/associations/alias_tracker.rb +76 -0
  8. data/lib/active_record/associations/association.rb +248 -0
  9. data/lib/active_record/associations/association_scope.rb +135 -0
  10. data/lib/active_record/associations/belongs_to_association.rb +60 -59
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -59
  12. data/lib/active_record/associations/builder/association.rb +108 -0
  13. data/lib/active_record/associations/builder/belongs_to.rb +98 -0
  14. data/lib/active_record/associations/builder/collection_association.rb +89 -0
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +39 -0
  16. data/lib/active_record/associations/builder/has_many.rb +15 -0
  17. data/lib/active_record/associations/builder/has_one.rb +25 -0
  18. data/lib/active_record/associations/builder/singular_association.rb +32 -0
  19. data/lib/active_record/associations/collection_association.rb +608 -0
  20. data/lib/active_record/associations/collection_proxy.rb +986 -0
  21. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +40 -112
  22. data/lib/active_record/associations/has_many_association.rb +83 -76
  23. data/lib/active_record/associations/has_many_through_association.rb +147 -66
  24. data/lib/active_record/associations/has_one_association.rb +67 -108
  25. data/lib/active_record/associations/has_one_through_association.rb +21 -25
  26. data/lib/active_record/associations/join_dependency/join_association.rb +174 -0
  27. data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
  28. data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
  29. data/lib/active_record/associations/join_dependency.rb +235 -0
  30. data/lib/active_record/associations/join_helper.rb +45 -0
  31. data/lib/active_record/associations/preloader/association.rb +121 -0
  32. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  33. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  34. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
  35. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  36. data/lib/active_record/associations/preloader/has_many_through.rb +19 -0
  37. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  38. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  39. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  40. data/lib/active_record/associations/preloader/through_association.rb +63 -0
  41. data/lib/active_record/associations/preloader.rb +178 -0
  42. data/lib/active_record/associations/singular_association.rb +64 -0
  43. data/lib/active_record/associations/through_association.rb +87 -0
  44. data/lib/active_record/associations.rb +512 -1224
  45. data/lib/active_record/attribute_assignment.rb +201 -0
  46. data/lib/active_record/attribute_methods/before_type_cast.rb +49 -12
  47. data/lib/active_record/attribute_methods/dirty.rb +51 -28
  48. data/lib/active_record/attribute_methods/primary_key.rb +94 -22
  49. data/lib/active_record/attribute_methods/query.rb +5 -4
  50. data/lib/active_record/attribute_methods/read.rb +63 -72
  51. data/lib/active_record/attribute_methods/serialization.rb +162 -0
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -41
  53. data/lib/active_record/attribute_methods/write.rb +39 -13
  54. data/lib/active_record/attribute_methods.rb +362 -29
  55. data/lib/active_record/autosave_association.rb +132 -75
  56. data/lib/active_record/base.rb +83 -1627
  57. data/lib/active_record/callbacks.rb +69 -47
  58. data/lib/active_record/coders/yaml_column.rb +38 -0
  59. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +411 -138
  60. data/lib/active_record/connection_adapters/abstract/database_limits.rb +21 -11
  61. data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -173
  62. data/lib/active_record/connection_adapters/abstract/query_cache.rb +36 -22
  63. data/lib/active_record/connection_adapters/abstract/quoting.rb +82 -25
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +176 -414
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +562 -232
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +281 -53
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +782 -0
  70. data/lib/active_record/connection_adapters/column.rb +318 -0
  71. data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
  72. data/lib/active_record/connection_adapters/mysql2_adapter.rb +273 -0
  73. data/lib/active_record/connection_adapters/mysql_adapter.rb +365 -450
  74. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
  75. data/lib/active_record/connection_adapters/postgresql/cast.rb +152 -0
  76. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
  77. data/lib/active_record/connection_adapters/postgresql/oid.rb +366 -0
  78. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -0
  79. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  80. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +489 -0
  81. data/lib/active_record/connection_adapters/postgresql_adapter.rb +672 -752
  82. data/lib/active_record/connection_adapters/schema_cache.rb +129 -0
  83. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +588 -17
  84. data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
  85. data/lib/active_record/connection_handling.rb +98 -0
  86. data/lib/active_record/core.rb +463 -0
  87. data/lib/active_record/counter_cache.rb +108 -101
  88. data/lib/active_record/dynamic_matchers.rb +131 -0
  89. data/lib/active_record/errors.rb +54 -13
  90. data/lib/active_record/explain.rb +38 -0
  91. data/lib/active_record/explain_registry.rb +30 -0
  92. data/lib/active_record/explain_subscriber.rb +29 -0
  93. data/lib/active_record/fixture_set/file.rb +55 -0
  94. data/lib/active_record/fixtures.rb +703 -785
  95. data/lib/active_record/inheritance.rb +200 -0
  96. data/lib/active_record/integration.rb +60 -0
  97. data/lib/active_record/locale/en.yml +8 -1
  98. data/lib/active_record/locking/optimistic.rb +69 -60
  99. data/lib/active_record/locking/pessimistic.rb +34 -12
  100. data/lib/active_record/log_subscriber.rb +40 -6
  101. data/lib/active_record/migration/command_recorder.rb +164 -0
  102. data/lib/active_record/migration/join_table.rb +15 -0
  103. data/lib/active_record/migration.rb +614 -216
  104. data/lib/active_record/model_schema.rb +345 -0
  105. data/lib/active_record/nested_attributes.rb +248 -119
  106. data/lib/active_record/null_relation.rb +65 -0
  107. data/lib/active_record/persistence.rb +275 -57
  108. data/lib/active_record/query_cache.rb +29 -9
  109. data/lib/active_record/querying.rb +62 -0
  110. data/lib/active_record/railtie.rb +135 -21
  111. data/lib/active_record/railties/console_sandbox.rb +5 -0
  112. data/lib/active_record/railties/controller_runtime.rb +17 -5
  113. data/lib/active_record/railties/databases.rake +249 -359
  114. data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
  115. data/lib/active_record/readonly_attributes.rb +30 -0
  116. data/lib/active_record/reflection.rb +283 -103
  117. data/lib/active_record/relation/batches.rb +38 -34
  118. data/lib/active_record/relation/calculations.rb +252 -139
  119. data/lib/active_record/relation/delegation.rb +125 -0
  120. data/lib/active_record/relation/finder_methods.rb +182 -188
  121. data/lib/active_record/relation/merger.rb +161 -0
  122. data/lib/active_record/relation/predicate_builder.rb +86 -21
  123. data/lib/active_record/relation/query_methods.rb +917 -134
  124. data/lib/active_record/relation/spawn_methods.rb +53 -92
  125. data/lib/active_record/relation.rb +405 -143
  126. data/lib/active_record/result.rb +67 -0
  127. data/lib/active_record/runtime_registry.rb +17 -0
  128. data/lib/active_record/sanitization.rb +168 -0
  129. data/lib/active_record/schema.rb +20 -14
  130. data/lib/active_record/schema_dumper.rb +55 -46
  131. data/lib/active_record/schema_migration.rb +39 -0
  132. data/lib/active_record/scoping/default.rb +146 -0
  133. data/lib/active_record/scoping/named.rb +175 -0
  134. data/lib/active_record/scoping.rb +82 -0
  135. data/lib/active_record/serialization.rb +8 -46
  136. data/lib/active_record/serializers/xml_serializer.rb +21 -68
  137. data/lib/active_record/statement_cache.rb +26 -0
  138. data/lib/active_record/store.rb +156 -0
  139. data/lib/active_record/tasks/database_tasks.rb +203 -0
  140. data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
  141. data/lib/active_record/tasks/mysql_database_tasks.rb +143 -0
  142. data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
  143. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  144. data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
  145. data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
  146. data/lib/active_record/test_case.rb +57 -28
  147. data/lib/active_record/timestamp.rb +49 -18
  148. data/lib/active_record/transactions.rb +106 -63
  149. data/lib/active_record/translation.rb +22 -0
  150. data/lib/active_record/validations/associated.rb +25 -24
  151. data/lib/active_record/validations/presence.rb +65 -0
  152. data/lib/active_record/validations/uniqueness.rb +123 -83
  153. data/lib/active_record/validations.rb +29 -29
  154. data/lib/active_record/version.rb +7 -5
  155. data/lib/active_record.rb +83 -34
  156. data/lib/rails/generators/active_record/migration/migration_generator.rb +46 -9
  157. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +19 -0
  158. data/lib/rails/generators/active_record/migration/templates/migration.rb +30 -8
  159. data/lib/rails/generators/active_record/model/model_generator.rb +15 -5
  160. data/lib/rails/generators/active_record/model/templates/model.rb +7 -2
  161. data/lib/rails/generators/active_record/model/templates/module.rb +3 -1
  162. data/lib/rails/generators/active_record.rb +4 -8
  163. metadata +163 -121
  164. data/CHANGELOG +0 -6023
  165. data/examples/associations.png +0 -0
  166. data/lib/active_record/association_preload.rb +0 -403
  167. data/lib/active_record/associations/association_collection.rb +0 -562
  168. data/lib/active_record/associations/association_proxy.rb +0 -295
  169. data/lib/active_record/associations/through_association_scope.rb +0 -154
  170. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -113
  171. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -401
  172. data/lib/active_record/dynamic_finder_match.rb +0 -53
  173. data/lib/active_record/dynamic_scope_match.rb +0 -32
  174. data/lib/active_record/named_scope.rb +0 -138
  175. data/lib/active_record/observer.rb +0 -140
  176. data/lib/active_record/session_store.rb +0 -340
  177. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -16
  178. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  179. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -2
  180. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -24
  181. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -16
@@ -0,0 +1,203 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class Transaction #:nodoc:
4
+ attr_reader :connection
5
+
6
+ def initialize(connection)
7
+ @connection = connection
8
+ @state = TransactionState.new
9
+ end
10
+
11
+ def state
12
+ @state
13
+ end
14
+ end
15
+
16
+ class TransactionState
17
+ attr_accessor :parent
18
+
19
+ VALID_STATES = Set.new([:committed, :rolledback, nil])
20
+
21
+ def initialize(state = nil)
22
+ @state = state
23
+ @parent = nil
24
+ end
25
+
26
+ def committed?
27
+ @state == :committed
28
+ end
29
+
30
+ def rolledback?
31
+ @state == :rolledback
32
+ end
33
+
34
+ def set_state(state)
35
+ if !VALID_STATES.include?(state)
36
+ raise ArgumentError, "Invalid transaction state: #{state}"
37
+ end
38
+ @state = state
39
+ end
40
+ end
41
+
42
+ class ClosedTransaction < Transaction #:nodoc:
43
+ def number
44
+ 0
45
+ end
46
+
47
+ def begin(options = {})
48
+ RealTransaction.new(connection, self, options)
49
+ end
50
+
51
+ def closed?
52
+ true
53
+ end
54
+
55
+ def open?
56
+ false
57
+ end
58
+
59
+ def joinable?
60
+ false
61
+ end
62
+
63
+ # This is a noop when there are no open transactions
64
+ def add_record(record)
65
+ end
66
+ end
67
+
68
+ class OpenTransaction < Transaction #:nodoc:
69
+ attr_reader :parent, :records
70
+ attr_writer :joinable
71
+
72
+ def initialize(connection, parent, options = {})
73
+ super connection
74
+
75
+ @parent = parent
76
+ @records = []
77
+ @finishing = false
78
+ @joinable = options.fetch(:joinable, true)
79
+ end
80
+
81
+ # This state is necessary so that we correctly handle stuff that might
82
+ # happen in a commit/rollback. But it's kinda distasteful. Maybe we can
83
+ # find a better way to structure it in the future.
84
+ def finishing?
85
+ @finishing
86
+ end
87
+
88
+ def joinable?
89
+ @joinable && !finishing?
90
+ end
91
+
92
+ def number
93
+ if finishing?
94
+ parent.number
95
+ else
96
+ parent.number + 1
97
+ end
98
+ end
99
+
100
+ def begin(options = {})
101
+ if finishing?
102
+ parent.begin
103
+ else
104
+ SavepointTransaction.new(connection, self, options)
105
+ end
106
+ end
107
+
108
+ def rollback
109
+ @finishing = true
110
+ perform_rollback
111
+ parent
112
+ end
113
+
114
+ def commit
115
+ @finishing = true
116
+ perform_commit
117
+ parent
118
+ end
119
+
120
+ def add_record(record)
121
+ if record.has_transactional_callbacks?
122
+ records << record
123
+ else
124
+ record.set_transaction_state(@state)
125
+ end
126
+ end
127
+
128
+ def rollback_records
129
+ @state.set_state(:rolledback)
130
+ records.uniq.each do |record|
131
+ begin
132
+ record.rolledback!(parent.closed?)
133
+ rescue => e
134
+ record.logger.error(e) if record.respond_to?(:logger) && record.logger
135
+ end
136
+ end
137
+ end
138
+
139
+ def commit_records
140
+ @state.set_state(:committed)
141
+ records.uniq.each do |record|
142
+ begin
143
+ record.committed!
144
+ rescue => e
145
+ record.logger.error(e) if record.respond_to?(:logger) && record.logger
146
+ end
147
+ end
148
+ end
149
+
150
+ def closed?
151
+ false
152
+ end
153
+
154
+ def open?
155
+ true
156
+ end
157
+ end
158
+
159
+ class RealTransaction < OpenTransaction #:nodoc:
160
+ def initialize(connection, parent, options = {})
161
+ super
162
+
163
+ if options[:isolation]
164
+ connection.begin_isolated_db_transaction(options[:isolation])
165
+ else
166
+ connection.begin_db_transaction
167
+ end
168
+ end
169
+
170
+ def perform_rollback
171
+ connection.rollback_db_transaction
172
+ rollback_records
173
+ end
174
+
175
+ def perform_commit
176
+ connection.commit_db_transaction
177
+ commit_records
178
+ end
179
+ end
180
+
181
+ class SavepointTransaction < OpenTransaction #:nodoc:
182
+ def initialize(connection, parent, options = {})
183
+ if options[:isolation]
184
+ raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
185
+ end
186
+
187
+ super
188
+ connection.create_savepoint
189
+ end
190
+
191
+ def perform_rollback
192
+ connection.rollback_to_savepoint
193
+ rollback_records
194
+ end
195
+
196
+ def perform_commit
197
+ @state.set_state(:committed)
198
+ @state.parent = parent.state
199
+ connection.release_savepoint
200
+ end
201
+ end
202
+ end
203
+ end
@@ -2,19 +2,45 @@ require 'date'
2
2
  require 'bigdecimal'
3
3
  require 'bigdecimal/util'
4
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'
5
+ require 'active_record/connection_adapters/schema_cache'
6
+ require 'active_record/connection_adapters/abstract/schema_dumper'
7
+ require 'monitor'
15
8
 
16
9
  module ActiveRecord
17
10
  module ConnectionAdapters # :nodoc:
11
+ extend ActiveSupport::Autoload
12
+
13
+ autoload :Column
14
+ autoload :ConnectionSpecification
15
+
16
+ autoload_at 'active_record/connection_adapters/abstract/schema_definitions' do
17
+ autoload :IndexDefinition
18
+ autoload :ColumnDefinition
19
+ autoload :TableDefinition
20
+ autoload :Table
21
+ autoload :AlterTable
22
+ end
23
+
24
+ autoload_at 'active_record/connection_adapters/abstract/connection_pool' do
25
+ autoload :ConnectionHandler
26
+ autoload :ConnectionManagement
27
+ end
28
+
29
+ autoload_under 'abstract' do
30
+ autoload :SchemaStatements
31
+ autoload :DatabaseStatements
32
+ autoload :DatabaseLimits
33
+ autoload :Quoting
34
+ autoload :ConnectionPool
35
+ autoload :QueryCache
36
+ end
37
+
38
+ autoload_at 'active_record/connection_adapters/abstract/transaction' do
39
+ autoload :ClosedTransaction
40
+ autoload :RealTransaction
41
+ autoload :SavepointTransaction
42
+ end
43
+
18
44
  # Active Record supports multiple database systems. AbstractAdapter and
19
45
  # related classes form the abstraction layer which makes this possible.
20
46
  # An AbstractAdapter represents a connection to a database, and provides an
@@ -33,68 +59,245 @@ module ActiveRecord
33
59
  include DatabaseLimits
34
60
  include QueryCache
35
61
  include ActiveSupport::Callbacks
62
+ include MonitorMixin
63
+ include ColumnDumper
64
+
65
+ SIMPLE_INT = /\A\d+\z/
36
66
 
37
67
  define_callbacks :checkout, :checkin
38
68
 
39
- def initialize(connection, logger = nil) #:nodoc:
40
- @active = nil
41
- @connection, @logger = connection, logger
69
+ attr_accessor :visitor, :pool
70
+ attr_reader :schema_cache, :last_use, :in_use, :logger
71
+ alias :in_use? :in_use
72
+
73
+ def self.type_cast_config_to_integer(config)
74
+ if config =~ SIMPLE_INT
75
+ config.to_i
76
+ else
77
+ config
78
+ end
79
+ end
80
+
81
+ def self.type_cast_config_to_boolean(config)
82
+ if config == "false"
83
+ false
84
+ else
85
+ config
86
+ end
87
+ end
88
+
89
+ def initialize(connection, logger = nil, pool = nil) #:nodoc:
90
+ super()
91
+
92
+ @connection = connection
93
+ @in_use = false
94
+ @instrumenter = ActiveSupport::Notifications.instrumenter
95
+ @last_use = false
96
+ @logger = logger
97
+ @pool = pool
98
+ @query_cache = Hash.new { |h,sql| h[sql] = {} }
42
99
  @query_cache_enabled = false
43
- @query_cache = {}
44
- @instrumenter = ActiveSupport::Notifications.instrumenter
100
+ @schema_cache = SchemaCache.new self
101
+ @visitor = nil
102
+ end
103
+
104
+ def valid_type?(type)
105
+ true
106
+ end
107
+
108
+ class SchemaCreation
109
+ def initialize(conn)
110
+ @conn = conn
111
+ @cache = {}
112
+ end
113
+
114
+ def accept(o)
115
+ m = @cache[o.class] ||= "visit_#{o.class.name.split('::').last}"
116
+ send m, o
117
+ end
118
+
119
+ private
120
+
121
+ def visit_AlterTable(o)
122
+ sql = "ALTER TABLE #{quote_table_name(o.name)} "
123
+ sql << o.adds.map { |col| visit_AddColumn col }.join(' ')
124
+ end
125
+
126
+ def visit_AddColumn(o)
127
+ sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
128
+ sql = "ADD #{quote_column_name(o.name)} #{sql_type}"
129
+ add_column_options!(sql, column_options(o))
130
+ end
131
+
132
+ def visit_ColumnDefinition(o)
133
+ sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
134
+ column_sql = "#{quote_column_name(o.name)} #{sql_type}"
135
+ add_column_options!(column_sql, column_options(o)) unless o.primary_key?
136
+ column_sql
137
+ end
138
+
139
+ def visit_TableDefinition(o)
140
+ create_sql = "CREATE#{' TEMPORARY' if o.temporary} TABLE "
141
+ create_sql << "#{quote_table_name(o.name)} ("
142
+ create_sql << o.columns.map { |c| accept c }.join(', ')
143
+ create_sql << ") #{o.options}"
144
+ create_sql
145
+ end
146
+
147
+ def column_options(o)
148
+ column_options = {}
149
+ column_options[:null] = o.null unless o.null.nil?
150
+ column_options[:default] = o.default unless o.default.nil?
151
+ column_options[:column] = o
152
+ column_options
153
+ end
154
+
155
+ def quote_column_name(name)
156
+ @conn.quote_column_name name
157
+ end
158
+
159
+ def quote_table_name(name)
160
+ @conn.quote_table_name name
161
+ end
162
+
163
+ def type_to_sql(type, limit, precision, scale)
164
+ @conn.type_to_sql type.to_sym, limit, precision, scale
165
+ end
166
+
167
+ def add_column_options!(column_sql, column_options)
168
+ @conn.add_column_options! column_sql, column_options
169
+ column_sql
170
+ end
45
171
  end
46
172
 
47
- # Returns the human-readable name of the adapter. Use mixed case - one
173
+ def schema_creation
174
+ SchemaCreation.new self
175
+ end
176
+
177
+ def lease
178
+ synchronize do
179
+ unless in_use
180
+ @in_use = true
181
+ @last_use = Time.now
182
+ end
183
+ end
184
+ end
185
+
186
+ def schema_cache=(cache)
187
+ cache.connection = self
188
+ @schema_cache = cache
189
+ end
190
+
191
+ def expire
192
+ @in_use = false
193
+ end
194
+
195
+ def unprepared_visitor
196
+ self.class::BindSubstitution.new self
197
+ end
198
+
199
+ def unprepared_statement
200
+ old, @visitor = @visitor, unprepared_visitor
201
+ yield
202
+ ensure
203
+ @visitor = old
204
+ end
205
+
206
+ # Returns the human-readable name of the adapter. Use mixed case - one
48
207
  # can always use downcase if needed.
49
208
  def adapter_name
50
209
  'Abstract'
51
210
  end
52
211
 
53
- # Does this adapter support migrations? Backend specific, as the
212
+ # Does this adapter support migrations? Backend specific, as the
54
213
  # abstract adapter always returns +false+.
55
214
  def supports_migrations?
56
215
  false
57
216
  end
58
217
 
59
218
  # Can this adapter determine the primary key for tables not attached
60
- # to an Active Record class, such as join tables? Backend specific, as
219
+ # to an Active Record class, such as join tables? Backend specific, as
61
220
  # the abstract adapter always returns +false+.
62
221
  def supports_primary_key?
63
222
  false
64
223
  end
65
224
 
66
- # Does this adapter support using DISTINCT within COUNT? This is +true+
225
+ # Does this adapter support using DISTINCT within COUNT? This is +true+
67
226
  # for all adapters except sqlite.
68
227
  def supports_count_distinct?
69
228
  true
70
229
  end
71
230
 
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.
231
+ # Does this adapter support DDL rollbacks in transactions? That is, would
232
+ # CREATE TABLE or ALTER TABLE get rolled back by a transaction? PostgreSQL,
233
+ # SQL Server, and others support this. MySQL and others do not.
75
234
  def supports_ddl_transactions?
76
235
  false
77
236
  end
78
237
 
79
- # Does this adapter support savepoints? PostgreSQL and MySQL do, SQLite
80
- # does not.
238
+ def supports_bulk_alter?
239
+ false
240
+ end
241
+
242
+ # Does this adapter support savepoints? PostgreSQL and MySQL do,
243
+ # SQLite < 3.6.8 does not.
81
244
  def supports_savepoints?
82
245
  false
83
246
  end
84
247
 
85
248
  # Should primary key values be selected from their corresponding
86
- # sequence before the insert statement? If true, next_sequence_value
249
+ # sequence before the insert statement? If true, next_sequence_value
87
250
  # is called before each insert to set the record's primary key.
88
251
  # This is false for all adapters but Firebird.
89
252
  def prefetch_primary_key?(table_name = nil)
90
253
  false
91
254
  end
92
255
 
256
+ # Does this adapter support index sort order?
257
+ def supports_index_sort_order?
258
+ false
259
+ end
260
+
261
+ # Does this adapter support partial indices?
262
+ def supports_partial_index?
263
+ false
264
+ end
265
+
266
+ # Does this adapter support explain? As of this writing sqlite3,
267
+ # mysql2, and postgresql are the only ones that do.
268
+ def supports_explain?
269
+ false
270
+ end
271
+
272
+ # Does this adapter support setting the isolation level for a transaction?
273
+ def supports_transaction_isolation?
274
+ false
275
+ end
276
+
277
+ # Does this adapter support database extensions? As of this writing only
278
+ # postgresql does.
279
+ def supports_extensions?
280
+ false
281
+ end
282
+
283
+ # A list of extensions, to be filled in by adapters that support them. At
284
+ # the moment only postgresql does.
285
+ def extensions
286
+ []
287
+ end
288
+
289
+ # A list of index algorithms, to be filled by adapters that support them.
290
+ # MySQL and PostgreSQL have support for them right now.
291
+ def index_algorithms
292
+ {}
293
+ end
294
+
93
295
  # QUOTING ==================================================
94
296
 
95
- # Override to return the quoted table name. Defaults to column quoting.
96
- def quote_table_name(name)
97
- quote_column_name(name)
297
+ # Returns a bind substitution value given a +column+ and list of current
298
+ # +binds+.
299
+ def substitute_at(column, index)
300
+ Arel::Nodes::BindParam.new '?'
98
301
  end
99
302
 
100
303
  # REFERENTIAL INTEGRITY ====================================
@@ -110,19 +313,21 @@ module ActiveRecord
110
313
  # checking whether the database is actually capable of responding, i.e. whether
111
314
  # the connection isn't stale.
112
315
  def active?
113
- @active != false
114
316
  end
115
317
 
116
318
  # Disconnects from the database if already connected, and establishes a
117
- # new connection with the database.
319
+ # new connection with the database. Implementors should call super if they
320
+ # override the default implementation.
118
321
  def reconnect!
119
- @active = true
322
+ clear_cache!
323
+ reset_transaction
120
324
  end
121
325
 
122
326
  # Disconnects from the database if already connected. Otherwise, this
123
327
  # method does nothing.
124
328
  def disconnect!
125
- @active = false
329
+ clear_cache!
330
+ reset_transaction
126
331
  end
127
332
 
128
333
  # Reset the state of this connection, directing the DBMS to clear
@@ -135,6 +340,13 @@ module ActiveRecord
135
340
  # this should be overridden by concrete adapters
136
341
  end
137
342
 
343
+ ###
344
+ # Clear any caching the database adapter may be doing, for example
345
+ # clearing the prepared statement cache. This is database specific.
346
+ def clear_cache!
347
+ # this should be overridden by concrete adapters
348
+ end
349
+
138
350
  # Returns true if its required to reload the connection between requests for development mode.
139
351
  # This is not the case for Ruby/MySQL and it's not necessary for any adapters except SQLite.
140
352
  def requires_reloading?
@@ -159,20 +371,21 @@ module ActiveRecord
159
371
  end
160
372
 
161
373
  def open_transactions
162
- @open_transactions ||= 0
374
+ @transaction.number
163
375
  end
164
376
 
165
377
  def increment_open_transactions
166
- @open_transactions ||= 0
167
- @open_transactions += 1
378
+ ActiveSupport::Deprecation.warn "#increment_open_transactions is deprecated and has no effect"
168
379
  end
169
380
 
170
381
  def decrement_open_transactions
171
- @open_transactions -= 1
382
+ ActiveSupport::Deprecation.warn "#decrement_open_transactions is deprecated and has no effect"
172
383
  end
173
384
 
174
385
  def transaction_joinable=(joinable)
175
- @transaction_joinable = joinable
386
+ message = "#transaction_joinable= is deprecated. Please pass the :joinable option to #begin_transaction instead."
387
+ ActiveSupport::Deprecation.warn message
388
+ @transaction.joinable = joinable
176
389
  end
177
390
 
178
391
  def create_savepoint
@@ -184,29 +397,44 @@ module ActiveRecord
184
397
  def release_savepoint
185
398
  end
186
399
 
400
+ def case_sensitive_modifier(node)
401
+ node
402
+ end
403
+
404
+ def case_insensitive_comparison(table, attribute, column, value)
405
+ table[attribute].lower.eq(table.lower(value))
406
+ end
407
+
187
408
  def current_savepoint_name
188
409
  "active_record_#{open_transactions}"
189
410
  end
190
411
 
191
- protected
412
+ # Check the connection back in to the connection pool
413
+ def close
414
+ pool.checkin self
415
+ end
192
416
 
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
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)
203
- end
417
+ protected
204
418
 
205
- def translate_exception(e, message)
206
- # override in derived class
207
- ActiveRecord::StatementInvalid.new(message)
208
- end
419
+ def log(sql, name = "SQL", binds = [])
420
+ @instrumenter.instrument(
421
+ "sql.active_record",
422
+ :sql => sql,
423
+ :name => name,
424
+ :connection_id => object_id,
425
+ :binds => binds) { yield }
426
+ rescue => e
427
+ message = "#{e.class.name}: #{e.message}: #{sql}"
428
+ @logger.error message if @logger
429
+ exception = translate_exception(e, message)
430
+ exception.set_backtrace e.backtrace
431
+ raise exception
432
+ end
209
433
 
434
+ def translate_exception(exception, message)
435
+ # override in derived class
436
+ ActiveRecord::StatementInvalid.new(message, exception)
437
+ end
210
438
  end
211
439
  end
212
440
  end