activerecord 3.1.10 → 4.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (237) hide show
  1. checksums.yaml +6 -6
  2. data/CHANGELOG.md +1837 -338
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +39 -43
  5. data/examples/performance.rb +51 -20
  6. data/examples/simple.rb +4 -4
  7. data/lib/active_record/aggregations.rb +57 -43
  8. data/lib/active_record/association_relation.rb +35 -0
  9. data/lib/active_record/associations/alias_tracker.rb +47 -39
  10. data/lib/active_record/associations/association.rb +71 -85
  11. data/lib/active_record/associations/association_scope.rb +138 -89
  12. data/lib/active_record/associations/belongs_to_association.rb +65 -25
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +9 -3
  14. data/lib/active_record/associations/builder/association.rb +125 -29
  15. data/lib/active_record/associations/builder/belongs_to.rb +91 -60
  16. data/lib/active_record/associations/builder/collection_association.rb +69 -49
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +113 -42
  18. data/lib/active_record/associations/builder/has_many.rb +8 -64
  19. data/lib/active_record/associations/builder/has_one.rb +12 -52
  20. data/lib/active_record/associations/builder/singular_association.rb +22 -29
  21. data/lib/active_record/associations/collection_association.rb +294 -187
  22. data/lib/active_record/associations/collection_proxy.rb +961 -94
  23. data/lib/active_record/associations/foreign_association.rb +11 -0
  24. data/lib/active_record/associations/has_many_association.rb +118 -23
  25. data/lib/active_record/associations/has_many_through_association.rb +115 -45
  26. data/lib/active_record/associations/has_one_association.rb +57 -24
  27. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  28. data/lib/active_record/associations/join_dependency/join_association.rb +76 -102
  29. data/lib/active_record/associations/join_dependency/join_base.rb +7 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +30 -37
  31. data/lib/active_record/associations/join_dependency.rb +230 -156
  32. data/lib/active_record/associations/preloader/association.rb +96 -55
  33. data/lib/active_record/associations/preloader/collection_association.rb +3 -3
  34. data/lib/active_record/associations/preloader/has_many_through.rb +7 -3
  35. data/lib/active_record/associations/preloader/has_one.rb +1 -1
  36. data/lib/active_record/associations/preloader/singular_association.rb +3 -3
  37. data/lib/active_record/associations/preloader/through_association.rb +61 -32
  38. data/lib/active_record/associations/preloader.rb +113 -87
  39. data/lib/active_record/associations/singular_association.rb +29 -13
  40. data/lib/active_record/associations/through_association.rb +37 -19
  41. data/lib/active_record/associations.rb +505 -371
  42. data/lib/active_record/attribute.rb +163 -0
  43. data/lib/active_record/attribute_assignment.rb +212 -0
  44. data/lib/active_record/attribute_decorators.rb +66 -0
  45. data/lib/active_record/attribute_methods/before_type_cast.rb +52 -7
  46. data/lib/active_record/attribute_methods/dirty.rb +141 -51
  47. data/lib/active_record/attribute_methods/primary_key.rb +87 -36
  48. data/lib/active_record/attribute_methods/query.rb +5 -4
  49. data/lib/active_record/attribute_methods/read.rb +74 -117
  50. data/lib/active_record/attribute_methods/serialization.rb +70 -0
  51. data/lib/active_record/attribute_methods/time_zone_conversion.rb +49 -47
  52. data/lib/active_record/attribute_methods/write.rb +60 -21
  53. data/lib/active_record/attribute_methods.rb +409 -48
  54. data/lib/active_record/attribute_set/builder.rb +106 -0
  55. data/lib/active_record/attribute_set.rb +81 -0
  56. data/lib/active_record/attributes.rb +147 -0
  57. data/lib/active_record/autosave_association.rb +279 -232
  58. data/lib/active_record/base.rb +84 -1969
  59. data/lib/active_record/callbacks.rb +66 -28
  60. data/lib/active_record/coders/json.rb +13 -0
  61. data/lib/active_record/coders/yaml_column.rb +18 -21
  62. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +422 -243
  63. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  64. data/lib/active_record/connection_adapters/abstract/database_statements.rb +170 -194
  65. data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -19
  66. data/lib/active_record/connection_adapters/abstract/quoting.rb +79 -57
  67. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  68. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +125 -0
  69. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +273 -170
  70. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +50 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +731 -254
  72. data/lib/active_record/connection_adapters/abstract/transaction.rb +215 -0
  73. data/lib/active_record/connection_adapters/abstract_adapter.rb +339 -95
  74. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +946 -0
  75. data/lib/active_record/connection_adapters/column.rb +33 -221
  76. data/lib/active_record/connection_adapters/connection_specification.rb +275 -0
  77. data/lib/active_record/connection_adapters/mysql2_adapter.rb +140 -602
  78. data/lib/active_record/connection_adapters/mysql_adapter.rb +254 -756
  79. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +93 -0
  80. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  81. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +232 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +100 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +19 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +36 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +108 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +596 -0
  112. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  113. data/lib/active_record/connection_adapters/postgresql_adapter.rb +445 -902
  114. data/lib/active_record/connection_adapters/schema_cache.rb +94 -0
  115. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +578 -25
  116. data/lib/active_record/connection_handling.rb +132 -0
  117. data/lib/active_record/core.rb +579 -0
  118. data/lib/active_record/counter_cache.rb +159 -102
  119. data/lib/active_record/dynamic_matchers.rb +140 -0
  120. data/lib/active_record/enum.rb +197 -0
  121. data/lib/active_record/errors.rb +102 -34
  122. data/lib/active_record/explain.rb +38 -0
  123. data/lib/active_record/explain_registry.rb +30 -0
  124. data/lib/active_record/explain_subscriber.rb +29 -0
  125. data/lib/active_record/fixture_set/file.rb +56 -0
  126. data/lib/active_record/fixtures.rb +318 -260
  127. data/lib/active_record/gem_version.rb +15 -0
  128. data/lib/active_record/inheritance.rb +247 -0
  129. data/lib/active_record/integration.rb +113 -0
  130. data/lib/active_record/legacy_yaml_adapter.rb +30 -0
  131. data/lib/active_record/locale/en.yml +8 -1
  132. data/lib/active_record/locking/optimistic.rb +80 -52
  133. data/lib/active_record/locking/pessimistic.rb +27 -5
  134. data/lib/active_record/log_subscriber.rb +25 -18
  135. data/lib/active_record/migration/command_recorder.rb +130 -38
  136. data/lib/active_record/migration/join_table.rb +15 -0
  137. data/lib/active_record/migration.rb +532 -201
  138. data/lib/active_record/model_schema.rb +342 -0
  139. data/lib/active_record/nested_attributes.rb +229 -139
  140. data/lib/active_record/no_touching.rb +52 -0
  141. data/lib/active_record/null_relation.rb +81 -0
  142. data/lib/active_record/persistence.rb +304 -99
  143. data/lib/active_record/query_cache.rb +25 -43
  144. data/lib/active_record/querying.rb +68 -0
  145. data/lib/active_record/railtie.rb +86 -45
  146. data/lib/active_record/railties/console_sandbox.rb +3 -4
  147. data/lib/active_record/railties/controller_runtime.rb +7 -4
  148. data/lib/active_record/railties/databases.rake +198 -377
  149. data/lib/active_record/railties/jdbcmysql_error.rb +2 -2
  150. data/lib/active_record/readonly_attributes.rb +23 -0
  151. data/lib/active_record/reflection.rb +516 -165
  152. data/lib/active_record/relation/batches.rb +96 -45
  153. data/lib/active_record/relation/calculations.rb +221 -144
  154. data/lib/active_record/relation/delegation.rb +140 -0
  155. data/lib/active_record/relation/finder_methods.rb +362 -243
  156. data/lib/active_record/relation/merger.rb +193 -0
  157. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  158. data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
  159. data/lib/active_record/relation/predicate_builder.rb +135 -41
  160. data/lib/active_record/relation/query_methods.rb +982 -155
  161. data/lib/active_record/relation/spawn_methods.rb +50 -110
  162. data/lib/active_record/relation.rb +371 -180
  163. data/lib/active_record/result.rb +109 -12
  164. data/lib/active_record/runtime_registry.rb +22 -0
  165. data/lib/active_record/sanitization.rb +191 -0
  166. data/lib/active_record/schema.rb +19 -13
  167. data/lib/active_record/schema_dumper.rb +111 -61
  168. data/lib/active_record/schema_migration.rb +53 -0
  169. data/lib/active_record/scoping/default.rb +135 -0
  170. data/lib/active_record/scoping/named.rb +164 -0
  171. data/lib/active_record/scoping.rb +87 -0
  172. data/lib/active_record/serialization.rb +7 -45
  173. data/lib/active_record/serializers/xml_serializer.rb +14 -65
  174. data/lib/active_record/statement_cache.rb +111 -0
  175. data/lib/active_record/store.rb +205 -0
  176. data/lib/active_record/tasks/database_tasks.rb +299 -0
  177. data/lib/active_record/tasks/mysql_database_tasks.rb +159 -0
  178. data/lib/active_record/tasks/postgresql_database_tasks.rb +101 -0
  179. data/lib/active_record/tasks/sqlite_database_tasks.rb +55 -0
  180. data/lib/active_record/timestamp.rb +35 -14
  181. data/lib/active_record/transactions.rb +141 -74
  182. data/lib/active_record/translation.rb +22 -0
  183. data/lib/active_record/type/big_integer.rb +13 -0
  184. data/lib/active_record/type/binary.rb +50 -0
  185. data/lib/active_record/type/boolean.rb +31 -0
  186. data/lib/active_record/type/date.rb +50 -0
  187. data/lib/active_record/type/date_time.rb +54 -0
  188. data/lib/active_record/type/decimal.rb +64 -0
  189. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  190. data/lib/active_record/type/decorator.rb +14 -0
  191. data/lib/active_record/type/float.rb +19 -0
  192. data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
  193. data/lib/active_record/type/integer.rb +59 -0
  194. data/lib/active_record/type/mutable.rb +16 -0
  195. data/lib/active_record/type/numeric.rb +36 -0
  196. data/lib/active_record/type/serialized.rb +62 -0
  197. data/lib/active_record/type/string.rb +40 -0
  198. data/lib/active_record/type/text.rb +11 -0
  199. data/lib/active_record/type/time.rb +26 -0
  200. data/lib/active_record/type/time_value.rb +38 -0
  201. data/lib/active_record/type/type_map.rb +64 -0
  202. data/lib/active_record/type/unsigned_integer.rb +15 -0
  203. data/lib/active_record/type/value.rb +110 -0
  204. data/lib/active_record/type.rb +23 -0
  205. data/lib/active_record/validations/associated.rb +27 -18
  206. data/lib/active_record/validations/presence.rb +67 -0
  207. data/lib/active_record/validations/uniqueness.rb +125 -66
  208. data/lib/active_record/validations.rb +37 -30
  209. data/lib/active_record/version.rb +5 -7
  210. data/lib/active_record.rb +80 -25
  211. data/lib/rails/generators/active_record/migration/migration_generator.rb +54 -9
  212. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +19 -0
  213. data/lib/rails/generators/active_record/migration/templates/migration.rb +25 -11
  214. data/lib/rails/generators/active_record/migration.rb +11 -8
  215. data/lib/rails/generators/active_record/model/model_generator.rb +17 -4
  216. data/lib/rails/generators/active_record/model/templates/model.rb +5 -2
  217. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  218. data/lib/rails/generators/active_record.rb +3 -11
  219. metadata +132 -53
  220. data/examples/associations.png +0 -0
  221. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -62
  222. data/lib/active_record/associations/join_helper.rb +0 -55
  223. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  224. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -135
  225. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -556
  226. data/lib/active_record/dynamic_finder_match.rb +0 -56
  227. data/lib/active_record/dynamic_scope_match.rb +0 -23
  228. data/lib/active_record/identity_map.rb +0 -163
  229. data/lib/active_record/named_scope.rb +0 -200
  230. data/lib/active_record/observer.rb +0 -121
  231. data/lib/active_record/session_store.rb +0 -358
  232. data/lib/active_record/test_case.rb +0 -69
  233. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -17
  234. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  235. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  236. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  237. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -16
@@ -1,23 +1,55 @@
1
1
  require 'date'
2
2
  require 'bigdecimal'
3
3
  require 'bigdecimal/util'
4
+ require 'active_record/type'
4
5
  require 'active_support/core_ext/benchmark'
5
- require 'active_support/deprecation'
6
-
7
- # TODO: Autoload these files
8
- require 'active_record/connection_adapters/column'
9
- require 'active_record/connection_adapters/abstract/schema_definitions'
10
- require 'active_record/connection_adapters/abstract/schema_statements'
11
- require 'active_record/connection_adapters/abstract/database_statements'
12
- require 'active_record/connection_adapters/abstract/quoting'
13
- require 'active_record/connection_adapters/abstract/connection_pool'
14
- require 'active_record/connection_adapters/abstract/connection_specification'
15
- require 'active_record/connection_adapters/abstract/query_cache'
16
- require 'active_record/connection_adapters/abstract/database_limits'
17
- require 'active_record/result'
6
+ require 'active_record/connection_adapters/schema_cache'
7
+ require 'active_record/connection_adapters/abstract/schema_dumper'
8
+ require 'active_record/connection_adapters/abstract/schema_creation'
9
+ require 'monitor'
10
+ require 'arel/collectors/bind'
11
+ require 'arel/collectors/sql_string'
18
12
 
19
13
  module ActiveRecord
20
14
  module ConnectionAdapters # :nodoc:
15
+ extend ActiveSupport::Autoload
16
+
17
+ autoload :Column
18
+ autoload :ConnectionSpecification
19
+
20
+ autoload_at 'active_record/connection_adapters/abstract/schema_definitions' do
21
+ autoload :IndexDefinition
22
+ autoload :ColumnDefinition
23
+ autoload :ChangeColumnDefinition
24
+ autoload :TableDefinition
25
+ autoload :Table
26
+ autoload :AlterTable
27
+ autoload :TimestampDefaultDeprecation
28
+ end
29
+
30
+ autoload_at 'active_record/connection_adapters/abstract/connection_pool' do
31
+ autoload :ConnectionHandler
32
+ autoload :ConnectionManagement
33
+ end
34
+
35
+ autoload_under 'abstract' do
36
+ autoload :SchemaStatements
37
+ autoload :DatabaseStatements
38
+ autoload :DatabaseLimits
39
+ autoload :Quoting
40
+ autoload :ConnectionPool
41
+ autoload :QueryCache
42
+ autoload :Savepoints
43
+ end
44
+
45
+ autoload_at 'active_record/connection_adapters/abstract/transaction' do
46
+ autoload :TransactionManager
47
+ autoload :NullTransaction
48
+ autoload :RealTransaction
49
+ autoload :SavepointTransaction
50
+ autoload :TransactionState
51
+ end
52
+
21
53
  # Active Record supports multiple database systems. AbstractAdapter and
22
54
  # related classes form the abstraction layer which makes this possible.
23
55
  # An AbstractAdapter represents a connection to a database, and provides an
@@ -32,71 +64,136 @@ module ActiveRecord
32
64
  # Most of the methods in the adapter are useful during migrations. Most
33
65
  # notably, the instance methods provided by SchemaStatement are very useful.
34
66
  class AbstractAdapter
67
+ ADAPTER_NAME = 'Abstract'.freeze
35
68
  include Quoting, DatabaseStatements, SchemaStatements
36
69
  include DatabaseLimits
37
70
  include QueryCache
38
71
  include ActiveSupport::Callbacks
72
+ include MonitorMixin
73
+ include ColumnDumper
74
+
75
+ SIMPLE_INT = /\A\d+\z/
39
76
 
40
77
  define_callbacks :checkout, :checkin
41
78
 
42
- attr_accessor :visitor
43
- attr_reader :logger
79
+ attr_accessor :visitor, :pool
80
+ attr_reader :schema_cache, :owner, :logger
81
+ alias :in_use? :owner
44
82
 
45
- def initialize(connection, logger = nil) #:nodoc:
46
- @active = nil
47
- @connection, @logger = connection, logger
48
- @query_cache_enabled = false
49
- @query_cache = Hash.new { |h,sql| h[sql] = {} }
50
- @instrumenter = ActiveSupport::Notifications.instrumenter
51
- @visitor = nil
83
+ def self.type_cast_config_to_integer(config)
84
+ if config =~ SIMPLE_INT
85
+ config.to_i
86
+ else
87
+ config
88
+ end
89
+ end
90
+
91
+ def self.type_cast_config_to_boolean(config)
92
+ if config == "false"
93
+ false
94
+ else
95
+ config
96
+ end
52
97
  end
53
98
 
54
- # Returns a visitor instance for this adaptor, which conforms to the Arel::ToSql interface
55
- def self.visitor_for(pool) # :nodoc:
56
- adapter = pool.spec.config[:adapter]
99
+ attr_reader :prepared_statements
57
100
 
58
- if Arel::Visitors::VISITORS[adapter]
59
- ActiveSupport::Deprecation.warn(
60
- "Arel::Visitors::VISITORS is deprecated and will be removed. Database adapters " \
61
- "should define a visitor_for method which returns the appropriate visitor for " \
62
- "the database. For example, MysqlAdapter.visitor_for(pool) returns " \
63
- "Arel::Visitors::MySQL.new(pool)."
64
- )
101
+ def initialize(connection, logger = nil, pool = nil) #:nodoc:
102
+ super()
103
+
104
+ @connection = connection
105
+ @owner = nil
106
+ @instrumenter = ActiveSupport::Notifications.instrumenter
107
+ @logger = logger
108
+ @pool = pool
109
+ @schema_cache = SchemaCache.new self
110
+ @visitor = nil
111
+ @prepared_statements = false
112
+ end
113
+
114
+ class Version
115
+ include Comparable
116
+
117
+ def initialize(version_string)
118
+ @version = version_string.split('.').map(&:to_i)
119
+ end
120
+
121
+ def <=>(version_string)
122
+ @version <=> version_string.split('.').map(&:to_i)
123
+ end
124
+ end
125
+
126
+ class BindCollector < Arel::Collectors::Bind
127
+ def compile(bvs, conn)
128
+ super(bvs.map { |bv| conn.quote(*bv.reverse) })
129
+ end
130
+ end
131
+
132
+ class SQLString < Arel::Collectors::SQLString
133
+ def compile(bvs, conn)
134
+ super(bvs)
135
+ end
136
+ end
65
137
 
66
- Arel::Visitors::VISITORS[adapter].new(pool)
138
+ def collector
139
+ if prepared_statements
140
+ SQLString.new
67
141
  else
68
- Arel::Visitors::ToSql.new(pool)
142
+ BindCollector.new
69
143
  end
70
144
  end
71
145
 
146
+ def valid_type?(type)
147
+ true
148
+ end
149
+
150
+ def schema_creation
151
+ SchemaCreation.new self
152
+ end
153
+
154
+ def lease
155
+ synchronize do
156
+ unless in_use?
157
+ @owner = Thread.current
158
+ end
159
+ end
160
+ end
161
+
162
+ def schema_cache=(cache)
163
+ cache.connection = self
164
+ @schema_cache = cache
165
+ end
166
+
167
+ def expire
168
+ @owner = nil
169
+ end
170
+
171
+ def unprepared_statement
172
+ old_prepared_statements, @prepared_statements = @prepared_statements, false
173
+ yield
174
+ ensure
175
+ @prepared_statements = old_prepared_statements
176
+ end
177
+
72
178
  # Returns the human-readable name of the adapter. Use mixed case - one
73
179
  # can always use downcase if needed.
74
180
  def adapter_name
75
- 'Abstract'
181
+ self.class::ADAPTER_NAME
76
182
  end
77
183
 
78
- # Does this adapter support migrations? Backend specific, as the
79
- # abstract adapter always returns +false+.
184
+ # Does this adapter support migrations?
80
185
  def supports_migrations?
81
186
  false
82
187
  end
83
188
 
84
189
  # Can this adapter determine the primary key for tables not attached
85
- # to an Active Record class, such as join tables? Backend specific, as
86
- # the abstract adapter always returns +false+.
190
+ # to an Active Record class, such as join tables?
87
191
  def supports_primary_key?
88
192
  false
89
193
  end
90
194
 
91
- # Does this adapter support using DISTINCT within COUNT? This is +true+
92
- # for all adapters except sqlite.
93
- def supports_count_distinct?
94
- true
95
- end
96
-
97
195
  # Does this adapter support DDL rollbacks in transactions? That is, would
98
- # CREATE TABLE or ALTER TABLE get rolled back by a transaction? PostgreSQL,
99
- # SQL Server, and others support this. MySQL and others do not.
196
+ # CREATE TABLE or ALTER TABLE get rolled back by a transaction?
100
197
  def supports_ddl_transactions?
101
198
  false
102
199
  end
@@ -105,8 +202,7 @@ module ActiveRecord
105
202
  false
106
203
  end
107
204
 
108
- # Does this adapter support savepoints? PostgreSQL and MySQL do,
109
- # SQLite < 3.6.8 does not.
205
+ # Does this adapter support savepoints?
110
206
  def supports_savepoints?
111
207
  false
112
208
  end
@@ -114,22 +210,75 @@ module ActiveRecord
114
210
  # Should primary key values be selected from their corresponding
115
211
  # sequence before the insert statement? If true, next_sequence_value
116
212
  # is called before each insert to set the record's primary key.
117
- # This is false for all adapters but Firebird.
118
213
  def prefetch_primary_key?(table_name = nil)
119
214
  false
120
215
  end
121
216
 
122
- # QUOTING ==================================================
217
+ # Does this adapter support index sort order?
218
+ def supports_index_sort_order?
219
+ false
220
+ end
123
221
 
124
- # Override to return the quoted table name. Defaults to column quoting.
125
- def quote_table_name(name)
126
- quote_column_name(name)
222
+ # Does this adapter support partial indices?
223
+ def supports_partial_index?
224
+ false
127
225
  end
128
226
 
129
- # Returns a bind substitution value given a +column+ and list of current
130
- # +binds+
131
- def substitute_at(column, index)
132
- Arel::Nodes::BindParam.new '?'
227
+ # Does this adapter support explain?
228
+ def supports_explain?
229
+ false
230
+ end
231
+
232
+ # Does this adapter support setting the isolation level for a transaction?
233
+ def supports_transaction_isolation?
234
+ false
235
+ end
236
+
237
+ # Does this adapter support database extensions?
238
+ def supports_extensions?
239
+ false
240
+ end
241
+
242
+ # Does this adapter support creating indexes in the same statement as
243
+ # creating the table?
244
+ def supports_indexes_in_create?
245
+ false
246
+ end
247
+
248
+ # Does this adapter support creating foreign key constraints?
249
+ def supports_foreign_keys?
250
+ false
251
+ end
252
+
253
+ # Does this adapter support views?
254
+ def supports_views?
255
+ false
256
+ end
257
+
258
+ # This is meant to be implemented by the adapters that support extensions
259
+ def disable_extension(name)
260
+ end
261
+
262
+ # This is meant to be implemented by the adapters that support extensions
263
+ def enable_extension(name)
264
+ end
265
+
266
+ # A list of extensions, to be filled in by adapters that support them.
267
+ def extensions
268
+ []
269
+ end
270
+
271
+ # A list of index algorithms, to be filled by adapters that support them.
272
+ def index_algorithms
273
+ {}
274
+ end
275
+
276
+ # QUOTING ==================================================
277
+
278
+ # Returns a bind substitution value given a bind +column+
279
+ # NOTE: The column param is currently being used by the sqlserver-adapter
280
+ def substitute_at(column, _unused = 0)
281
+ Arel::Nodes::BindParam.new
133
282
  end
134
283
 
135
284
  # REFERENTIAL INTEGRITY ====================================
@@ -145,19 +294,21 @@ module ActiveRecord
145
294
  # checking whether the database is actually capable of responding, i.e. whether
146
295
  # the connection isn't stale.
147
296
  def active?
148
- @active != false
149
297
  end
150
298
 
151
299
  # Disconnects from the database if already connected, and establishes a
152
- # new connection with the database.
300
+ # new connection with the database. Implementors should call super if they
301
+ # override the default implementation.
153
302
  def reconnect!
154
- @active = true
303
+ clear_cache!
304
+ reset_transaction
155
305
  end
156
306
 
157
307
  # Disconnects from the database if already connected. Otherwise, this
158
308
  # method does nothing.
159
309
  def disconnect!
160
- @active = false
310
+ clear_cache!
311
+ reset_transaction
161
312
  end
162
313
 
163
314
  # Reset the state of this connection, directing the DBMS to clear
@@ -178,7 +329,6 @@ module ActiveRecord
178
329
  end
179
330
 
180
331
  # Returns true if its required to reload the connection between requests for development mode.
181
- # This is not the case for Ruby/MySQL and it's not necessary for any adapters except SQLite.
182
332
  def requires_reloading?
183
333
  false
184
334
  end
@@ -200,62 +350,156 @@ module ActiveRecord
200
350
  @connection
201
351
  end
202
352
 
203
- def open_transactions
204
- @open_transactions ||= 0
353
+ def create_savepoint(name = nil)
205
354
  end
206
355
 
207
- def increment_open_transactions
208
- @open_transactions ||= 0
209
- @open_transactions += 1
356
+ def release_savepoint(name = nil)
210
357
  end
211
358
 
212
- def decrement_open_transactions
213
- @open_transactions -= 1
359
+ def case_sensitive_modifier(node, table_attribute)
360
+ node
214
361
  end
215
362
 
216
- def transaction_joinable=(joinable)
217
- @transaction_joinable = joinable
363
+ def case_sensitive_comparison(table, attribute, column, value)
364
+ table_attr = table[attribute]
365
+ value = case_sensitive_modifier(value, table_attr) unless value.nil?
366
+ table_attr.eq(value)
218
367
  end
219
368
 
220
- def create_savepoint
369
+ def case_insensitive_comparison(table, attribute, column, value)
370
+ table[attribute].lower.eq(table.lower(value))
221
371
  end
222
372
 
223
- def rollback_to_savepoint
373
+ def current_savepoint_name
374
+ current_transaction.savepoint_name
224
375
  end
225
376
 
226
- def release_savepoint
377
+ # Check the connection back in to the connection pool
378
+ def close
379
+ pool.checkin self
227
380
  end
228
381
 
229
- def case_sensitive_modifier(node)
230
- node
382
+ def type_map # :nodoc:
383
+ @type_map ||= Type::TypeMap.new.tap do |mapping|
384
+ initialize_type_map(mapping)
385
+ end
231
386
  end
232
387
 
233
- def current_savepoint_name
234
- "active_record_#{open_transactions}"
388
+ def new_column(name, default, cast_type, sql_type = nil, null = true)
389
+ Column.new(name, default, cast_type, sql_type, null)
390
+ end
391
+
392
+ def lookup_cast_type(sql_type) # :nodoc:
393
+ type_map.lookup(sql_type)
394
+ end
395
+
396
+ def column_name_for_operation(operation, node) # :nodoc:
397
+ visitor.accept(node, collector).value
235
398
  end
236
399
 
237
400
  protected
238
401
 
239
- def log(sql, name = "SQL", binds = [])
240
- @instrumenter.instrument(
241
- "sql.active_record",
242
- :sql => sql,
243
- :name => name,
244
- :connection_id => object_id,
245
- :binds => binds) { yield }
246
- rescue Exception => e
247
- message = "#{e.class.name}: #{e.message}: #{sql}"
248
- @logger.debug message if @logger
249
- exception = translate_exception(e, message)
250
- exception.set_backtrace e.backtrace
251
- raise exception
402
+ def initialize_type_map(m) # :nodoc:
403
+ register_class_with_limit m, %r(boolean)i, Type::Boolean
404
+ register_class_with_limit m, %r(char)i, Type::String
405
+ register_class_with_limit m, %r(binary)i, Type::Binary
406
+ register_class_with_limit m, %r(text)i, Type::Text
407
+ register_class_with_limit m, %r(date)i, Type::Date
408
+ register_class_with_limit m, %r(time)i, Type::Time
409
+ register_class_with_limit m, %r(datetime)i, Type::DateTime
410
+ register_class_with_limit m, %r(float)i, Type::Float
411
+ register_class_with_limit m, %r(int)i, Type::Integer
412
+
413
+ m.alias_type %r(blob)i, 'binary'
414
+ m.alias_type %r(clob)i, 'text'
415
+ m.alias_type %r(timestamp)i, 'datetime'
416
+ m.alias_type %r(numeric)i, 'decimal'
417
+ m.alias_type %r(number)i, 'decimal'
418
+ m.alias_type %r(double)i, 'float'
419
+
420
+ m.register_type(%r(decimal)i) do |sql_type|
421
+ scale = extract_scale(sql_type)
422
+ precision = extract_precision(sql_type)
423
+
424
+ if scale == 0
425
+ # FIXME: Remove this class as well
426
+ Type::DecimalWithoutScale.new(precision: precision)
427
+ else
428
+ Type::Decimal.new(precision: precision, scale: scale)
429
+ end
430
+ end
431
+ end
432
+
433
+ def reload_type_map # :nodoc:
434
+ type_map.clear
435
+ initialize_type_map(type_map)
436
+ end
437
+
438
+ def register_class_with_limit(mapping, key, klass) # :nodoc:
439
+ mapping.register_type(key) do |*args|
440
+ limit = extract_limit(args.last)
441
+ klass.new(limit: limit)
442
+ end
443
+ end
444
+
445
+ def extract_scale(sql_type) # :nodoc:
446
+ case sql_type
447
+ when /\((\d+)\)/ then 0
448
+ when /\((\d+)(,(\d+))\)/ then $3.to_i
449
+ end
450
+ end
451
+
452
+ def extract_precision(sql_type) # :nodoc:
453
+ $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
454
+ end
455
+
456
+ def extract_limit(sql_type) # :nodoc:
457
+ case sql_type
458
+ when /^bigint/i
459
+ 8
460
+ when /\((.*)\)/
461
+ $1.to_i
252
462
  end
463
+ end
253
464
 
254
- def translate_exception(e, message)
255
- # override in derived class
256
- ActiveRecord::StatementInvalid.new(message)
465
+ def translate_exception_class(e, sql)
466
+ begin
467
+ message = "#{e.class.name}: #{e.message}: #{sql}"
468
+ rescue Encoding::CompatibilityError
469
+ message = "#{e.class.name}: #{e.message.force_encoding sql.encoding}: #{sql}"
257
470
  end
258
471
 
472
+ exception = translate_exception(e, message)
473
+ exception.set_backtrace e.backtrace
474
+ exception
475
+ end
476
+
477
+ def log(sql, name = "SQL", binds = [], statement_name = nil)
478
+ @instrumenter.instrument(
479
+ "sql.active_record",
480
+ :sql => sql,
481
+ :name => name,
482
+ :connection_id => object_id,
483
+ :statement_name => statement_name,
484
+ :binds => binds) { yield }
485
+ rescue => e
486
+ raise translate_exception_class(e, sql)
487
+ end
488
+
489
+ def translate_exception(exception, message)
490
+ # override in derived class
491
+ ActiveRecord::StatementInvalid.new(message, exception)
492
+ end
493
+
494
+ def without_prepared_statement?(binds)
495
+ !prepared_statements || binds.empty?
496
+ end
497
+
498
+ def column_for(table_name, column_name) # :nodoc:
499
+ column_name = column_name.to_s
500
+ columns(table_name).detect { |c| c.name == column_name } ||
501
+ raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
502
+ end
259
503
  end
260
504
  end
261
505
  end