activerecord 4.2.6 → 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 (246) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1307 -1105
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -8
  5. data/examples/performance.rb +2 -3
  6. data/examples/simple.rb +0 -1
  7. data/lib/active_record/aggregations.rb +37 -23
  8. data/lib/active_record/association_relation.rb +3 -3
  9. data/lib/active_record/associations/alias_tracker.rb +19 -16
  10. data/lib/active_record/associations/association.rb +11 -9
  11. data/lib/active_record/associations/association_scope.rb +73 -102
  12. data/lib/active_record/associations/belongs_to_association.rb +21 -32
  13. data/lib/active_record/associations/builder/association.rb +28 -34
  14. data/lib/active_record/associations/builder/belongs_to.rb +43 -18
  15. data/lib/active_record/associations/builder/collection_association.rb +7 -19
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
  17. data/lib/active_record/associations/builder/has_many.rb +4 -4
  18. data/lib/active_record/associations/builder/has_one.rb +11 -6
  19. data/lib/active_record/associations/builder/singular_association.rb +3 -10
  20. data/lib/active_record/associations/collection_association.rb +50 -31
  21. data/lib/active_record/associations/collection_proxy.rb +69 -29
  22. data/lib/active_record/associations/foreign_association.rb +1 -1
  23. data/lib/active_record/associations/has_many_association.rb +20 -71
  24. data/lib/active_record/associations/has_many_through_association.rb +8 -47
  25. data/lib/active_record/associations/has_one_association.rb +12 -5
  26. data/lib/active_record/associations/join_dependency/join_association.rb +20 -8
  27. data/lib/active_record/associations/join_dependency.rb +29 -19
  28. data/lib/active_record/associations/preloader/association.rb +46 -52
  29. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  30. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  31. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  32. data/lib/active_record/associations/preloader/through_association.rb +27 -14
  33. data/lib/active_record/associations/preloader.rb +14 -4
  34. data/lib/active_record/associations/singular_association.rb +7 -1
  35. data/lib/active_record/associations/through_association.rb +11 -3
  36. data/lib/active_record/associations.rb +317 -209
  37. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  38. data/lib/active_record/attribute.rb +68 -18
  39. data/lib/active_record/attribute_assignment.rb +20 -141
  40. data/lib/active_record/attribute_decorators.rb +6 -5
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  42. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  43. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  44. data/lib/active_record/attribute_methods/query.rb +2 -2
  45. data/lib/active_record/attribute_methods/read.rb +31 -59
  46. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
  48. data/lib/active_record/attribute_methods/write.rb +14 -38
  49. data/lib/active_record/attribute_methods.rb +70 -45
  50. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  51. data/lib/active_record/attribute_set/builder.rb +6 -4
  52. data/lib/active_record/attribute_set.rb +30 -3
  53. data/lib/active_record/attributes.rb +199 -80
  54. data/lib/active_record/autosave_association.rb +49 -16
  55. data/lib/active_record/base.rb +32 -23
  56. data/lib/active_record/callbacks.rb +39 -43
  57. data/lib/active_record/coders/json.rb +1 -1
  58. data/lib/active_record/coders/yaml_column.rb +20 -8
  59. data/lib/active_record/collection_cache_key.rb +40 -0
  60. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
  61. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  62. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
  63. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
  64. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -9
  65. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  66. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  67. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
  68. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
  69. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +378 -140
  70. data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
  71. data/lib/active_record/connection_adapters/abstract_adapter.rb +153 -59
  72. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -362
  73. data/lib/active_record/connection_adapters/column.rb +28 -43
  74. data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
  75. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  76. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  77. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  78. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  79. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  80. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  81. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  82. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  83. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  84. data/lib/active_record/connection_adapters/mysql2_adapter.rb +25 -176
  85. data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
  86. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
  87. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -56
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  98. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  100. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  101. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  102. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  105. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
  106. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  107. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  108. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  109. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
  110. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  111. data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
  112. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  113. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  114. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  115. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  116. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  117. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +148 -203
  118. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  119. data/lib/active_record/connection_handling.rb +37 -14
  120. data/lib/active_record/core.rb +89 -107
  121. data/lib/active_record/counter_cache.rb +13 -24
  122. data/lib/active_record/dynamic_matchers.rb +1 -20
  123. data/lib/active_record/enum.rb +113 -76
  124. data/lib/active_record/errors.rb +87 -48
  125. data/lib/active_record/explain_registry.rb +1 -1
  126. data/lib/active_record/explain_subscriber.rb +1 -1
  127. data/lib/active_record/fixture_set/file.rb +26 -5
  128. data/lib/active_record/fixtures.rb +76 -40
  129. data/lib/active_record/gem_version.rb +3 -3
  130. data/lib/active_record/inheritance.rb +32 -40
  131. data/lib/active_record/integration.rb +4 -4
  132. data/lib/active_record/internal_metadata.rb +56 -0
  133. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  134. data/lib/active_record/locale/en.yml +3 -2
  135. data/lib/active_record/locking/optimistic.rb +15 -15
  136. data/lib/active_record/locking/pessimistic.rb +1 -1
  137. data/lib/active_record/log_subscriber.rb +43 -21
  138. data/lib/active_record/migration/command_recorder.rb +59 -18
  139. data/lib/active_record/migration/compatibility.rb +126 -0
  140. data/lib/active_record/migration.rb +364 -109
  141. data/lib/active_record/model_schema.rb +128 -38
  142. data/lib/active_record/nested_attributes.rb +58 -29
  143. data/lib/active_record/null_relation.rb +16 -8
  144. data/lib/active_record/persistence.rb +121 -80
  145. data/lib/active_record/query_cache.rb +15 -18
  146. data/lib/active_record/querying.rb +10 -9
  147. data/lib/active_record/railtie.rb +27 -18
  148. data/lib/active_record/railties/controller_runtime.rb +1 -1
  149. data/lib/active_record/railties/databases.rake +58 -45
  150. data/lib/active_record/readonly_attributes.rb +1 -1
  151. data/lib/active_record/reflection.rb +282 -115
  152. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  153. data/lib/active_record/relation/batches.rb +139 -34
  154. data/lib/active_record/relation/calculations.rb +80 -102
  155. data/lib/active_record/relation/delegation.rb +7 -20
  156. data/lib/active_record/relation/finder_methods.rb +163 -81
  157. data/lib/active_record/relation/from_clause.rb +32 -0
  158. data/lib/active_record/relation/merger.rb +16 -42
  159. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -15
  160. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  161. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  162. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  163. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  164. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  165. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  166. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  167. data/lib/active_record/relation/predicate_builder.rb +120 -107
  168. data/lib/active_record/relation/query_attribute.rb +19 -0
  169. data/lib/active_record/relation/query_methods.rb +308 -244
  170. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  171. data/lib/active_record/relation/spawn_methods.rb +4 -7
  172. data/lib/active_record/relation/where_clause.rb +174 -0
  173. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  174. data/lib/active_record/relation.rb +176 -116
  175. data/lib/active_record/result.rb +4 -3
  176. data/lib/active_record/runtime_registry.rb +1 -1
  177. data/lib/active_record/sanitization.rb +95 -66
  178. data/lib/active_record/schema.rb +26 -22
  179. data/lib/active_record/schema_dumper.rb +62 -38
  180. data/lib/active_record/schema_migration.rb +11 -17
  181. data/lib/active_record/scoping/default.rb +23 -9
  182. data/lib/active_record/scoping/named.rb +49 -28
  183. data/lib/active_record/scoping.rb +32 -15
  184. data/lib/active_record/secure_token.rb +38 -0
  185. data/lib/active_record/serialization.rb +2 -4
  186. data/lib/active_record/statement_cache.rb +16 -14
  187. data/lib/active_record/store.rb +8 -3
  188. data/lib/active_record/suppressor.rb +58 -0
  189. data/lib/active_record/table_metadata.rb +68 -0
  190. data/lib/active_record/tasks/database_tasks.rb +58 -41
  191. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -20
  192. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  193. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  194. data/lib/active_record/timestamp.rb +20 -9
  195. data/lib/active_record/touch_later.rb +58 -0
  196. data/lib/active_record/transactions.rb +138 -56
  197. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  198. data/lib/active_record/type/date.rb +2 -41
  199. data/lib/active_record/type/date_time.rb +2 -49
  200. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  201. data/lib/active_record/type/internal/timezone.rb +15 -0
  202. data/lib/active_record/type/serialized.rb +15 -14
  203. data/lib/active_record/type/time.rb +10 -16
  204. data/lib/active_record/type/type_map.rb +4 -4
  205. data/lib/active_record/type.rb +66 -17
  206. data/lib/active_record/type_caster/connection.rb +29 -0
  207. data/lib/active_record/type_caster/map.rb +19 -0
  208. data/lib/active_record/type_caster.rb +7 -0
  209. data/lib/active_record/validations/absence.rb +23 -0
  210. data/lib/active_record/validations/associated.rb +10 -3
  211. data/lib/active_record/validations/length.rb +24 -0
  212. data/lib/active_record/validations/presence.rb +11 -12
  213. data/lib/active_record/validations/uniqueness.rb +30 -29
  214. data/lib/active_record/validations.rb +33 -32
  215. data/lib/active_record.rb +7 -2
  216. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  217. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  218. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
  219. data/lib/rails/generators/active_record/migration.rb +7 -0
  220. data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
  221. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  222. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  223. metadata +58 -34
  224. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  225. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  226. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  227. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  228. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  229. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  230. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  231. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  232. data/lib/active_record/type/big_integer.rb +0 -13
  233. data/lib/active_record/type/binary.rb +0 -50
  234. data/lib/active_record/type/boolean.rb +0 -31
  235. data/lib/active_record/type/decimal.rb +0 -50
  236. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  237. data/lib/active_record/type/decorator.rb +0 -14
  238. data/lib/active_record/type/float.rb +0 -19
  239. data/lib/active_record/type/integer.rb +0 -59
  240. data/lib/active_record/type/mutable.rb +0 -16
  241. data/lib/active_record/type/numeric.rb +0 -36
  242. data/lib/active_record/type/string.rb +0 -40
  243. data/lib/active_record/type/text.rb +0 -11
  244. data/lib/active_record/type/time_value.rb +0 -38
  245. data/lib/active_record/type/unsigned_integer.rb +0 -15
  246. data/lib/active_record/type/value.rb +0 -105
@@ -1,13 +1,10 @@
1
1
  module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  class TransactionState
4
- attr_reader :parent
5
-
6
4
  VALID_STATES = Set.new([:committed, :rolledback, nil])
7
5
 
8
6
  def initialize(state = nil)
9
7
  @state = state
10
- @parent = nil
11
8
  end
12
9
 
13
10
  def finalized?
@@ -27,7 +24,7 @@ module ActiveRecord
27
24
  end
28
25
 
29
26
  def set_state(state)
30
- if !VALID_STATES.include?(state)
27
+ unless VALID_STATES.include?(state)
31
28
  raise ArgumentError, "Invalid transaction state: #{state}"
32
29
  end
33
30
  @state = state
@@ -36,6 +33,7 @@ module ActiveRecord
36
33
 
37
34
  class NullTransaction #:nodoc:
38
35
  def initialize; end
36
+ def state; end
39
37
  def closed?; true; end
40
38
  def open?; false; end
41
39
  def joinable?; false; end
@@ -47,11 +45,12 @@ module ActiveRecord
47
45
  attr_reader :connection, :state, :records, :savepoint_name
48
46
  attr_writer :joinable
49
47
 
50
- def initialize(connection, options)
48
+ def initialize(connection, options, run_commit_callbacks: false)
51
49
  @connection = connection
52
50
  @state = TransactionState.new
53
51
  @records = []
54
52
  @joinable = options.fetch(:joinable, true)
53
+ @run_commit_callbacks = run_commit_callbacks
55
54
  end
56
55
 
57
56
  def add_record(record)
@@ -65,16 +64,11 @@ module ActiveRecord
65
64
  def rollback_records
66
65
  ite = records.uniq
67
66
  while record = ite.shift
68
- begin
69
- record.rolledback! full_rollback?
70
- rescue => e
71
- raise if ActiveRecord::Base.raise_in_transactional_callbacks
72
- record.logger.error(e) if record.respond_to?(:logger) && record.logger
73
- end
67
+ record.rolledback!(force_restore_state: full_rollback?)
74
68
  end
75
69
  ensure
76
70
  ite.each do |i|
77
- i.rolledback!(full_rollback?, false)
71
+ i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false)
78
72
  end
79
73
  end
80
74
 
@@ -82,20 +76,22 @@ module ActiveRecord
82
76
  @state.set_state(:committed)
83
77
  end
84
78
 
79
+ def before_commit_records
80
+ records.uniq.each(&:before_committed!) if @run_commit_callbacks
81
+ end
82
+
85
83
  def commit_records
86
84
  ite = records.uniq
87
85
  while record = ite.shift
88
- begin
86
+ if @run_commit_callbacks
89
87
  record.committed!
90
- rescue => e
91
- raise if ActiveRecord::Base.raise_in_transactional_callbacks
92
- record.logger.error(e) if record.respond_to?(:logger) && record.logger
88
+ else
89
+ # if not running callbacks, only adds the record to the parent transaction
90
+ record.add_to_transaction
93
91
  end
94
92
  end
95
93
  ensure
96
- ite.each do |i|
97
- i.committed!(false)
98
- end
94
+ ite.each { |i| i.committed!(should_run_callbacks: false) }
99
95
  end
100
96
 
101
97
  def full_rollback?; true; end
@@ -106,8 +102,8 @@ module ActiveRecord
106
102
 
107
103
  class SavepointTransaction < Transaction
108
104
 
109
- def initialize(connection, savepoint_name, options)
110
- super(connection, options)
105
+ def initialize(connection, savepoint_name, options, *args)
106
+ super(connection, options, *args)
111
107
  if options[:isolation]
112
108
  raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
113
109
  end
@@ -117,14 +113,11 @@ module ActiveRecord
117
113
  def rollback
118
114
  connection.rollback_to_savepoint(savepoint_name)
119
115
  super
120
- rollback_records
121
116
  end
122
117
 
123
118
  def commit
124
119
  connection.release_savepoint(savepoint_name)
125
120
  super
126
- parent = connection.transaction_manager.current_transaction
127
- records.each { |r| parent.add_record(r) }
128
121
  end
129
122
 
130
123
  def full_rollback?; false; end
@@ -132,7 +125,7 @@ module ActiveRecord
132
125
 
133
126
  class RealTransaction < Transaction
134
127
 
135
- def initialize(connection, options)
128
+ def initialize(connection, options, *args)
136
129
  super
137
130
  if options[:isolation]
138
131
  connection.begin_isolated_db_transaction(options[:isolation])
@@ -144,13 +137,11 @@ module ActiveRecord
144
137
  def rollback
145
138
  connection.rollback_db_transaction
146
139
  super
147
- rollback_records
148
140
  end
149
141
 
150
142
  def commit
151
143
  connection.commit_db_transaction
152
144
  super
153
- commit_records
154
145
  end
155
146
  end
156
147
 
@@ -161,29 +152,46 @@ module ActiveRecord
161
152
  end
162
153
 
163
154
  def begin_transaction(options = {})
155
+ run_commit_callbacks = !current_transaction.joinable?
164
156
  transaction =
165
157
  if @stack.empty?
166
- RealTransaction.new(@connection, options)
158
+ RealTransaction.new(@connection, options, run_commit_callbacks: run_commit_callbacks)
167
159
  else
168
- SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options)
160
+ SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options,
161
+ run_commit_callbacks: run_commit_callbacks)
169
162
  end
163
+
170
164
  @stack.push(transaction)
171
165
  transaction
172
166
  end
173
167
 
174
168
  def commit_transaction
175
- @stack.pop.commit
169
+ transaction = @stack.last
170
+
171
+ begin
172
+ transaction.before_commit_records
173
+ ensure
174
+ @stack.pop
175
+ end
176
+
177
+ transaction.commit
178
+ transaction.commit_records
176
179
  end
177
180
 
178
- def rollback_transaction
179
- @stack.pop.rollback
181
+ def rollback_transaction(transaction = nil)
182
+ transaction ||= @stack.pop
183
+ transaction.rollback
184
+ transaction.rollback_records
180
185
  end
181
186
 
182
187
  def within_new_transaction(options = {})
183
188
  transaction = begin_transaction options
184
189
  yield
185
190
  rescue Exception => error
186
- rollback_transaction if transaction
191
+ if transaction
192
+ rollback_transaction
193
+ after_failure_actions(transaction, error)
194
+ end
187
195
  raise
188
196
  ensure
189
197
  unless error
@@ -193,7 +201,7 @@ module ActiveRecord
193
201
  begin
194
202
  commit_transaction
195
203
  rescue Exception
196
- transaction.rollback unless transaction.state.completed?
204
+ rollback_transaction(transaction) unless transaction.state.completed?
197
205
  raise
198
206
  end
199
207
  end
@@ -209,7 +217,16 @@ module ActiveRecord
209
217
  end
210
218
 
211
219
  private
220
+
212
221
  NULL_TRANSACTION = NullTransaction.new
222
+
223
+ # Deallocate invalidated prepared statements outside of the transaction
224
+ def after_failure_actions(transaction, error)
225
+ return unless transaction.is_a?(RealTransaction)
226
+ return unless error.is_a?(ActiveRecord::PreparedStatementCacheExpired)
227
+ @connection.clear_cache!
228
+ end
229
+
213
230
  end
214
231
  end
215
232
  end
@@ -1,12 +1,9 @@
1
- require 'date'
2
- require 'bigdecimal'
3
- require 'bigdecimal/util'
4
1
  require 'active_record/type'
5
- require 'active_support/core_ext/benchmark'
2
+ require 'active_record/connection_adapters/determine_if_preparable_visitor'
6
3
  require 'active_record/connection_adapters/schema_cache'
4
+ require 'active_record/connection_adapters/sql_type_metadata'
7
5
  require 'active_record/connection_adapters/abstract/schema_dumper'
8
6
  require 'active_record/connection_adapters/abstract/schema_creation'
9
- require 'monitor'
10
7
  require 'arel/collectors/bind'
11
8
  require 'arel/collectors/sql_string'
12
9
 
@@ -21,15 +18,15 @@ module ActiveRecord
21
18
  autoload :IndexDefinition
22
19
  autoload :ColumnDefinition
23
20
  autoload :ChangeColumnDefinition
21
+ autoload :ForeignKeyDefinition
24
22
  autoload :TableDefinition
25
23
  autoload :Table
26
24
  autoload :AlterTable
27
- autoload :TimestampDefaultDeprecation
25
+ autoload :ReferenceDefinition
28
26
  end
29
27
 
30
28
  autoload_at 'active_record/connection_adapters/abstract/connection_pool' do
31
29
  autoload :ConnectionHandler
32
- autoload :ConnectionManagement
33
30
  end
34
31
 
35
32
  autoload_under 'abstract' do
@@ -54,23 +51,23 @@ module ActiveRecord
54
51
  # related classes form the abstraction layer which makes this possible.
55
52
  # An AbstractAdapter represents a connection to a database, and provides an
56
53
  # 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.
54
+ # a connection, escaping values, building the right SQL fragments for +:offset+
55
+ # and +:limit+ options, etc.
59
56
  #
60
57
  # All the concrete database adapters follow the interface laid down in this class.
61
- # ActiveRecord::Base.connection returns an AbstractAdapter object, which
58
+ # {ActiveRecord::Base.connection}[rdoc-ref:ConnectionHandling#connection] returns an AbstractAdapter object, which
62
59
  # you can use.
63
60
  #
64
61
  # Most of the methods in the adapter are useful during migrations. Most
65
- # notably, the instance methods provided by SchemaStatement are very useful.
62
+ # notably, the instance methods provided by SchemaStatements are very useful.
66
63
  class AbstractAdapter
67
64
  ADAPTER_NAME = 'Abstract'.freeze
68
65
  include Quoting, DatabaseStatements, SchemaStatements
69
66
  include DatabaseLimits
70
67
  include QueryCache
71
68
  include ActiveSupport::Callbacks
72
- include MonitorMixin
73
69
  include ColumnDumper
70
+ include Savepoints
74
71
 
75
72
  SIMPLE_INT = /\A\d+\z/
76
73
 
@@ -98,22 +95,43 @@ module ActiveRecord
98
95
 
99
96
  attr_reader :prepared_statements
100
97
 
101
- def initialize(connection, logger = nil, pool = nil) #:nodoc:
98
+ def initialize(connection, logger = nil, config = {}) # :nodoc:
102
99
  super()
103
100
 
104
101
  @connection = connection
105
102
  @owner = nil
106
103
  @instrumenter = ActiveSupport::Notifications.instrumenter
107
104
  @logger = logger
108
- @pool = pool
105
+ @config = config
106
+ @pool = nil
109
107
  @schema_cache = SchemaCache.new self
110
- @visitor = nil
111
- @prepared_statements = false
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
117
+ end
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
112
129
  end
113
130
 
114
131
  class BindCollector < Arel::Collectors::Bind
115
132
  def compile(bvs, conn)
116
- super(bvs.map { |bv| conn.quote(*bv.reverse) })
133
+ casted_binds = conn.prepare_binds_for_database(bvs)
134
+ super(casted_binds.map { |value| conn.quote(value) })
117
135
  end
118
136
  end
119
137
 
@@ -131,20 +149,32 @@ module ActiveRecord
131
149
  end
132
150
  end
133
151
 
152
+ def arel_visitor # :nodoc:
153
+ Arel::Visitors::ToSql.new(self)
154
+ end
155
+
134
156
  def valid_type?(type)
135
- true
157
+ false
136
158
  end
137
159
 
138
160
  def schema_creation
139
161
  SchemaCreation.new self
140
162
  end
141
163
 
164
+ # this method must only be called while holding connection pool's mutex
142
165
  def lease
143
- synchronize do
144
- unless in_use?
145
- @owner = Thread.current
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}."
146
173
  end
174
+ raise ActiveRecordError, msg
147
175
  end
176
+
177
+ @owner = Thread.current
148
178
  end
149
179
 
150
180
  def schema_cache=(cache)
@@ -152,6 +182,7 @@ module ActiveRecord
152
182
  @schema_cache = cache
153
183
  end
154
184
 
185
+ # this method must only be called while holding connection pool's mutex
155
186
  def expire
156
187
  @owner = nil
157
188
  end
@@ -195,6 +226,11 @@ module ActiveRecord
195
226
  false
196
227
  end
197
228
 
229
+ # Does this adapter support application-enforced advisory locking?
230
+ def supports_advisory_locks?
231
+ false
232
+ end
233
+
198
234
  # Should primary key values be selected from their corresponding
199
235
  # sequence before the insert statement? If true, next_sequence_value
200
236
  # is called before each insert to set the record's primary key.
@@ -212,6 +248,11 @@ module ActiveRecord
212
248
  false
213
249
  end
214
250
 
251
+ # Does this adapter support expression indices?
252
+ def supports_expression_index?
253
+ false
254
+ end
255
+
215
256
  # Does this adapter support explain?
216
257
  def supports_explain?
217
258
  false
@@ -243,6 +284,31 @@ module ActiveRecord
243
284
  false
244
285
  end
245
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
+
246
312
  # This is meant to be implemented by the adapters that support extensions
247
313
  def disable_extension(name)
248
314
  end
@@ -251,6 +317,20 @@ module ActiveRecord
251
317
  def enable_extension(name)
252
318
  end
253
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
+
254
334
  # A list of extensions, to be filled in by adapters that support them.
255
335
  def extensions
256
336
  []
@@ -261,14 +341,6 @@ module ActiveRecord
261
341
  {}
262
342
  end
263
343
 
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
344
  # REFERENTIAL INTEGRITY ====================================
273
345
 
274
346
  # Override to turn off referential integrity while executing <tt>&block</tt>.
@@ -322,14 +394,14 @@ module ActiveRecord
322
394
  end
323
395
 
324
396
  # 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
397
+ # This is done under the hood by calling #active?. If the connection
326
398
  # is no longer active, then this method will reconnect to the database.
327
399
  def verify!(*ignored)
328
400
  reconnect! unless active?
329
401
  end
330
402
 
331
403
  # Provides access to the underlying database driver for this adapter. For
332
- # example, this method returns a Mysql object in case of MysqlAdapter,
404
+ # example, this method returns a Mysql2::Client object in case of Mysql2Adapter,
333
405
  # and a PGconn object in case of PostgreSQLAdapter.
334
406
  #
335
407
  # This is useful for when you need to call a proprietary method such as
@@ -338,29 +410,26 @@ module ActiveRecord
338
410
  @connection
339
411
  end
340
412
 
341
- def create_savepoint(name = nil)
342
- end
343
-
344
- def release_savepoint(name = nil)
345
- end
346
-
347
- def case_sensitive_modifier(node, table_attribute)
348
- node
349
- end
350
-
351
413
  def case_sensitive_comparison(table, attribute, column, value)
352
- table_attr = table[attribute]
353
- value = case_sensitive_modifier(value, table_attr) unless value.nil?
354
- table_attr.eq(value)
414
+ if value.nil?
415
+ table[attribute].eq(value)
416
+ else
417
+ table[attribute].eq(Arel::Nodes::BindParam.new)
418
+ end
355
419
  end
356
420
 
357
421
  def case_insensitive_comparison(table, attribute, column, value)
358
- table[attribute].lower.eq(table.lower(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
359
427
  end
360
428
 
361
- def current_savepoint_name
362
- current_transaction.savepoint_name
429
+ def can_perform_case_insensitive_comparison_for?(column)
430
+ true
363
431
  end
432
+ private :can_perform_case_insensitive_comparison_for?
364
433
 
365
434
  # Check the connection back in to the connection pool
366
435
  def close
@@ -373,8 +442,8 @@ module ActiveRecord
373
442
  end
374
443
  end
375
444
 
376
- def new_column(name, default, cast_type, sql_type = nil, null = true)
377
- Column.new(name, default, cast_type, sql_type, null)
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)
378
447
  end
379
448
 
380
449
  def lookup_cast_type(sql_type) # :nodoc:
@@ -385,18 +454,36 @@ module ActiveRecord
385
454
  visitor.accept(node, collector).value
386
455
  end
387
456
 
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
473
+ end
474
+
388
475
  protected
389
476
 
390
477
  def initialize_type_map(m) # :nodoc:
391
- register_class_with_limit m, %r(boolean)i, Type::Boolean
392
- register_class_with_limit m, %r(char)i, Type::String
393
- register_class_with_limit m, %r(binary)i, Type::Binary
394
- register_class_with_limit m, %r(text)i, Type::Text
395
- register_class_with_limit m, %r(date)i, Type::Date
396
- register_class_with_limit m, %r(time)i, Type::Time
397
- register_class_with_limit m, %r(datetime)i, Type::DateTime
398
- register_class_with_limit m, %r(float)i, Type::Float
399
- register_class_with_limit m, %r(int)i, Type::Integer
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
400
487
 
401
488
  m.alias_type %r(blob)i, 'binary'
402
489
  m.alias_type %r(clob)i, 'text'
@@ -430,6 +517,13 @@ module ActiveRecord
430
517
  end
431
518
  end
432
519
 
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
525
+ end
526
+
433
527
  def extract_scale(sql_type) # :nodoc:
434
528
  case sql_type
435
529
  when /\((\d+)\)/ then 0
@@ -476,7 +570,7 @@ module ActiveRecord
476
570
 
477
571
  def translate_exception(exception, message)
478
572
  # override in derived class
479
- ActiveRecord::StatementInvalid.new(message, exception)
573
+ ActiveRecord::StatementInvalid.new(message)
480
574
  end
481
575
 
482
576
  def without_prepared_statement?(binds)