activerecord 4.2.0 → 5.2.8.1

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 (274) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +640 -928
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +10 -11
  5. data/examples/performance.rb +32 -31
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +264 -247
  8. data/lib/active_record/association_relation.rb +24 -6
  9. data/lib/active_record/associations/alias_tracker.rb +29 -35
  10. data/lib/active_record/associations/association.rb +87 -41
  11. data/lib/active_record/associations/association_scope.rb +106 -132
  12. data/lib/active_record/associations/belongs_to_association.rb +55 -36
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
  14. data/lib/active_record/associations/builder/association.rb +29 -38
  15. data/lib/active_record/associations/builder/belongs_to.rb +77 -30
  16. data/lib/active_record/associations/builder/collection_association.rb +14 -23
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +50 -39
  18. data/lib/active_record/associations/builder/has_many.rb +6 -4
  19. data/lib/active_record/associations/builder/has_one.rb +13 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +15 -11
  21. data/lib/active_record/associations/collection_association.rb +145 -266
  22. data/lib/active_record/associations/collection_proxy.rb +242 -138
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +35 -75
  25. data/lib/active_record/associations/has_many_through_association.rb +51 -69
  26. data/lib/active_record/associations/has_one_association.rb +39 -24
  27. data/lib/active_record/associations/has_one_through_association.rb +18 -9
  28. data/lib/active_record/associations/join_dependency/join_association.rb +40 -81
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  31. data/lib/active_record/associations/join_dependency.rb +134 -154
  32. data/lib/active_record/associations/preloader/association.rb +85 -116
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -74
  34. data/lib/active_record/associations/preloader.rb +83 -93
  35. data/lib/active_record/associations/singular_association.rb +27 -40
  36. data/lib/active_record/associations/through_association.rb +48 -23
  37. data/lib/active_record/associations.rb +1732 -1596
  38. data/lib/active_record/attribute_assignment.rb +58 -182
  39. data/lib/active_record/attribute_decorators.rb +39 -15
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -5
  41. data/lib/active_record/attribute_methods/dirty.rb +94 -125
  42. data/lib/active_record/attribute_methods/primary_key.rb +86 -71
  43. data/lib/active_record/attribute_methods/query.rb +4 -2
  44. data/lib/active_record/attribute_methods/read.rb +45 -63
  45. data/lib/active_record/attribute_methods/serialization.rb +40 -20
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +62 -36
  47. data/lib/active_record/attribute_methods/write.rb +31 -46
  48. data/lib/active_record/attribute_methods.rb +170 -117
  49. data/lib/active_record/attributes.rb +201 -74
  50. data/lib/active_record/autosave_association.rb +118 -45
  51. data/lib/active_record/base.rb +60 -48
  52. data/lib/active_record/callbacks.rb +97 -57
  53. data/lib/active_record/coders/json.rb +3 -1
  54. data/lib/active_record/coders/yaml_column.rb +37 -13
  55. data/lib/active_record/collection_cache_key.rb +53 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -284
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +254 -87
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +72 -22
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -52
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -217
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +81 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +617 -212
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +139 -75
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +332 -191
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +567 -563
  69. data/lib/active_record/connection_adapters/column.rb +50 -41
  70. data/lib/active_record/connection_adapters/connection_specification.rb +147 -135
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +42 -195
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -115
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +10 -6
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +7 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  99. data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +65 -51
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +107 -47
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +144 -90
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +466 -280
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +439 -330
  117. data/lib/active_record/connection_adapters/schema_cache.rb +48 -24
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +269 -324
  126. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  127. data/lib/active_record/connection_handling.rb +40 -27
  128. data/lib/active_record/core.rb +205 -202
  129. data/lib/active_record/counter_cache.rb +80 -37
  130. data/lib/active_record/define_callbacks.rb +22 -0
  131. data/lib/active_record/dynamic_matchers.rb +87 -105
  132. data/lib/active_record/enum.rb +136 -90
  133. data/lib/active_record/errors.rb +180 -52
  134. data/lib/active_record/explain.rb +23 -11
  135. data/lib/active_record/explain_registry.rb +4 -2
  136. data/lib/active_record/explain_subscriber.rb +11 -6
  137. data/lib/active_record/fixture_set/file.rb +35 -9
  138. data/lib/active_record/fixtures.rb +193 -135
  139. data/lib/active_record/gem_version.rb +5 -3
  140. data/lib/active_record/inheritance.rb +148 -112
  141. data/lib/active_record/integration.rb +70 -28
  142. data/lib/active_record/internal_metadata.rb +45 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  144. data/lib/active_record/locale/en.yml +3 -2
  145. data/lib/active_record/locking/optimistic.rb +92 -98
  146. data/lib/active_record/locking/pessimistic.rb +15 -3
  147. data/lib/active_record/log_subscriber.rb +95 -33
  148. data/lib/active_record/migration/command_recorder.rb +133 -90
  149. data/lib/active_record/migration/compatibility.rb +217 -0
  150. data/lib/active_record/migration/join_table.rb +8 -6
  151. data/lib/active_record/migration.rb +594 -267
  152. data/lib/active_record/model_schema.rb +292 -111
  153. data/lib/active_record/nested_attributes.rb +266 -214
  154. data/lib/active_record/no_touching.rb +8 -2
  155. data/lib/active_record/null_relation.rb +24 -37
  156. data/lib/active_record/persistence.rb +350 -119
  157. data/lib/active_record/query_cache.rb +13 -24
  158. data/lib/active_record/querying.rb +19 -17
  159. data/lib/active_record/railtie.rb +117 -35
  160. data/lib/active_record/railties/console_sandbox.rb +2 -0
  161. data/lib/active_record/railties/controller_runtime.rb +9 -3
  162. data/lib/active_record/railties/databases.rake +160 -174
  163. data/lib/active_record/readonly_attributes.rb +5 -4
  164. data/lib/active_record/reflection.rb +447 -288
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  166. data/lib/active_record/relation/batches.rb +204 -55
  167. data/lib/active_record/relation/calculations.rb +259 -244
  168. data/lib/active_record/relation/delegation.rb +67 -60
  169. data/lib/active_record/relation/finder_methods.rb +290 -253
  170. data/lib/active_record/relation/from_clause.rb +26 -0
  171. data/lib/active_record/relation/merger.rb +91 -68
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -23
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  174. data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  179. data/lib/active_record/relation/predicate_builder.rb +118 -92
  180. data/lib/active_record/relation/query_attribute.rb +45 -0
  181. data/lib/active_record/relation/query_methods.rb +446 -389
  182. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  183. data/lib/active_record/relation/spawn_methods.rb +18 -16
  184. data/lib/active_record/relation/where_clause.rb +186 -0
  185. data/lib/active_record/relation/where_clause_factory.rb +34 -0
  186. data/lib/active_record/relation.rb +287 -339
  187. data/lib/active_record/result.rb +54 -36
  188. data/lib/active_record/runtime_registry.rb +6 -4
  189. data/lib/active_record/sanitization.rb +155 -124
  190. data/lib/active_record/schema.rb +30 -24
  191. data/lib/active_record/schema_dumper.rb +91 -87
  192. data/lib/active_record/schema_migration.rb +19 -19
  193. data/lib/active_record/scoping/default.rb +102 -84
  194. data/lib/active_record/scoping/named.rb +81 -32
  195. data/lib/active_record/scoping.rb +45 -26
  196. data/lib/active_record/secure_token.rb +40 -0
  197. data/lib/active_record/serialization.rb +5 -5
  198. data/lib/active_record/statement_cache.rb +45 -35
  199. data/lib/active_record/store.rb +42 -36
  200. data/lib/active_record/suppressor.rb +61 -0
  201. data/lib/active_record/table_metadata.rb +82 -0
  202. data/lib/active_record/tasks/database_tasks.rb +136 -95
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +59 -89
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -31
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -16
  206. data/lib/active_record/timestamp.rb +70 -38
  207. data/lib/active_record/touch_later.rb +64 -0
  208. data/lib/active_record/transactions.rb +208 -123
  209. data/lib/active_record/translation.rb +2 -0
  210. data/lib/active_record/type/adapter_specific_registry.rb +136 -0
  211. data/lib/active_record/type/date.rb +4 -41
  212. data/lib/active_record/type/date_time.rb +4 -38
  213. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  214. data/lib/active_record/type/hash_lookup_type_map.rb +13 -5
  215. data/lib/active_record/type/internal/timezone.rb +17 -0
  216. data/lib/active_record/type/json.rb +30 -0
  217. data/lib/active_record/type/serialized.rb +30 -15
  218. data/lib/active_record/type/text.rb +2 -2
  219. data/lib/active_record/type/time.rb +11 -16
  220. data/lib/active_record/type/type_map.rb +15 -17
  221. data/lib/active_record/type/unsigned_integer.rb +9 -7
  222. data/lib/active_record/type.rb +79 -23
  223. data/lib/active_record/type_caster/connection.rb +33 -0
  224. data/lib/active_record/type_caster/map.rb +23 -0
  225. data/lib/active_record/type_caster.rb +9 -0
  226. data/lib/active_record/validations/absence.rb +25 -0
  227. data/lib/active_record/validations/associated.rb +13 -4
  228. data/lib/active_record/validations/length.rb +26 -0
  229. data/lib/active_record/validations/presence.rb +14 -13
  230. data/lib/active_record/validations/uniqueness.rb +41 -32
  231. data/lib/active_record/validations.rb +38 -35
  232. data/lib/active_record/version.rb +3 -1
  233. data/lib/active_record.rb +36 -21
  234. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  235. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  236. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -35
  237. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +8 -6
  238. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -7
  239. data/lib/rails/generators/active_record/migration.rb +18 -1
  240. data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
  241. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +3 -0
  242. data/lib/rails/generators/active_record.rb +7 -5
  243. metadata +77 -53
  244. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  245. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  246. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  247. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  248. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  249. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  250. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  251. data/lib/active_record/attribute.rb +0 -149
  252. data/lib/active_record/attribute_set/builder.rb +0 -86
  253. data/lib/active_record/attribute_set.rb +0 -77
  254. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  255. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  256. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  257. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  258. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  259. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  260. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  261. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  262. data/lib/active_record/type/big_integer.rb +0 -13
  263. data/lib/active_record/type/binary.rb +0 -50
  264. data/lib/active_record/type/boolean.rb +0 -30
  265. data/lib/active_record/type/decimal.rb +0 -40
  266. data/lib/active_record/type/decorator.rb +0 -14
  267. data/lib/active_record/type/float.rb +0 -19
  268. data/lib/active_record/type/integer.rb +0 -55
  269. data/lib/active_record/type/mutable.rb +0 -16
  270. data/lib/active_record/type/numeric.rb +0 -36
  271. data/lib/active_record/type/string.rb +0 -36
  272. data/lib/active_record/type/time_value.rb +0 -38
  273. data/lib/active_record/type/value.rb +0 -101
  274. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,14 +1,15 @@
1
- require 'date'
2
- require 'bigdecimal'
3
- require 'bigdecimal/util'
4
- require 'active_record/type'
5
- require 'active_support/core_ext/benchmark'
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'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/connection_adapters/determine_if_preparable_visitor"
4
+ require "active_record/connection_adapters/schema_cache"
5
+ require "active_record/connection_adapters/sql_type_metadata"
6
+ require "active_record/connection_adapters/abstract/schema_dumper"
7
+ require "active_record/connection_adapters/abstract/schema_creation"
8
+ require "active_support/concurrency/load_interlock_aware_monitor"
9
+ require "arel/collectors/bind"
10
+ require "arel/collectors/composite"
11
+ require "arel/collectors/sql_string"
12
+ require "arel/collectors/substitute_binds"
12
13
 
13
14
  module ActiveRecord
14
15
  module ConnectionAdapters # :nodoc:
@@ -17,22 +18,22 @@ module ActiveRecord
17
18
  autoload :Column
18
19
  autoload :ConnectionSpecification
19
20
 
20
- autoload_at 'active_record/connection_adapters/abstract/schema_definitions' do
21
+ autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
21
22
  autoload :IndexDefinition
22
23
  autoload :ColumnDefinition
23
24
  autoload :ChangeColumnDefinition
25
+ autoload :ForeignKeyDefinition
24
26
  autoload :TableDefinition
25
27
  autoload :Table
26
28
  autoload :AlterTable
27
- autoload :TimestampDefaultDeprecation
29
+ autoload :ReferenceDefinition
28
30
  end
29
31
 
30
- autoload_at 'active_record/connection_adapters/abstract/connection_pool' do
32
+ autoload_at "active_record/connection_adapters/abstract/connection_pool" do
31
33
  autoload :ConnectionHandler
32
- autoload :ConnectionManagement
33
34
  end
34
35
 
35
- autoload_under 'abstract' do
36
+ autoload_under "abstract" do
36
37
  autoload :SchemaStatements
37
38
  autoload :DatabaseStatements
38
39
  autoload :DatabaseLimits
@@ -42,7 +43,7 @@ module ActiveRecord
42
43
  autoload :Savepoints
43
44
  end
44
45
 
45
- autoload_at 'active_record/connection_adapters/abstract/transaction' do
46
+ autoload_at "active_record/connection_adapters/abstract/transaction" do
46
47
  autoload :TransactionManager
47
48
  autoload :NullTransaction
48
49
  autoload :RealTransaction
@@ -54,34 +55,35 @@ module ActiveRecord
54
55
  # related classes form the abstraction layer which makes this possible.
55
56
  # An AbstractAdapter represents a connection to a database, and provides an
56
57
  # abstract interface for database-specific functionality such as establishing
57
- # a connection, escaping values, building the right SQL fragments for ':offset'
58
- # and ':limit' options, etc.
58
+ # a connection, escaping values, building the right SQL fragments for +:offset+
59
+ # and +:limit+ options, etc.
59
60
  #
60
61
  # All the concrete database adapters follow the interface laid down in this class.
61
- # ActiveRecord::Base.connection returns an AbstractAdapter object, which
62
+ # {ActiveRecord::Base.connection}[rdoc-ref:ConnectionHandling#connection] returns an AbstractAdapter object, which
62
63
  # you can use.
63
64
  #
64
65
  # Most of the methods in the adapter are useful during migrations. Most
65
- # notably, the instance methods provided by SchemaStatement are very useful.
66
+ # notably, the instance methods provided by SchemaStatements are very useful.
66
67
  class AbstractAdapter
67
- ADAPTER_NAME = 'Abstract'.freeze
68
+ ADAPTER_NAME = "Abstract".freeze
69
+ include ActiveSupport::Callbacks
70
+ define_callbacks :checkout, :checkin
71
+
68
72
  include Quoting, DatabaseStatements, SchemaStatements
69
73
  include DatabaseLimits
70
74
  include QueryCache
71
- include ActiveSupport::Callbacks
72
- include MonitorMixin
73
- include ColumnDumper
75
+ include Savepoints
74
76
 
75
77
  SIMPLE_INT = /\A\d+\z/
76
78
 
77
- define_callbacks :checkout, :checkin
78
-
79
79
  attr_accessor :visitor, :pool
80
- attr_reader :schema_cache, :owner, :logger
80
+ attr_reader :schema_cache, :owner, :logger, :prepared_statements, :lock
81
81
  alias :in_use? :owner
82
82
 
83
83
  def self.type_cast_config_to_integer(config)
84
- if config =~ SIMPLE_INT
84
+ if config.is_a?(Integer)
85
+ config
86
+ elsif config =~ SIMPLE_INT
85
87
  config.to_i
86
88
  else
87
89
  config
@@ -96,55 +98,67 @@ module ActiveRecord
96
98
  end
97
99
  end
98
100
 
99
- attr_reader :prepared_statements
100
-
101
- def initialize(connection, logger = nil, pool = nil) #:nodoc:
101
+ def initialize(connection, logger = nil, config = {}) # :nodoc:
102
102
  super()
103
103
 
104
104
  @connection = connection
105
105
  @owner = nil
106
106
  @instrumenter = ActiveSupport::Notifications.instrumenter
107
107
  @logger = logger
108
- @pool = pool
108
+ @config = config
109
+ @pool = nil
110
+ @idle_since = Concurrent.monotonic_time
109
111
  @schema_cache = SchemaCache.new self
110
- @visitor = nil
111
- @prepared_statements = false
112
- end
112
+ @quoted_column_names, @quoted_table_names = {}, {}
113
+ @visitor = arel_visitor
114
+ @lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
113
115
 
114
- class BindCollector < Arel::Collectors::Bind
115
- def compile(bvs, conn)
116
- super(bvs.map { |bv| conn.quote(*bv.reverse) })
116
+ if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
117
+ @prepared_statements = true
118
+ @visitor.extend(DetermineIfPreparableVisitor)
119
+ else
120
+ @prepared_statements = false
117
121
  end
118
122
  end
119
123
 
120
- class SQLString < Arel::Collectors::SQLString
121
- def compile(bvs, conn)
122
- super(bvs)
123
- end
124
+ def migrations_paths # :nodoc:
125
+ @config[:migrations_paths] || Migrator.migrations_paths
124
126
  end
125
127
 
126
- def collector
127
- if prepared_statements
128
- SQLString.new
129
- else
130
- BindCollector.new
131
- end
128
+ def migration_context # :nodoc:
129
+ MigrationContext.new(migrations_paths)
132
130
  end
133
131
 
134
- def valid_type?(type)
135
- true
132
+ class Version
133
+ include Comparable
134
+
135
+ def initialize(version_string)
136
+ @version = version_string.split(".").map(&:to_i)
137
+ end
138
+
139
+ def <=>(version_string)
140
+ @version <=> version_string.split(".").map(&:to_i)
141
+ end
136
142
  end
137
143
 
138
- def schema_creation
139
- SchemaCreation.new self
144
+ def valid_type?(type) # :nodoc:
145
+ !native_database_types[type].nil?
140
146
  end
141
147
 
148
+ # this method must only be called while holding connection pool's mutex
142
149
  def lease
143
- synchronize do
144
- unless in_use?
145
- @owner = Thread.current
150
+ if in_use?
151
+ msg = "Cannot lease connection, ".dup
152
+ if @owner == Thread.current
153
+ msg << "it is already leased by the current thread."
154
+ else
155
+ msg << "it is already in use by a different thread: #{@owner}. " \
156
+ "Current thread: #{Thread.current}."
146
157
  end
158
+ raise ActiveRecordError, msg
147
159
  end
160
+
161
+ @owner = Thread.current
148
162
  end
149
163
 
150
164
  def schema_cache=(cache)
@@ -152,8 +166,39 @@ module ActiveRecord
152
166
  @schema_cache = cache
153
167
  end
154
168
 
169
+ # this method must only be called while holding connection pool's mutex
155
170
  def expire
156
- @owner = nil
171
+ if in_use?
172
+ if @owner != Thread.current
173
+ raise ActiveRecordError, "Cannot expire connection, " \
174
+ "it is owned by a different thread: #{@owner}. " \
175
+ "Current thread: #{Thread.current}."
176
+ end
177
+
178
+ @idle_since = Concurrent.monotonic_time
179
+ @owner = nil
180
+ else
181
+ raise ActiveRecordError, "Cannot expire connection, it is not currently leased."
182
+ end
183
+ end
184
+
185
+ # this method must only be called while holding connection pool's mutex (and a desire for segfaults)
186
+ def steal! # :nodoc:
187
+ if in_use?
188
+ if @owner != Thread.current
189
+ pool.send :remove_connection_from_thread_cache, self, @owner
190
+
191
+ @owner = Thread.current
192
+ end
193
+ else
194
+ raise ActiveRecordError, "Cannot steal connection, it is not currently leased."
195
+ end
196
+ end
197
+
198
+ # Seconds since this connection was returned to the pool
199
+ def seconds_idle # :nodoc:
200
+ return 0 if in_use?
201
+ Concurrent.monotonic_time - @idle_since
157
202
  end
158
203
 
159
204
  def unprepared_statement
@@ -169,17 +214,6 @@ module ActiveRecord
169
214
  self.class::ADAPTER_NAME
170
215
  end
171
216
 
172
- # Does this adapter support migrations?
173
- def supports_migrations?
174
- false
175
- end
176
-
177
- # Can this adapter determine the primary key for tables not attached
178
- # to an Active Record class, such as join tables?
179
- def supports_primary_key?
180
- false
181
- end
182
-
183
217
  # Does this adapter support DDL rollbacks in transactions? That is, would
184
218
  # CREATE TABLE or ALTER TABLE get rolled back by a transaction?
185
219
  def supports_ddl_transactions?
@@ -195,6 +229,11 @@ module ActiveRecord
195
229
  false
196
230
  end
197
231
 
232
+ # Does this adapter support application-enforced advisory locking?
233
+ def supports_advisory_locks?
234
+ false
235
+ end
236
+
198
237
  # Should primary key values be selected from their corresponding
199
238
  # sequence before the insert statement? If true, next_sequence_value
200
239
  # is called before each insert to set the record's primary key.
@@ -212,6 +251,11 @@ module ActiveRecord
212
251
  false
213
252
  end
214
253
 
254
+ # Does this adapter support expression indices?
255
+ def supports_expression_index?
256
+ false
257
+ end
258
+
215
259
  # Does this adapter support explain?
216
260
  def supports_explain?
217
261
  false
@@ -238,11 +282,57 @@ module ActiveRecord
238
282
  false
239
283
  end
240
284
 
285
+ # Does this adapter support creating invalid constraints?
286
+ def supports_validate_constraints?
287
+ false
288
+ end
289
+
290
+ # Does this adapter support creating foreign key constraints
291
+ # in the same statement as creating the table?
292
+ def supports_foreign_keys_in_create?
293
+ supports_foreign_keys?
294
+ end
295
+
241
296
  # Does this adapter support views?
242
297
  def supports_views?
243
298
  false
244
299
  end
245
300
 
301
+ # Does this adapter support datetime with precision?
302
+ def supports_datetime_with_precision?
303
+ false
304
+ end
305
+
306
+ # Does this adapter support json data type?
307
+ def supports_json?
308
+ false
309
+ end
310
+
311
+ # Does this adapter support metadata comments on database objects (tables, columns, indexes)?
312
+ def supports_comments?
313
+ false
314
+ end
315
+
316
+ # Can comments for tables, columns, and indexes be specified in create/alter table statements?
317
+ def supports_comments_in_create?
318
+ false
319
+ end
320
+
321
+ # Does this adapter support multi-value insert?
322
+ def supports_multi_insert?
323
+ true
324
+ end
325
+
326
+ # Does this adapter support virtual columns?
327
+ def supports_virtual_columns?
328
+ false
329
+ end
330
+
331
+ # Does this adapter support foreign/external tables?
332
+ def supports_foreign_tables?
333
+ false
334
+ end
335
+
246
336
  # This is meant to be implemented by the adapters that support extensions
247
337
  def disable_extension(name)
248
338
  end
@@ -251,6 +341,20 @@ module ActiveRecord
251
341
  def enable_extension(name)
252
342
  end
253
343
 
344
+ # This is meant to be implemented by the adapters that support advisory
345
+ # locks
346
+ #
347
+ # Return true if we got the lock, otherwise false
348
+ def get_advisory_lock(lock_id) # :nodoc:
349
+ end
350
+
351
+ # This is meant to be implemented by the adapters that support advisory
352
+ # locks.
353
+ #
354
+ # Return true if we released the lock, otherwise false
355
+ def release_advisory_lock(lock_id) # :nodoc:
356
+ end
357
+
254
358
  # A list of extensions, to be filled in by adapters that support them.
255
359
  def extensions
256
360
  []
@@ -261,14 +365,6 @@ module ActiveRecord
261
365
  {}
262
366
  end
263
367
 
264
- # QUOTING ==================================================
265
-
266
- # Returns a bind substitution value given a bind +column+
267
- # NOTE: The column param is currently being used by the sqlserver-adapter
268
- def substitute_at(column, _unused = 0)
269
- Arel::Nodes::BindParam.new
270
- end
271
-
272
368
  # REFERENTIAL INTEGRITY ====================================
273
369
 
274
370
  # Override to turn off referential integrity while executing <tt>&block</tt>.
@@ -299,6 +395,19 @@ module ActiveRecord
299
395
  reset_transaction
300
396
  end
301
397
 
398
+ # Immediately forget this connection ever existed. Unlike disconnect!,
399
+ # this will not communicate with the server.
400
+ #
401
+ # After calling this method, the behavior of all other methods becomes
402
+ # undefined. This is called internally just before a forked process gets
403
+ # rid of a connection that belonged to its parent.
404
+ def discard!
405
+ # This should be overridden by concrete adapters.
406
+ #
407
+ # Prevent @connection's finalizer from touching the socket, or
408
+ # otherwise communicating with its server, when it is collected.
409
+ end
410
+
302
411
  # Reset the state of this connection, directing the DBMS to clear
303
412
  # transactions and other connection-related server-side state. Usually a
304
413
  # database-dependent operation.
@@ -322,15 +431,15 @@ module ActiveRecord
322
431
  end
323
432
 
324
433
  # Checks whether the connection to the database is still active (i.e. not stale).
325
- # This is done under the hood by calling <tt>active?</tt>. If the connection
434
+ # This is done under the hood by calling #active?. If the connection
326
435
  # is no longer active, then this method will reconnect to the database.
327
- def verify!(*ignored)
436
+ def verify!
328
437
  reconnect! unless active?
329
438
  end
330
439
 
331
440
  # Provides access to the underlying database driver for this adapter. For
332
- # example, this method returns a Mysql object in case of MysqlAdapter,
333
- # and a PGconn object in case of PostgreSQLAdapter.
441
+ # example, this method returns a Mysql2::Client object in case of Mysql2Adapter,
442
+ # and a PG::Connection object in case of PostgreSQLAdapter.
334
443
  #
335
444
  # This is useful for when you need to call a proprietary method such as
336
445
  # PostgreSQL's lo_* methods.
@@ -338,150 +447,182 @@ module ActiveRecord
338
447
  @connection
339
448
  end
340
449
 
341
- def create_savepoint(name = nil)
342
- end
343
-
344
- def rollback_to_savepoint(name = nil)
450
+ def case_sensitive_comparison(table, attribute, column, value) # :nodoc:
451
+ table[attribute].eq(value)
345
452
  end
346
453
 
347
- def release_savepoint(name = nil)
348
- end
349
-
350
- def case_sensitive_modifier(node, table_attribute)
351
- node
352
- end
353
-
354
- def case_sensitive_comparison(table, attribute, column, value)
355
- table_attr = table[attribute]
356
- value = case_sensitive_modifier(value, table_attr) unless value.nil?
357
- table_attr.eq(value)
358
- end
359
-
360
- def case_insensitive_comparison(table, attribute, column, value)
361
- table[attribute].lower.eq(table.lower(value))
454
+ def case_insensitive_comparison(table, attribute, column, value) # :nodoc:
455
+ if can_perform_case_insensitive_comparison_for?(column)
456
+ table[attribute].lower.eq(table.lower(value))
457
+ else
458
+ table[attribute].eq(value)
459
+ end
362
460
  end
363
461
 
364
- def current_savepoint_name
365
- current_transaction.savepoint_name
462
+ def can_perform_case_insensitive_comparison_for?(column)
463
+ true
366
464
  end
465
+ private :can_perform_case_insensitive_comparison_for?
367
466
 
368
467
  # Check the connection back in to the connection pool
369
468
  def close
370
469
  pool.checkin self
371
470
  end
372
471
 
373
- def type_map # :nodoc:
374
- @type_map ||= Type::TypeMap.new.tap do |mapping|
375
- initialize_type_map(mapping)
376
- end
472
+ def column_name_for_operation(operation, node) # :nodoc:
473
+ column_name_from_arel_node(node)
377
474
  end
378
475
 
379
- def new_column(name, default, cast_type, sql_type = nil, null = true)
380
- Column.new(name, default, cast_type, sql_type, null)
476
+ def column_name_from_arel_node(node) # :nodoc:
477
+ visitor.accept(node, Arel::Collectors::SQLString.new).value
381
478
  end
382
479
 
383
- def lookup_cast_type(sql_type) # :nodoc:
384
- type_map.lookup(sql_type)
480
+ def default_index_type?(index) # :nodoc:
481
+ index.using.nil?
385
482
  end
386
483
 
387
- def column_name_for_operation(operation, node) # :nodoc:
388
- node.to_sql
389
- end
390
-
391
- protected
392
-
393
- def initialize_type_map(m) # :nodoc:
394
- register_class_with_limit m, %r(boolean)i, Type::Boolean
395
- register_class_with_limit m, %r(char)i, Type::String
396
- register_class_with_limit m, %r(binary)i, Type::Binary
397
- register_class_with_limit m, %r(text)i, Type::Text
398
- register_class_with_limit m, %r(date)i, Type::Date
399
- register_class_with_limit m, %r(time)i, Type::Time
400
- register_class_with_limit m, %r(datetime)i, Type::DateTime
401
- register_class_with_limit m, %r(float)i, Type::Float
402
- register_class_with_limit m, %r(int)i, Type::Integer
403
-
404
- m.alias_type %r(blob)i, 'binary'
405
- m.alias_type %r(clob)i, 'text'
406
- m.alias_type %r(timestamp)i, 'datetime'
407
- m.alias_type %r(numeric)i, 'decimal'
408
- m.alias_type %r(number)i, 'decimal'
409
- m.alias_type %r(double)i, 'float'
410
-
411
- m.register_type(%r(decimal)i) do |sql_type|
412
- scale = extract_scale(sql_type)
413
- precision = extract_precision(sql_type)
414
-
415
- if scale == 0
416
- # FIXME: Remove this class as well
417
- Type::DecimalWithoutScale.new(precision: precision)
418
- else
419
- Type::Decimal.new(precision: precision, scale: scale)
484
+ private
485
+ def type_map
486
+ @type_map ||= Type::TypeMap.new.tap do |mapping|
487
+ initialize_type_map(mapping)
420
488
  end
421
489
  end
422
- end
423
490
 
424
- def reload_type_map # :nodoc:
425
- type_map.clear
426
- initialize_type_map(type_map)
427
- end
491
+ def initialize_type_map(m = type_map)
492
+ register_class_with_limit m, %r(boolean)i, Type::Boolean
493
+ register_class_with_limit m, %r(char)i, Type::String
494
+ register_class_with_limit m, %r(binary)i, Type::Binary
495
+ register_class_with_limit m, %r(text)i, Type::Text
496
+ register_class_with_precision m, %r(date)i, Type::Date
497
+ register_class_with_precision m, %r(time)i, Type::Time
498
+ register_class_with_precision m, %r(datetime)i, Type::DateTime
499
+ register_class_with_limit m, %r(float)i, Type::Float
500
+ register_class_with_limit m, %r(int)i, Type::Integer
501
+
502
+ m.alias_type %r(blob)i, "binary"
503
+ m.alias_type %r(clob)i, "text"
504
+ m.alias_type %r(timestamp)i, "datetime"
505
+ m.alias_type %r(numeric)i, "decimal"
506
+ m.alias_type %r(number)i, "decimal"
507
+ m.alias_type %r(double)i, "float"
508
+
509
+ m.register_type %r(^json)i, Type::Json.new
510
+
511
+ m.register_type(%r(decimal)i) do |sql_type|
512
+ scale = extract_scale(sql_type)
513
+ precision = extract_precision(sql_type)
514
+
515
+ if scale == 0
516
+ # FIXME: Remove this class as well
517
+ Type::DecimalWithoutScale.new(precision: precision)
518
+ else
519
+ Type::Decimal.new(precision: precision, scale: scale)
520
+ end
521
+ end
522
+ end
428
523
 
429
- def register_class_with_limit(mapping, key, klass) # :nodoc:
430
- mapping.register_type(key) do |*args|
431
- limit = extract_limit(args.last)
432
- klass.new(limit: limit)
524
+ def reload_type_map
525
+ type_map.clear
526
+ initialize_type_map
433
527
  end
434
- end
435
528
 
436
- def extract_scale(sql_type) # :nodoc:
437
- case sql_type
529
+ def register_class_with_limit(mapping, key, klass)
530
+ mapping.register_type(key) do |*args|
531
+ limit = extract_limit(args.last)
532
+ klass.new(limit: limit)
533
+ end
534
+ end
535
+
536
+ def register_class_with_precision(mapping, key, klass)
537
+ mapping.register_type(key) do |*args|
538
+ precision = extract_precision(args.last)
539
+ klass.new(precision: precision)
540
+ end
541
+ end
542
+
543
+ def extract_scale(sql_type)
544
+ case sql_type
438
545
  when /\((\d+)\)/ then 0
439
546
  when /\((\d+)(,(\d+))\)/ then $3.to_i
547
+ end
440
548
  end
441
- end
442
549
 
443
- def extract_precision(sql_type) # :nodoc:
444
- $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
445
- end
550
+ def extract_precision(sql_type)
551
+ $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
552
+ end
446
553
 
447
- def extract_limit(sql_type) # :nodoc:
448
- $1.to_i if sql_type =~ /\((.*)\)/
449
- end
554
+ def extract_limit(sql_type)
555
+ $1.to_i if sql_type =~ /\((.*)\)/
556
+ end
450
557
 
451
- def translate_exception_class(e, sql)
452
- message = "#{e.class.name}: #{e.message}: #{sql}"
453
- @logger.error message if @logger
454
- exception = translate_exception(e, message)
455
- exception.set_backtrace e.backtrace
456
- exception
457
- end
558
+ def translate_exception_class(e, sql)
559
+ begin
560
+ message = "#{e.class.name}: #{e.message}: #{sql}"
561
+ rescue Encoding::CompatibilityError
562
+ message = "#{e.class.name}: #{e.message.force_encoding sql.encoding}: #{sql}"
563
+ end
458
564
 
459
- def log(sql, name = "SQL", binds = [], statement_name = nil)
460
- @instrumenter.instrument(
461
- "sql.active_record",
462
- :sql => sql,
463
- :name => name,
464
- :connection_id => object_id,
465
- :statement_name => statement_name,
466
- :binds => binds) { yield }
467
- rescue => e
468
- raise translate_exception_class(e, sql)
469
- end
565
+ exception = translate_exception(e, message)
566
+ exception.set_backtrace e.backtrace
567
+ exception
568
+ end
470
569
 
471
- def translate_exception(exception, message)
472
- # override in derived class
473
- ActiveRecord::StatementInvalid.new(message, exception)
474
- end
570
+ def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil) # :doc:
571
+ @instrumenter.instrument(
572
+ "sql.active_record",
573
+ sql: sql,
574
+ name: name,
575
+ binds: binds,
576
+ type_casted_binds: type_casted_binds,
577
+ statement_name: statement_name,
578
+ connection_id: object_id) do
579
+ begin
580
+ @lock.synchronize do
581
+ yield
582
+ end
583
+ rescue => e
584
+ raise translate_exception_class(e, sql)
585
+ end
586
+ end
587
+ end
475
588
 
476
- def without_prepared_statement?(binds)
477
- !prepared_statements || binds.empty?
478
- end
589
+ def translate_exception(exception, message)
590
+ # override in derived class
591
+ case exception
592
+ when RuntimeError
593
+ exception
594
+ else
595
+ ActiveRecord::StatementInvalid.new(message)
596
+ end
597
+ end
479
598
 
480
- def column_for(table_name, column_name) # :nodoc:
481
- column_name = column_name.to_s
482
- columns(table_name).detect { |c| c.name == column_name } ||
483
- raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
484
- end
599
+ def without_prepared_statement?(binds)
600
+ !prepared_statements || binds.empty?
601
+ end
602
+
603
+ def column_for(table_name, column_name)
604
+ column_name = column_name.to_s
605
+ columns(table_name).detect { |c| c.name == column_name } ||
606
+ raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
607
+ end
608
+
609
+ def collector
610
+ if prepared_statements
611
+ Arel::Collectors::Composite.new(
612
+ Arel::Collectors::SQLString.new,
613
+ Arel::Collectors::Bind.new,
614
+ )
615
+ else
616
+ Arel::Collectors::SubstituteBinds.new(
617
+ self,
618
+ Arel::Collectors::SQLString.new,
619
+ )
620
+ end
621
+ end
622
+
623
+ def arel_visitor
624
+ Arel::Visitors::ToSql.new(self)
625
+ end
485
626
  end
486
627
  end
487
628
  end