activerecord 3.2.19 → 5.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 (264) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1715 -604
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +40 -45
  5. data/examples/performance.rb +33 -22
  6. data/examples/simple.rb +3 -4
  7. data/lib/active_record/aggregations.rb +76 -51
  8. data/lib/active_record/association_relation.rb +35 -0
  9. data/lib/active_record/associations/alias_tracker.rb +54 -40
  10. data/lib/active_record/associations/association.rb +76 -56
  11. data/lib/active_record/associations/association_scope.rb +125 -93
  12. data/lib/active_record/associations/belongs_to_association.rb +57 -28
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -2
  14. data/lib/active_record/associations/builder/association.rb +120 -32
  15. data/lib/active_record/associations/builder/belongs_to.rb +115 -62
  16. data/lib/active_record/associations/builder/collection_association.rb +61 -53
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +117 -43
  18. data/lib/active_record/associations/builder/has_many.rb +9 -65
  19. data/lib/active_record/associations/builder/has_one.rb +18 -52
  20. data/lib/active_record/associations/builder/singular_association.rb +18 -19
  21. data/lib/active_record/associations/collection_association.rb +268 -186
  22. data/lib/active_record/associations/collection_proxy.rb +1003 -63
  23. data/lib/active_record/associations/foreign_association.rb +11 -0
  24. data/lib/active_record/associations/has_many_association.rb +81 -41
  25. data/lib/active_record/associations/has_many_through_association.rb +76 -55
  26. data/lib/active_record/associations/has_one_association.rb +51 -21
  27. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  28. data/lib/active_record/associations/join_dependency/join_association.rb +83 -108
  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 +239 -155
  32. data/lib/active_record/associations/preloader/association.rb +97 -62
  33. data/lib/active_record/associations/preloader/collection_association.rb +2 -8
  34. data/lib/active_record/associations/preloader/has_many_through.rb +7 -3
  35. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  36. data/lib/active_record/associations/preloader/singular_association.rb +3 -3
  37. data/lib/active_record/associations/preloader/through_association.rb +75 -33
  38. data/lib/active_record/associations/preloader.rb +111 -79
  39. data/lib/active_record/associations/singular_association.rb +35 -13
  40. data/lib/active_record/associations/through_association.rb +41 -19
  41. data/lib/active_record/associations.rb +727 -501
  42. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  43. data/lib/active_record/attribute.rb +213 -0
  44. data/lib/active_record/attribute_assignment.rb +32 -162
  45. data/lib/active_record/attribute_decorators.rb +67 -0
  46. data/lib/active_record/attribute_methods/before_type_cast.rb +52 -7
  47. data/lib/active_record/attribute_methods/dirty.rb +101 -61
  48. data/lib/active_record/attribute_methods/primary_key.rb +50 -36
  49. data/lib/active_record/attribute_methods/query.rb +7 -6
  50. data/lib/active_record/attribute_methods/read.rb +56 -117
  51. data/lib/active_record/attribute_methods/serialization.rb +43 -96
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +93 -42
  53. data/lib/active_record/attribute_methods/write.rb +34 -45
  54. data/lib/active_record/attribute_methods.rb +333 -144
  55. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  56. data/lib/active_record/attribute_set/builder.rb +108 -0
  57. data/lib/active_record/attribute_set.rb +108 -0
  58. data/lib/active_record/attributes.rb +265 -0
  59. data/lib/active_record/autosave_association.rb +285 -223
  60. data/lib/active_record/base.rb +95 -490
  61. data/lib/active_record/callbacks.rb +95 -61
  62. data/lib/active_record/coders/json.rb +13 -0
  63. data/lib/active_record/coders/yaml_column.rb +28 -19
  64. data/lib/active_record/collection_cache_key.rb +40 -0
  65. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +724 -277
  66. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  67. data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -192
  68. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -26
  69. data/lib/active_record/connection_adapters/abstract/quoting.rb +140 -57
  70. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +147 -0
  72. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +419 -276
  73. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +105 -0
  74. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +963 -276
  75. data/lib/active_record/connection_adapters/abstract/transaction.rb +232 -0
  76. data/lib/active_record/connection_adapters/abstract_adapter.rb +397 -106
  77. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +643 -342
  78. data/lib/active_record/connection_adapters/column.rb +30 -259
  79. data/lib/active_record/connection_adapters/connection_specification.rb +263 -0
  80. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  81. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  82. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  83. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  84. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  85. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  86. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  87. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  88. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  89. data/lib/active_record/connection_adapters/mysql2_adapter.rb +47 -196
  90. data/lib/active_record/connection_adapters/postgresql/column.rb +15 -0
  91. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +170 -0
  92. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +70 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +48 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +21 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +10 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +39 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +93 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
  110. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  112. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  113. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  114. data/lib/active_record/connection_adapters/postgresql/oid.rb +31 -0
  115. data/lib/active_record/connection_adapters/postgresql/quoting.rb +116 -0
  116. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +49 -0
  117. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +180 -0
  118. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  119. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +682 -0
  120. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  121. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  122. data/lib/active_record/connection_adapters/postgresql_adapter.rb +558 -1039
  123. data/lib/active_record/connection_adapters/schema_cache.rb +74 -36
  124. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  125. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +538 -24
  129. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  130. data/lib/active_record/connection_handling.rb +155 -0
  131. data/lib/active_record/core.rb +561 -0
  132. data/lib/active_record/counter_cache.rb +146 -105
  133. data/lib/active_record/dynamic_matchers.rb +101 -64
  134. data/lib/active_record/enum.rb +234 -0
  135. data/lib/active_record/errors.rb +153 -56
  136. data/lib/active_record/explain.rb +15 -63
  137. data/lib/active_record/explain_registry.rb +30 -0
  138. data/lib/active_record/explain_subscriber.rb +10 -6
  139. data/lib/active_record/fixture_set/file.rb +77 -0
  140. data/lib/active_record/fixtures.rb +355 -232
  141. data/lib/active_record/gem_version.rb +15 -0
  142. data/lib/active_record/inheritance.rb +144 -79
  143. data/lib/active_record/integration.rb +66 -13
  144. data/lib/active_record/internal_metadata.rb +56 -0
  145. data/lib/active_record/legacy_yaml_adapter.rb +46 -0
  146. data/lib/active_record/locale/en.yml +9 -1
  147. data/lib/active_record/locking/optimistic.rb +77 -56
  148. data/lib/active_record/locking/pessimistic.rb +6 -6
  149. data/lib/active_record/log_subscriber.rb +53 -28
  150. data/lib/active_record/migration/command_recorder.rb +166 -33
  151. data/lib/active_record/migration/compatibility.rb +126 -0
  152. data/lib/active_record/migration/join_table.rb +15 -0
  153. data/lib/active_record/migration.rb +792 -264
  154. data/lib/active_record/model_schema.rb +192 -130
  155. data/lib/active_record/nested_attributes.rb +238 -145
  156. data/lib/active_record/no_touching.rb +52 -0
  157. data/lib/active_record/null_relation.rb +89 -0
  158. data/lib/active_record/persistence.rb +357 -157
  159. data/lib/active_record/query_cache.rb +22 -43
  160. data/lib/active_record/querying.rb +34 -23
  161. data/lib/active_record/railtie.rb +88 -48
  162. data/lib/active_record/railties/console_sandbox.rb +3 -4
  163. data/lib/active_record/railties/controller_runtime.rb +5 -4
  164. data/lib/active_record/railties/databases.rake +170 -422
  165. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  166. data/lib/active_record/readonly_attributes.rb +2 -5
  167. data/lib/active_record/reflection.rb +715 -189
  168. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  169. data/lib/active_record/relation/batches.rb +203 -50
  170. data/lib/active_record/relation/calculations.rb +203 -194
  171. data/lib/active_record/relation/delegation.rb +103 -25
  172. data/lib/active_record/relation/finder_methods.rb +457 -261
  173. data/lib/active_record/relation/from_clause.rb +32 -0
  174. data/lib/active_record/relation/merger.rb +167 -0
  175. data/lib/active_record/relation/predicate_builder/array_handler.rb +43 -0
  176. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  177. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  178. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  179. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  180. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  181. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  182. data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
  183. data/lib/active_record/relation/predicate_builder.rb +153 -48
  184. data/lib/active_record/relation/query_attribute.rb +19 -0
  185. data/lib/active_record/relation/query_methods.rb +1019 -194
  186. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  187. data/lib/active_record/relation/spawn_methods.rb +46 -150
  188. data/lib/active_record/relation/where_clause.rb +174 -0
  189. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  190. data/lib/active_record/relation.rb +450 -245
  191. data/lib/active_record/result.rb +104 -12
  192. data/lib/active_record/runtime_registry.rb +22 -0
  193. data/lib/active_record/sanitization.rb +120 -94
  194. data/lib/active_record/schema.rb +28 -18
  195. data/lib/active_record/schema_dumper.rb +141 -74
  196. data/lib/active_record/schema_migration.rb +50 -0
  197. data/lib/active_record/scoping/default.rb +64 -57
  198. data/lib/active_record/scoping/named.rb +93 -108
  199. data/lib/active_record/scoping.rb +73 -121
  200. data/lib/active_record/secure_token.rb +38 -0
  201. data/lib/active_record/serialization.rb +7 -5
  202. data/lib/active_record/statement_cache.rb +113 -0
  203. data/lib/active_record/store.rb +173 -15
  204. data/lib/active_record/suppressor.rb +58 -0
  205. data/lib/active_record/table_metadata.rb +68 -0
  206. data/lib/active_record/tasks/database_tasks.rb +313 -0
  207. data/lib/active_record/tasks/mysql_database_tasks.rb +151 -0
  208. data/lib/active_record/tasks/postgresql_database_tasks.rb +110 -0
  209. data/lib/active_record/tasks/sqlite_database_tasks.rb +59 -0
  210. data/lib/active_record/timestamp.rb +42 -24
  211. data/lib/active_record/touch_later.rb +58 -0
  212. data/lib/active_record/transactions.rb +233 -105
  213. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  214. data/lib/active_record/type/date.rb +7 -0
  215. data/lib/active_record/type/date_time.rb +7 -0
  216. data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
  217. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  218. data/lib/active_record/type/internal/timezone.rb +15 -0
  219. data/lib/active_record/type/serialized.rb +63 -0
  220. data/lib/active_record/type/time.rb +20 -0
  221. data/lib/active_record/type/type_map.rb +64 -0
  222. data/lib/active_record/type.rb +72 -0
  223. data/lib/active_record/type_caster/connection.rb +29 -0
  224. data/lib/active_record/type_caster/map.rb +19 -0
  225. data/lib/active_record/type_caster.rb +7 -0
  226. data/lib/active_record/validations/absence.rb +23 -0
  227. data/lib/active_record/validations/associated.rb +33 -18
  228. data/lib/active_record/validations/length.rb +24 -0
  229. data/lib/active_record/validations/presence.rb +66 -0
  230. data/lib/active_record/validations/uniqueness.rb +128 -68
  231. data/lib/active_record/validations.rb +48 -40
  232. data/lib/active_record/version.rb +5 -7
  233. data/lib/active_record.rb +71 -47
  234. data/lib/rails/generators/active_record/migration/migration_generator.rb +56 -8
  235. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +24 -0
  236. data/lib/rails/generators/active_record/migration/templates/migration.rb +28 -16
  237. data/lib/rails/generators/active_record/migration.rb +18 -8
  238. data/lib/rails/generators/active_record/model/model_generator.rb +38 -16
  239. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  240. data/lib/rails/generators/active_record/model/templates/model.rb +7 -6
  241. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  242. data/lib/rails/generators/active_record.rb +3 -11
  243. metadata +188 -134
  244. data/examples/associations.png +0 -0
  245. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  246. data/lib/active_record/associations/join_helper.rb +0 -55
  247. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  248. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  249. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  250. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -441
  251. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  252. data/lib/active_record/dynamic_finder_match.rb +0 -68
  253. data/lib/active_record/dynamic_scope_match.rb +0 -23
  254. data/lib/active_record/fixtures/file.rb +0 -65
  255. data/lib/active_record/identity_map.rb +0 -162
  256. data/lib/active_record/observer.rb +0 -121
  257. data/lib/active_record/serializers/xml_serializer.rb +0 -203
  258. data/lib/active_record/session_store.rb +0 -360
  259. data/lib/active_record/test_case.rb +0 -73
  260. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
  261. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  262. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  263. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  264. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,120 +1,218 @@
1
- require 'date'
2
- require 'bigdecimal'
3
- require 'bigdecimal/util'
4
- require 'active_support/core_ext/benchmark'
5
- require 'active_support/deprecation'
1
+ require 'active_record/type'
2
+ require 'active_record/connection_adapters/determine_if_preparable_visitor'
6
3
  require 'active_record/connection_adapters/schema_cache'
7
- require 'monitor'
4
+ require 'active_record/connection_adapters/sql_type_metadata'
5
+ require 'active_record/connection_adapters/abstract/schema_dumper'
6
+ require 'active_record/connection_adapters/abstract/schema_creation'
7
+ require 'arel/collectors/bind'
8
+ require 'arel/collectors/sql_string'
8
9
 
9
10
  module ActiveRecord
10
11
  module ConnectionAdapters # :nodoc:
11
12
  extend ActiveSupport::Autoload
12
13
 
13
14
  autoload :Column
15
+ autoload :ConnectionSpecification
16
+
17
+ autoload_at 'active_record/connection_adapters/abstract/schema_definitions' do
18
+ autoload :IndexDefinition
19
+ autoload :ColumnDefinition
20
+ autoload :ChangeColumnDefinition
21
+ autoload :ForeignKeyDefinition
22
+ autoload :TableDefinition
23
+ autoload :Table
24
+ autoload :AlterTable
25
+ autoload :ReferenceDefinition
26
+ end
14
27
 
15
- autoload_under 'abstract' do
16
- autoload :IndexDefinition, 'active_record/connection_adapters/abstract/schema_definitions'
17
- autoload :ColumnDefinition, 'active_record/connection_adapters/abstract/schema_definitions'
18
- autoload :TableDefinition, 'active_record/connection_adapters/abstract/schema_definitions'
19
- autoload :Table, 'active_record/connection_adapters/abstract/schema_definitions'
28
+ autoload_at 'active_record/connection_adapters/abstract/connection_pool' do
29
+ autoload :ConnectionHandler
30
+ end
20
31
 
32
+ autoload_under 'abstract' do
21
33
  autoload :SchemaStatements
22
34
  autoload :DatabaseStatements
23
35
  autoload :DatabaseLimits
24
36
  autoload :Quoting
25
-
26
37
  autoload :ConnectionPool
27
- autoload :ConnectionHandler, 'active_record/connection_adapters/abstract/connection_pool'
28
- autoload :ConnectionManagement, 'active_record/connection_adapters/abstract/connection_pool'
29
- autoload :ConnectionSpecification
30
-
31
38
  autoload :QueryCache
39
+ autoload :Savepoints
40
+ end
41
+
42
+ autoload_at 'active_record/connection_adapters/abstract/transaction' do
43
+ autoload :TransactionManager
44
+ autoload :NullTransaction
45
+ autoload :RealTransaction
46
+ autoload :SavepointTransaction
47
+ autoload :TransactionState
32
48
  end
33
49
 
34
50
  # Active Record supports multiple database systems. AbstractAdapter and
35
51
  # related classes form the abstraction layer which makes this possible.
36
52
  # An AbstractAdapter represents a connection to a database, and provides an
37
53
  # abstract interface for database-specific functionality such as establishing
38
- # a connection, escaping values, building the right SQL fragments for ':offset'
39
- # and ':limit' options, etc.
54
+ # a connection, escaping values, building the right SQL fragments for +:offset+
55
+ # and +:limit+ options, etc.
40
56
  #
41
57
  # All the concrete database adapters follow the interface laid down in this class.
42
- # ActiveRecord::Base.connection returns an AbstractAdapter object, which
58
+ # {ActiveRecord::Base.connection}[rdoc-ref:ConnectionHandling#connection] returns an AbstractAdapter object, which
43
59
  # you can use.
44
60
  #
45
61
  # Most of the methods in the adapter are useful during migrations. Most
46
- # notably, the instance methods provided by SchemaStatement are very useful.
62
+ # notably, the instance methods provided by SchemaStatements are very useful.
47
63
  class AbstractAdapter
64
+ ADAPTER_NAME = 'Abstract'.freeze
48
65
  include Quoting, DatabaseStatements, SchemaStatements
49
66
  include DatabaseLimits
50
67
  include QueryCache
51
68
  include ActiveSupport::Callbacks
52
- include MonitorMixin
69
+ include ColumnDumper
70
+ include Savepoints
71
+
72
+ SIMPLE_INT = /\A\d+\z/
53
73
 
54
74
  define_callbacks :checkout, :checkin
55
75
 
56
76
  attr_accessor :visitor, :pool
57
- attr_reader :schema_cache, :last_use, :in_use, :logger
58
- alias :in_use? :in_use
77
+ attr_reader :schema_cache, :owner, :logger
78
+ alias :in_use? :owner
79
+
80
+ def self.type_cast_config_to_integer(config)
81
+ if config =~ SIMPLE_INT
82
+ config.to_i
83
+ else
84
+ config
85
+ end
86
+ end
87
+
88
+ def self.type_cast_config_to_boolean(config)
89
+ if config == "false"
90
+ false
91
+ else
92
+ config
93
+ end
94
+ end
59
95
 
60
- def initialize(connection, logger = nil, pool = nil) #:nodoc:
96
+ attr_reader :prepared_statements
97
+
98
+ def initialize(connection, logger = nil, config = {}) # :nodoc:
61
99
  super()
62
100
 
63
- @active = nil
64
101
  @connection = connection
65
- @in_use = false
102
+ @owner = nil
66
103
  @instrumenter = ActiveSupport::Notifications.instrumenter
67
- @last_use = false
68
104
  @logger = logger
69
- @open_transactions = 0
70
- @pool = pool
71
- @query_cache = Hash.new { |h,sql| h[sql] = {} }
72
- @query_cache_enabled = false
105
+ @config = config
106
+ @pool = nil
73
107
  @schema_cache = SchemaCache.new self
74
- @visitor = nil
108
+ @quoted_column_names, @quoted_table_names = {}, {}
109
+ @visitor = arel_visitor
110
+
111
+ if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
112
+ @prepared_statements = true
113
+ @visitor.extend(DetermineIfPreparableVisitor)
114
+ else
115
+ @prepared_statements = false
116
+ end
75
117
  end
76
118
 
119
+ class Version
120
+ include Comparable
121
+
122
+ def initialize(version_string)
123
+ @version = version_string.split('.').map(&:to_i)
124
+ end
125
+
126
+ def <=>(version_string)
127
+ @version <=> version_string.split('.').map(&:to_i)
128
+ end
129
+ end
130
+
131
+ class BindCollector < Arel::Collectors::Bind
132
+ def compile(bvs, conn)
133
+ casted_binds = conn.prepare_binds_for_database(bvs)
134
+ super(casted_binds.map { |value| conn.quote(value) })
135
+ end
136
+ end
137
+
138
+ class SQLString < Arel::Collectors::SQLString
139
+ def compile(bvs, conn)
140
+ super(bvs)
141
+ end
142
+ end
143
+
144
+ def collector
145
+ if prepared_statements
146
+ SQLString.new
147
+ else
148
+ BindCollector.new
149
+ end
150
+ end
151
+
152
+ def arel_visitor # :nodoc:
153
+ Arel::Visitors::ToSql.new(self)
154
+ end
155
+
156
+ def valid_type?(type)
157
+ false
158
+ end
159
+
160
+ def schema_creation
161
+ SchemaCreation.new self
162
+ end
163
+
164
+ # this method must only be called while holding connection pool's mutex
77
165
  def lease
78
- synchronize do
79
- unless in_use
80
- @in_use = true
81
- @last_use = Time.now
166
+ if in_use?
167
+ msg = 'Cannot lease connection, '
168
+ if @owner == Thread.current
169
+ msg << 'it is already leased by the current thread.'
170
+ else
171
+ msg << "it is already in use by a different thread: #{@owner}. " <<
172
+ "Current thread: #{Thread.current}."
82
173
  end
174
+ raise ActiveRecordError, msg
83
175
  end
176
+
177
+ @owner = Thread.current
84
178
  end
85
179
 
180
+ def schema_cache=(cache)
181
+ cache.connection = self
182
+ @schema_cache = cache
183
+ end
184
+
185
+ # this method must only be called while holding connection pool's mutex
86
186
  def expire
87
- @in_use = false
187
+ @owner = nil
188
+ end
189
+
190
+ def unprepared_statement
191
+ old_prepared_statements, @prepared_statements = @prepared_statements, false
192
+ yield
193
+ ensure
194
+ @prepared_statements = old_prepared_statements
88
195
  end
89
196
 
90
197
  # Returns the human-readable name of the adapter. Use mixed case - one
91
198
  # can always use downcase if needed.
92
199
  def adapter_name
93
- 'Abstract'
200
+ self.class::ADAPTER_NAME
94
201
  end
95
202
 
96
- # Does this adapter support migrations? Backend specific, as the
97
- # abstract adapter always returns +false+.
203
+ # Does this adapter support migrations?
98
204
  def supports_migrations?
99
205
  false
100
206
  end
101
207
 
102
208
  # Can this adapter determine the primary key for tables not attached
103
- # to an Active Record class, such as join tables? Backend specific, as
104
- # the abstract adapter always returns +false+.
209
+ # to an Active Record class, such as join tables?
105
210
  def supports_primary_key?
106
211
  false
107
212
  end
108
213
 
109
- # Does this adapter support using DISTINCT within COUNT? This is +true+
110
- # for all adapters except sqlite.
111
- def supports_count_distinct?
112
- true
113
- end
114
-
115
214
  # Does this adapter support DDL rollbacks in transactions? That is, would
116
- # CREATE TABLE or ALTER TABLE get rolled back by a transaction? PostgreSQL,
117
- # SQL Server, and others support this. MySQL and others do not.
215
+ # CREATE TABLE or ALTER TABLE get rolled back by a transaction?
118
216
  def supports_ddl_transactions?
119
217
  false
120
218
  end
@@ -123,16 +221,19 @@ module ActiveRecord
123
221
  false
124
222
  end
125
223
 
126
- # Does this adapter support savepoints? PostgreSQL and MySQL do,
127
- # SQLite < 3.6.8 does not.
224
+ # Does this adapter support savepoints?
128
225
  def supports_savepoints?
129
226
  false
130
227
  end
131
228
 
229
+ # Does this adapter support application-enforced advisory locking?
230
+ def supports_advisory_locks?
231
+ false
232
+ end
233
+
132
234
  # Should primary key values be selected from their corresponding
133
235
  # sequence before the insert statement? If true, next_sequence_value
134
236
  # is called before each insert to set the record's primary key.
135
- # This is false for all adapters but Firebird.
136
237
  def prefetch_primary_key?(table_name = nil)
137
238
  false
138
239
  end
@@ -142,23 +243,102 @@ module ActiveRecord
142
243
  false
143
244
  end
144
245
 
145
- # Does this adapter support explain? As of this writing sqlite3,
146
- # mysql2, and postgresql are the only ones that do.
246
+ # Does this adapter support partial indices?
247
+ def supports_partial_index?
248
+ false
249
+ end
250
+
251
+ # Does this adapter support expression indices?
252
+ def supports_expression_index?
253
+ false
254
+ end
255
+
256
+ # Does this adapter support explain?
147
257
  def supports_explain?
148
258
  false
149
259
  end
150
260
 
151
- # QUOTING ==================================================
261
+ # Does this adapter support setting the isolation level for a transaction?
262
+ def supports_transaction_isolation?
263
+ false
264
+ end
152
265
 
153
- # Override to return the quoted table name. Defaults to column quoting.
154
- def quote_table_name(name)
155
- quote_column_name(name)
266
+ # Does this adapter support database extensions?
267
+ def supports_extensions?
268
+ false
156
269
  end
157
270
 
158
- # Returns a bind substitution value given a +column+ and list of current
159
- # +binds+
160
- def substitute_at(column, index)
161
- Arel::Nodes::BindParam.new '?'
271
+ # Does this adapter support creating indexes in the same statement as
272
+ # creating the table?
273
+ def supports_indexes_in_create?
274
+ false
275
+ end
276
+
277
+ # Does this adapter support creating foreign key constraints?
278
+ def supports_foreign_keys?
279
+ false
280
+ end
281
+
282
+ # Does this adapter support views?
283
+ def supports_views?
284
+ false
285
+ end
286
+
287
+ # Does this adapter support datetime with precision?
288
+ def supports_datetime_with_precision?
289
+ false
290
+ end
291
+
292
+ # Does this adapter support json data type?
293
+ def supports_json?
294
+ false
295
+ end
296
+
297
+ # Does this adapter support metadata comments on database objects (tables, columns, indexes)?
298
+ def supports_comments?
299
+ false
300
+ end
301
+
302
+ # Can comments for tables, columns, and indexes be specified in create/alter table statements?
303
+ def supports_comments_in_create?
304
+ false
305
+ end
306
+
307
+ # Does this adapter support multi-value insert?
308
+ def supports_multi_insert?
309
+ true
310
+ end
311
+
312
+ # This is meant to be implemented by the adapters that support extensions
313
+ def disable_extension(name)
314
+ end
315
+
316
+ # This is meant to be implemented by the adapters that support extensions
317
+ def enable_extension(name)
318
+ end
319
+
320
+ # This is meant to be implemented by the adapters that support advisory
321
+ # locks
322
+ #
323
+ # Return true if we got the lock, otherwise false
324
+ def get_advisory_lock(lock_id) # :nodoc:
325
+ end
326
+
327
+ # This is meant to be implemented by the adapters that support advisory
328
+ # locks.
329
+ #
330
+ # Return true if we released the lock, otherwise false
331
+ def release_advisory_lock(lock_id) # :nodoc:
332
+ end
333
+
334
+ # A list of extensions, to be filled in by adapters that support them.
335
+ def extensions
336
+ []
337
+ end
338
+
339
+ # A list of index algorithms, to be filled by adapters that support them.
340
+ def index_algorithms
341
+ {}
162
342
  end
163
343
 
164
344
  # REFERENTIAL INTEGRITY ====================================
@@ -174,19 +354,21 @@ module ActiveRecord
174
354
  # checking whether the database is actually capable of responding, i.e. whether
175
355
  # the connection isn't stale.
176
356
  def active?
177
- @active != false
178
357
  end
179
358
 
180
359
  # Disconnects from the database if already connected, and establishes a
181
- # new connection with the database.
360
+ # new connection with the database. Implementors should call super if they
361
+ # override the default implementation.
182
362
  def reconnect!
183
- @active = true
363
+ clear_cache!
364
+ reset_transaction
184
365
  end
185
366
 
186
367
  # Disconnects from the database if already connected. Otherwise, this
187
368
  # method does nothing.
188
369
  def disconnect!
189
- @active = false
370
+ clear_cache!
371
+ reset_transaction
190
372
  end
191
373
 
192
374
  # Reset the state of this connection, directing the DBMS to clear
@@ -207,20 +389,19 @@ module ActiveRecord
207
389
  end
208
390
 
209
391
  # Returns true if its required to reload the connection between requests for development mode.
210
- # This is not the case for Ruby/MySQL and it's not necessary for any adapters except SQLite.
211
392
  def requires_reloading?
212
393
  false
213
394
  end
214
395
 
215
396
  # Checks whether the connection to the database is still active (i.e. not stale).
216
- # This is done under the hood by calling <tt>active?</tt>. If the connection
397
+ # This is done under the hood by calling #active?. If the connection
217
398
  # is no longer active, then this method will reconnect to the database.
218
399
  def verify!(*ignored)
219
400
  reconnect! unless active?
220
401
  end
221
402
 
222
403
  # Provides access to the underlying database driver for this adapter. For
223
- # example, this method returns a Mysql object in case of MysqlAdapter,
404
+ # example, this method returns a Mysql2::Client object in case of Mysql2Adapter,
224
405
  # and a PGconn object in case of PostgreSQLAdapter.
225
406
  #
226
407
  # This is useful for when you need to call a proprietary method such as
@@ -229,68 +410,178 @@ module ActiveRecord
229
410
  @connection
230
411
  end
231
412
 
232
- attr_reader :open_transactions
413
+ def case_sensitive_comparison(table, attribute, column, value)
414
+ if value.nil?
415
+ table[attribute].eq(value)
416
+ else
417
+ table[attribute].eq(Arel::Nodes::BindParam.new)
418
+ end
419
+ end
420
+
421
+ def case_insensitive_comparison(table, attribute, column, value)
422
+ if can_perform_case_insensitive_comparison_for?(column)
423
+ table[attribute].lower.eq(table.lower(Arel::Nodes::BindParam.new))
424
+ else
425
+ table[attribute].eq(Arel::Nodes::BindParam.new)
426
+ end
427
+ end
428
+
429
+ def can_perform_case_insensitive_comparison_for?(column)
430
+ true
431
+ end
432
+ private :can_perform_case_insensitive_comparison_for?
433
+
434
+ # Check the connection back in to the connection pool
435
+ def close
436
+ pool.checkin self
437
+ end
233
438
 
234
- def increment_open_transactions
235
- @open_transactions += 1
439
+ def type_map # :nodoc:
440
+ @type_map ||= Type::TypeMap.new.tap do |mapping|
441
+ initialize_type_map(mapping)
442
+ end
236
443
  end
237
444
 
238
- def decrement_open_transactions
239
- @open_transactions -= 1
445
+ def new_column(name, default, sql_type_metadata, null, table_name, default_function = nil, collation = nil) # :nodoc:
446
+ Column.new(name, default, sql_type_metadata, null, table_name, default_function, collation)
240
447
  end
241
448
 
242
- def transaction_joinable=(joinable)
243
- @transaction_joinable = joinable
449
+ def lookup_cast_type(sql_type) # :nodoc:
450
+ type_map.lookup(sql_type)
244
451
  end
245
452
 
246
- def create_savepoint
453
+ def column_name_for_operation(operation, node) # :nodoc:
454
+ visitor.accept(node, collector).value
247
455
  end
248
456
 
249
- def rollback_to_savepoint
457
+ def combine_bind_parameters(
458
+ from_clause: [],
459
+ join_clause: [],
460
+ where_clause: [],
461
+ having_clause: [],
462
+ limit: nil,
463
+ offset: nil
464
+ ) # :nodoc:
465
+ result = from_clause + join_clause + where_clause + having_clause
466
+ if limit
467
+ result << limit
468
+ end
469
+ if offset
470
+ result << offset
471
+ end
472
+ result
250
473
  end
251
474
 
252
- def release_savepoint
475
+ protected
476
+
477
+ def initialize_type_map(m) # :nodoc:
478
+ register_class_with_limit m, %r(boolean)i, Type::Boolean
479
+ register_class_with_limit m, %r(char)i, Type::String
480
+ register_class_with_limit m, %r(binary)i, Type::Binary
481
+ register_class_with_limit m, %r(text)i, Type::Text
482
+ register_class_with_precision m, %r(date)i, Type::Date
483
+ register_class_with_precision m, %r(time)i, Type::Time
484
+ register_class_with_precision m, %r(datetime)i, Type::DateTime
485
+ register_class_with_limit m, %r(float)i, Type::Float
486
+ register_class_with_limit m, %r(int)i, Type::Integer
487
+
488
+ m.alias_type %r(blob)i, 'binary'
489
+ m.alias_type %r(clob)i, 'text'
490
+ m.alias_type %r(timestamp)i, 'datetime'
491
+ m.alias_type %r(numeric)i, 'decimal'
492
+ m.alias_type %r(number)i, 'decimal'
493
+ m.alias_type %r(double)i, 'float'
494
+
495
+ m.register_type(%r(decimal)i) do |sql_type|
496
+ scale = extract_scale(sql_type)
497
+ precision = extract_precision(sql_type)
498
+
499
+ if scale == 0
500
+ # FIXME: Remove this class as well
501
+ Type::DecimalWithoutScale.new(precision: precision)
502
+ else
503
+ Type::Decimal.new(precision: precision, scale: scale)
504
+ end
505
+ end
253
506
  end
254
507
 
255
- def case_sensitive_modifier(node)
256
- node
508
+ def reload_type_map # :nodoc:
509
+ type_map.clear
510
+ initialize_type_map(type_map)
257
511
  end
258
512
 
259
- def case_insensitive_comparison(table, attribute, column, value)
260
- table[attribute].lower.eq(table.lower(value))
513
+ def register_class_with_limit(mapping, key, klass) # :nodoc:
514
+ mapping.register_type(key) do |*args|
515
+ limit = extract_limit(args.last)
516
+ klass.new(limit: limit)
517
+ end
261
518
  end
262
519
 
263
- def current_savepoint_name
264
- "active_record_#{open_transactions}"
520
+ def register_class_with_precision(mapping, key, klass) # :nodoc:
521
+ mapping.register_type(key) do |*args|
522
+ precision = extract_precision(args.last)
523
+ klass.new(precision: precision)
524
+ end
265
525
  end
266
526
 
267
- # Check the connection back in to the connection pool
268
- def close
269
- pool.checkin self
527
+ def extract_scale(sql_type) # :nodoc:
528
+ case sql_type
529
+ when /\((\d+)\)/ then 0
530
+ when /\((\d+)(,(\d+))\)/ then $3.to_i
531
+ end
270
532
  end
271
533
 
272
- protected
534
+ def extract_precision(sql_type) # :nodoc:
535
+ $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
536
+ end
273
537
 
274
- def log(sql, name = "SQL", binds = [])
275
- @instrumenter.instrument(
276
- "sql.active_record",
277
- :sql => sql,
278
- :name => name,
279
- :connection_id => object_id,
280
- :binds => binds) { yield }
281
- rescue Exception => e
282
- message = "#{e.class.name}: #{e.message}: #{sql}"
283
- @logger.debug message if @logger
284
- exception = translate_exception(e, message)
285
- exception.set_backtrace e.backtrace
286
- raise exception
538
+ def extract_limit(sql_type) # :nodoc:
539
+ case sql_type
540
+ when /^bigint/i
541
+ 8
542
+ when /\((.*)\)/
543
+ $1.to_i
287
544
  end
545
+ end
288
546
 
289
- def translate_exception(e, message)
290
- # override in derived class
291
- ActiveRecord::StatementInvalid.new(message)
547
+ def translate_exception_class(e, sql)
548
+ begin
549
+ message = "#{e.class.name}: #{e.message}: #{sql}"
550
+ rescue Encoding::CompatibilityError
551
+ message = "#{e.class.name}: #{e.message.force_encoding sql.encoding}: #{sql}"
292
552
  end
293
553
 
554
+ exception = translate_exception(e, message)
555
+ exception.set_backtrace e.backtrace
556
+ exception
557
+ end
558
+
559
+ def log(sql, name = "SQL", binds = [], statement_name = nil)
560
+ @instrumenter.instrument(
561
+ "sql.active_record",
562
+ :sql => sql,
563
+ :name => name,
564
+ :connection_id => object_id,
565
+ :statement_name => statement_name,
566
+ :binds => binds) { yield }
567
+ rescue => e
568
+ raise translate_exception_class(e, sql)
569
+ end
570
+
571
+ def translate_exception(exception, message)
572
+ # override in derived class
573
+ ActiveRecord::StatementInvalid.new(message)
574
+ end
575
+
576
+ def without_prepared_statement?(binds)
577
+ !prepared_statements || binds.empty?
578
+ end
579
+
580
+ def column_for(table_name, column_name) # :nodoc:
581
+ column_name = column_name.to_s
582
+ columns(table_name).detect { |c| c.name == column_name } ||
583
+ raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
584
+ end
294
585
  end
295
586
  end
296
587
  end