activerecord 4.2.11 → 5.2.4.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 +4 -4
  2. data/CHANGELOG.md +580 -1626
  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 +263 -249
  8. data/lib/active_record/association_relation.rb +11 -6
  9. data/lib/active_record/associations/alias_tracker.rb +29 -35
  10. data/lib/active_record/associations/association.rb +77 -43
  11. data/lib/active_record/associations/association_scope.rb +106 -133
  12. data/lib/active_record/associations/belongs_to_association.rb +52 -41
  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 +9 -22
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -35
  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 +139 -280
  22. data/lib/active_record/associations/collection_proxy.rb +231 -133
  23. data/lib/active_record/associations/foreign_association.rb +3 -1
  24. data/lib/active_record/associations/has_many_association.rb +34 -89
  25. data/lib/active_record/associations/has_many_through_association.rb +49 -76
  26. data/lib/active_record/associations/has_one_association.rb +38 -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 -87
  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 +133 -159
  32. data/lib/active_record/associations/preloader/association.rb +85 -120
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -74
  34. data/lib/active_record/associations/preloader.rb +81 -91
  35. data/lib/active_record/associations/singular_association.rb +27 -34
  36. data/lib/active_record/associations/through_association.rb +38 -18
  37. data/lib/active_record/associations.rb +1732 -1597
  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 +10 -8
  41. data/lib/active_record/attribute_methods/dirty.rb +94 -135
  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 +58 -36
  47. data/lib/active_record/attribute_methods/write.rb +30 -45
  48. data/lib/active_record/attribute_methods.rb +166 -109
  49. data/lib/active_record/attributes.rb +201 -82
  50. data/lib/active_record/autosave_association.rb +94 -36
  51. data/lib/active_record/base.rb +57 -44
  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 +24 -12
  55. data/lib/active_record/collection_cache_key.rb +53 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -290
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +237 -90
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +71 -21
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +118 -52
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +318 -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 +570 -228
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +138 -70
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +325 -202
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +542 -601
  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 +41 -180
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +45 -114
  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 -58
  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 +4 -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 -22
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -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 +5 -7
  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 -5
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +55 -53
  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 +462 -284
  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 +432 -323
  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 -308
  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 +178 -198
  129. data/lib/active_record/counter_cache.rb +79 -36
  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 +135 -88
  133. data/lib/active_record/errors.rb +179 -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 +10 -5
  137. data/lib/active_record/fixture_set/file.rb +35 -9
  138. data/lib/active_record/fixtures.rb +188 -132
  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 +21 -3
  144. data/lib/active_record/locale/en.yml +3 -2
  145. data/lib/active_record/locking/optimistic.rb +88 -96
  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 +581 -282
  152. data/lib/active_record/model_schema.rb +290 -111
  153. data/lib/active_record/nested_attributes.rb +264 -222
  154. data/lib/active_record/no_touching.rb +7 -1
  155. data/lib/active_record/null_relation.rb +24 -37
  156. data/lib/active_record/persistence.rb +347 -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 +94 -32
  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 +149 -156
  163. data/lib/active_record/readonly_attributes.rb +5 -4
  164. data/lib/active_record/reflection.rb +414 -267
  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 +256 -248
  168. data/lib/active_record/relation/delegation.rb +67 -60
  169. data/lib/active_record/relation/finder_methods.rb +288 -239
  170. data/lib/active_record/relation/from_clause.rb +26 -0
  171. data/lib/active_record/relation/merger.rb +86 -86
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -24
  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 +116 -119
  180. data/lib/active_record/relation/query_attribute.rb +45 -0
  181. data/lib/active_record/relation/query_methods.rb +448 -393
  182. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  183. data/lib/active_record/relation/spawn_methods.rb +11 -13
  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 -340
  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 -16
  193. data/lib/active_record/scoping/default.rb +102 -85
  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 +134 -96
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +56 -100
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +83 -41
  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 +199 -124
  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 -45
  212. data/lib/active_record/type/date_time.rb +4 -49
  213. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  214. data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
  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 +24 -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 +40 -41
  231. data/lib/active_record/validations.rb +38 -35
  232. data/lib/active_record/version.rb +3 -1
  233. data/lib/active_record.rb +34 -22
  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 -3
  238. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -1
  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/model/templates/{module.rb → module.rb.tt} +0 -0
  243. data/lib/rails/generators/active_record.rb +7 -5
  244. metadata +72 -50
  245. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  246. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  247. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  248. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  249. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  250. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  251. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  252. data/lib/active_record/attribute.rb +0 -163
  253. data/lib/active_record/attribute_set/builder.rb +0 -106
  254. data/lib/active_record/attribute_set.rb +0 -81
  255. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  256. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  257. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  258. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  259. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  260. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  261. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  262. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  263. data/lib/active_record/type/big_integer.rb +0 -13
  264. data/lib/active_record/type/binary.rb +0 -50
  265. data/lib/active_record/type/boolean.rb +0 -31
  266. data/lib/active_record/type/decimal.rb +0 -64
  267. data/lib/active_record/type/decorator.rb +0 -14
  268. data/lib/active_record/type/float.rb +0 -19
  269. data/lib/active_record/type/integer.rb +0 -59
  270. data/lib/active_record/type/mutable.rb +0 -16
  271. data/lib/active_record/type/numeric.rb +0 -36
  272. data/lib/active_record/type/string.rb +0 -40
  273. data/lib/active_record/type/time_value.rb +0 -38
  274. data/lib/active_record/type/value.rb +0 -110
@@ -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,76 +98,107 @@ 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
+ @quoted_column_names, @quoted_table_names = {}, {}
113
+ @visitor = arel_visitor
114
+ @lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
115
+
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
121
+ end
122
+ end
123
+
124
+ def migrations_paths # :nodoc:
125
+ @config[:migrations_paths] || Migrator.migrations_paths
126
+ end
127
+
128
+ def migration_context # :nodoc:
129
+ MigrationContext.new(migrations_paths)
112
130
  end
113
131
 
114
132
  class Version
115
133
  include Comparable
116
134
 
117
135
  def initialize(version_string)
118
- @version = version_string.split('.').map(&:to_i)
136
+ @version = version_string.split(".").map(&:to_i)
119
137
  end
120
138
 
121
139
  def <=>(version_string)
122
- @version <=> version_string.split('.').map(&:to_i)
140
+ @version <=> version_string.split(".").map(&:to_i)
123
141
  end
124
142
  end
125
143
 
126
- class BindCollector < Arel::Collectors::Bind
127
- def compile(bvs, conn)
128
- super(bvs.map { |bv| conn.quote(*bv.reverse) })
129
- end
144
+ def valid_type?(type) # :nodoc:
145
+ !native_database_types[type].nil?
130
146
  end
131
147
 
132
- class SQLString < Arel::Collectors::SQLString
133
- def compile(bvs, conn)
134
- super(bvs)
148
+ # this method must only be called while holding connection pool's mutex
149
+ def lease
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}."
157
+ end
158
+ raise ActiveRecordError, msg
135
159
  end
136
- end
137
160
 
138
- def collector
139
- if prepared_statements
140
- SQLString.new
141
- else
142
- BindCollector.new
143
- end
161
+ @owner = Thread.current
144
162
  end
145
163
 
146
- def valid_type?(type)
147
- true
164
+ def schema_cache=(cache)
165
+ cache.connection = self
166
+ @schema_cache = cache
148
167
  end
149
168
 
150
- def schema_creation
151
- SchemaCreation.new self
169
+ # this method must only be called while holding connection pool's mutex
170
+ def expire
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
152
183
  end
153
184
 
154
- def lease
155
- synchronize do
156
- unless in_use?
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
+
157
191
  @owner = Thread.current
158
192
  end
193
+ else
194
+ raise ActiveRecordError, "Cannot steal connection, it is not currently leased."
159
195
  end
160
196
  end
161
197
 
162
- def schema_cache=(cache)
163
- cache.connection = self
164
- @schema_cache = cache
165
- end
166
-
167
- def expire
168
- @owner = nil
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
169
202
  end
170
203
 
171
204
  def unprepared_statement
@@ -181,17 +214,6 @@ module ActiveRecord
181
214
  self.class::ADAPTER_NAME
182
215
  end
183
216
 
184
- # Does this adapter support migrations?
185
- def supports_migrations?
186
- false
187
- end
188
-
189
- # Can this adapter determine the primary key for tables not attached
190
- # to an Active Record class, such as join tables?
191
- def supports_primary_key?
192
- false
193
- end
194
-
195
217
  # Does this adapter support DDL rollbacks in transactions? That is, would
196
218
  # CREATE TABLE or ALTER TABLE get rolled back by a transaction?
197
219
  def supports_ddl_transactions?
@@ -207,6 +229,11 @@ module ActiveRecord
207
229
  false
208
230
  end
209
231
 
232
+ # Does this adapter support application-enforced advisory locking?
233
+ def supports_advisory_locks?
234
+ false
235
+ end
236
+
210
237
  # Should primary key values be selected from their corresponding
211
238
  # sequence before the insert statement? If true, next_sequence_value
212
239
  # is called before each insert to set the record's primary key.
@@ -224,6 +251,11 @@ module ActiveRecord
224
251
  false
225
252
  end
226
253
 
254
+ # Does this adapter support expression indices?
255
+ def supports_expression_index?
256
+ false
257
+ end
258
+
227
259
  # Does this adapter support explain?
228
260
  def supports_explain?
229
261
  false
@@ -250,11 +282,57 @@ module ActiveRecord
250
282
  false
251
283
  end
252
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
+
253
296
  # Does this adapter support views?
254
297
  def supports_views?
255
298
  false
256
299
  end
257
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
+
258
336
  # This is meant to be implemented by the adapters that support extensions
259
337
  def disable_extension(name)
260
338
  end
@@ -263,6 +341,20 @@ module ActiveRecord
263
341
  def enable_extension(name)
264
342
  end
265
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
+
266
358
  # A list of extensions, to be filled in by adapters that support them.
267
359
  def extensions
268
360
  []
@@ -273,14 +365,6 @@ module ActiveRecord
273
365
  {}
274
366
  end
275
367
 
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
282
- end
283
-
284
368
  # REFERENTIAL INTEGRITY ====================================
285
369
 
286
370
  # Override to turn off referential integrity while executing <tt>&block</tt>.
@@ -311,6 +395,19 @@ module ActiveRecord
311
395
  reset_transaction
312
396
  end
313
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
+
314
411
  # Reset the state of this connection, directing the DBMS to clear
315
412
  # transactions and other connection-related server-side state. Usually a
316
413
  # database-dependent operation.
@@ -334,15 +431,15 @@ module ActiveRecord
334
431
  end
335
432
 
336
433
  # Checks whether the connection to the database is still active (i.e. not stale).
337
- # 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
338
435
  # is no longer active, then this method will reconnect to the database.
339
- def verify!(*ignored)
436
+ def verify!
340
437
  reconnect! unless active?
341
438
  end
342
439
 
343
440
  # Provides access to the underlying database driver for this adapter. For
344
- # example, this method returns a Mysql object in case of MysqlAdapter,
345
- # 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.
346
443
  #
347
444
  # This is useful for when you need to call a proprietary method such as
348
445
  # PostgreSQL's lo_* methods.
@@ -350,156 +447,182 @@ module ActiveRecord
350
447
  @connection
351
448
  end
352
449
 
353
- def create_savepoint(name = nil)
354
- end
355
-
356
- def release_savepoint(name = nil)
357
- end
358
-
359
- def case_sensitive_modifier(node, table_attribute)
360
- node
361
- end
362
-
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)
450
+ def case_sensitive_comparison(table, attribute, column, value) # :nodoc:
451
+ table[attribute].eq(value)
367
452
  end
368
453
 
369
- def case_insensitive_comparison(table, attribute, column, value)
370
- 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
371
460
  end
372
461
 
373
- def current_savepoint_name
374
- current_transaction.savepoint_name
462
+ def can_perform_case_insensitive_comparison_for?(column)
463
+ true
375
464
  end
465
+ private :can_perform_case_insensitive_comparison_for?
376
466
 
377
467
  # Check the connection back in to the connection pool
378
468
  def close
379
469
  pool.checkin self
380
470
  end
381
471
 
382
- def type_map # :nodoc:
383
- @type_map ||= Type::TypeMap.new.tap do |mapping|
384
- initialize_type_map(mapping)
385
- end
472
+ def column_name_for_operation(operation, node) # :nodoc:
473
+ column_name_from_arel_node(node)
386
474
  end
387
475
 
388
- def new_column(name, default, cast_type, sql_type = nil, null = true)
389
- 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
390
478
  end
391
479
 
392
- def lookup_cast_type(sql_type) # :nodoc:
393
- type_map.lookup(sql_type)
480
+ def default_index_type?(index) # :nodoc:
481
+ index.using.nil?
394
482
  end
395
483
 
396
- def column_name_for_operation(operation, node) # :nodoc:
397
- visitor.accept(node, collector).value
398
- end
399
-
400
- protected
401
-
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)
484
+ private
485
+ def type_map
486
+ @type_map ||= Type::TypeMap.new.tap do |mapping|
487
+ initialize_type_map(mapping)
429
488
  end
430
489
  end
431
- end
432
490
 
433
- def reload_type_map # :nodoc:
434
- type_map.clear
435
- initialize_type_map(type_map)
436
- 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
437
523
 
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)
524
+ def reload_type_map
525
+ type_map.clear
526
+ initialize_type_map
442
527
  end
443
- end
444
528
 
445
- def extract_scale(sql_type) # :nodoc:
446
- 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
447
545
  when /\((\d+)\)/ then 0
448
546
  when /\((\d+)(,(\d+))\)/ then $3.to_i
547
+ end
449
548
  end
450
- end
451
549
 
452
- def extract_precision(sql_type) # :nodoc:
453
- $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
454
- end
550
+ def extract_precision(sql_type)
551
+ $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
552
+ end
455
553
 
456
- def extract_limit(sql_type) # :nodoc:
457
- case sql_type
458
- when /^bigint/i
459
- 8
460
- when /\((.*)\)/
461
- $1.to_i
554
+ def extract_limit(sql_type)
555
+ $1.to_i if sql_type =~ /\((.*)\)/
462
556
  end
463
- end
464
557
 
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}"
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
564
+
565
+ exception = translate_exception(e, message)
566
+ exception.set_backtrace e.backtrace
567
+ exception
470
568
  end
471
569
 
472
- exception = translate_exception(e, message)
473
- exception.set_backtrace e.backtrace
474
- exception
475
- 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
476
588
 
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
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
488
598
 
489
- def translate_exception(exception, message)
490
- # override in derived class
491
- ActiveRecord::StatementInvalid.new(message, exception)
492
- end
599
+ def without_prepared_statement?(binds)
600
+ !prepared_statements || binds.empty?
601
+ end
493
602
 
494
- def without_prepared_statement?(binds)
495
- !prepared_statements || binds.empty?
496
- end
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
497
608
 
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
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
503
626
  end
504
627
  end
505
628
  end