activerecord 4.2.11.1 → 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 +5 -5
  2. data/CHANGELOG.md +1282 -1195
  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.rb +8 -4
  8. data/lib/active_record/aggregations.rb +35 -24
  9. data/lib/active_record/association_relation.rb +3 -3
  10. data/lib/active_record/associations.rb +317 -209
  11. data/lib/active_record/associations/alias_tracker.rb +19 -16
  12. data/lib/active_record/associations/association.rb +11 -9
  13. data/lib/active_record/associations/association_scope.rb +73 -102
  14. data/lib/active_record/associations/belongs_to_association.rb +21 -32
  15. data/lib/active_record/associations/builder/association.rb +28 -34
  16. data/lib/active_record/associations/builder/belongs_to.rb +43 -18
  17. data/lib/active_record/associations/builder/collection_association.rb +7 -19
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
  19. data/lib/active_record/associations/builder/has_many.rb +4 -4
  20. data/lib/active_record/associations/builder/has_one.rb +11 -6
  21. data/lib/active_record/associations/builder/singular_association.rb +3 -10
  22. data/lib/active_record/associations/collection_association.rb +49 -41
  23. data/lib/active_record/associations/collection_proxy.rb +67 -27
  24. data/lib/active_record/associations/foreign_association.rb +1 -1
  25. data/lib/active_record/associations/has_many_association.rb +20 -71
  26. data/lib/active_record/associations/has_many_through_association.rb +8 -47
  27. data/lib/active_record/associations/has_one_association.rb +12 -5
  28. data/lib/active_record/associations/join_dependency.rb +29 -19
  29. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  30. data/lib/active_record/associations/preloader.rb +14 -4
  31. data/lib/active_record/associations/preloader/association.rb +46 -52
  32. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  33. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  34. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  35. data/lib/active_record/associations/preloader/through_association.rb +27 -14
  36. data/lib/active_record/associations/singular_association.rb +7 -1
  37. data/lib/active_record/associations/through_association.rb +11 -3
  38. data/lib/active_record/attribute.rb +68 -18
  39. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  40. data/lib/active_record/attribute_assignment.rb +19 -140
  41. data/lib/active_record/attribute_decorators.rb +6 -5
  42. data/lib/active_record/attribute_methods.rb +76 -47
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  44. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  45. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  46. data/lib/active_record/attribute_methods/query.rb +2 -2
  47. data/lib/active_record/attribute_methods/read.rb +31 -59
  48. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
  50. data/lib/active_record/attribute_methods/write.rb +13 -37
  51. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  52. data/lib/active_record/attribute_set.rb +30 -3
  53. data/lib/active_record/attribute_set/builder.rb +6 -4
  54. data/lib/active_record/attributes.rb +199 -81
  55. data/lib/active_record/autosave_association.rb +49 -16
  56. data/lib/active_record/base.rb +32 -23
  57. data/lib/active_record/callbacks.rb +39 -43
  58. data/lib/active_record/coders/json.rb +1 -1
  59. data/lib/active_record/coders/yaml_column.rb +20 -8
  60. data/lib/active_record/collection_cache_key.rb +40 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
  62. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  63. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
  64. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
  65. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -10
  66. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  67. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  68. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
  69. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
  70. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +380 -141
  71. data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
  72. data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
  73. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
  74. data/lib/active_record/connection_adapters/column.rb +28 -43
  75. data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
  76. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  77. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  78. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  79. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  80. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  81. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  82. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  83. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  84. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  85. data/lib/active_record/connection_adapters/mysql2_adapter.rb +29 -166
  86. data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
  87. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
  88. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -57
  91. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  96. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  100. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  106. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
  107. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  108. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  109. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
  111. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  112. data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
  113. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  114. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  115. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  116. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  117. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +149 -192
  119. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  120. data/lib/active_record/connection_handling.rb +37 -14
  121. data/lib/active_record/core.rb +89 -107
  122. data/lib/active_record/counter_cache.rb +13 -24
  123. data/lib/active_record/dynamic_matchers.rb +1 -20
  124. data/lib/active_record/enum.rb +113 -76
  125. data/lib/active_record/errors.rb +87 -48
  126. data/lib/active_record/explain_registry.rb +1 -1
  127. data/lib/active_record/explain_subscriber.rb +1 -1
  128. data/lib/active_record/fixture_set/file.rb +26 -5
  129. data/lib/active_record/fixtures.rb +76 -40
  130. data/lib/active_record/gem_version.rb +4 -4
  131. data/lib/active_record/inheritance.rb +32 -40
  132. data/lib/active_record/integration.rb +4 -4
  133. data/lib/active_record/internal_metadata.rb +56 -0
  134. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  135. data/lib/active_record/locale/en.yml +3 -2
  136. data/lib/active_record/locking/optimistic.rb +15 -15
  137. data/lib/active_record/locking/pessimistic.rb +1 -1
  138. data/lib/active_record/log_subscriber.rb +43 -21
  139. data/lib/active_record/migration.rb +363 -133
  140. data/lib/active_record/migration/command_recorder.rb +59 -18
  141. data/lib/active_record/migration/compatibility.rb +126 -0
  142. data/lib/active_record/model_schema.rb +129 -41
  143. data/lib/active_record/nested_attributes.rb +58 -29
  144. data/lib/active_record/null_relation.rb +16 -8
  145. data/lib/active_record/persistence.rb +121 -80
  146. data/lib/active_record/query_cache.rb +15 -18
  147. data/lib/active_record/querying.rb +10 -9
  148. data/lib/active_record/railtie.rb +23 -16
  149. data/lib/active_record/railties/controller_runtime.rb +1 -1
  150. data/lib/active_record/railties/databases.rake +69 -46
  151. data/lib/active_record/readonly_attributes.rb +1 -1
  152. data/lib/active_record/reflection.rb +282 -115
  153. data/lib/active_record/relation.rb +176 -116
  154. data/lib/active_record/relation/batches.rb +139 -34
  155. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  156. data/lib/active_record/relation/calculations.rb +79 -108
  157. data/lib/active_record/relation/delegation.rb +7 -20
  158. data/lib/active_record/relation/finder_methods.rb +163 -81
  159. data/lib/active_record/relation/from_clause.rb +32 -0
  160. data/lib/active_record/relation/merger.rb +16 -42
  161. data/lib/active_record/relation/predicate_builder.rb +120 -107
  162. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  163. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  164. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  165. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  166. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  167. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  168. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  169. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  170. data/lib/active_record/relation/query_attribute.rb +19 -0
  171. data/lib/active_record/relation/query_methods.rb +308 -244
  172. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  173. data/lib/active_record/relation/spawn_methods.rb +4 -7
  174. data/lib/active_record/relation/where_clause.rb +174 -0
  175. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  176. data/lib/active_record/result.rb +4 -3
  177. data/lib/active_record/runtime_registry.rb +1 -1
  178. data/lib/active_record/sanitization.rb +95 -66
  179. data/lib/active_record/schema.rb +26 -22
  180. data/lib/active_record/schema_dumper.rb +62 -38
  181. data/lib/active_record/schema_migration.rb +11 -14
  182. data/lib/active_record/scoping.rb +32 -15
  183. data/lib/active_record/scoping/default.rb +23 -9
  184. data/lib/active_record/scoping/named.rb +49 -28
  185. data/lib/active_record/secure_token.rb +38 -0
  186. data/lib/active_record/serialization.rb +2 -4
  187. data/lib/active_record/statement_cache.rb +16 -14
  188. data/lib/active_record/store.rb +8 -3
  189. data/lib/active_record/suppressor.rb +58 -0
  190. data/lib/active_record/table_metadata.rb +68 -0
  191. data/lib/active_record/tasks/database_tasks.rb +57 -43
  192. data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
  193. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  194. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  195. data/lib/active_record/timestamp.rb +20 -9
  196. data/lib/active_record/touch_later.rb +58 -0
  197. data/lib/active_record/transactions.rb +138 -56
  198. data/lib/active_record/type.rb +66 -17
  199. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  200. data/lib/active_record/type/date.rb +2 -45
  201. data/lib/active_record/type/date_time.rb +2 -49
  202. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  203. data/lib/active_record/type/internal/timezone.rb +15 -0
  204. data/lib/active_record/type/serialized.rb +15 -14
  205. data/lib/active_record/type/time.rb +10 -16
  206. data/lib/active_record/type/type_map.rb +4 -4
  207. data/lib/active_record/type_caster.rb +7 -0
  208. data/lib/active_record/type_caster/connection.rb +29 -0
  209. data/lib/active_record/type_caster/map.rb +19 -0
  210. data/lib/active_record/validations.rb +33 -32
  211. data/lib/active_record/validations/absence.rb +23 -0
  212. data/lib/active_record/validations/associated.rb +10 -3
  213. data/lib/active_record/validations/length.rb +24 -0
  214. data/lib/active_record/validations/presence.rb +11 -12
  215. data/lib/active_record/validations/uniqueness.rb +30 -29
  216. data/lib/rails/generators/active_record/migration.rb +7 -0
  217. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  218. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  219. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
  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 +59 -34
  224. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  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 -64
  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 -110
@@ -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,17 +95,25 @@ 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
112
117
  end
113
118
 
114
119
  class Version
@@ -125,7 +130,8 @@ module ActiveRecord
125
130
 
126
131
  class BindCollector < Arel::Collectors::Bind
127
132
  def compile(bvs, conn)
128
- 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) })
129
135
  end
130
136
  end
131
137
 
@@ -143,20 +149,32 @@ module ActiveRecord
143
149
  end
144
150
  end
145
151
 
152
+ def arel_visitor # :nodoc:
153
+ Arel::Visitors::ToSql.new(self)
154
+ end
155
+
146
156
  def valid_type?(type)
147
- true
157
+ false
148
158
  end
149
159
 
150
160
  def schema_creation
151
161
  SchemaCreation.new self
152
162
  end
153
163
 
164
+ # this method must only be called while holding connection pool's mutex
154
165
  def lease
155
- synchronize do
156
- unless in_use?
157
- @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}."
158
173
  end
174
+ raise ActiveRecordError, msg
159
175
  end
176
+
177
+ @owner = Thread.current
160
178
  end
161
179
 
162
180
  def schema_cache=(cache)
@@ -164,6 +182,7 @@ module ActiveRecord
164
182
  @schema_cache = cache
165
183
  end
166
184
 
185
+ # this method must only be called while holding connection pool's mutex
167
186
  def expire
168
187
  @owner = nil
169
188
  end
@@ -207,6 +226,11 @@ module ActiveRecord
207
226
  false
208
227
  end
209
228
 
229
+ # Does this adapter support application-enforced advisory locking?
230
+ def supports_advisory_locks?
231
+ false
232
+ end
233
+
210
234
  # Should primary key values be selected from their corresponding
211
235
  # sequence before the insert statement? If true, next_sequence_value
212
236
  # is called before each insert to set the record's primary key.
@@ -224,6 +248,11 @@ module ActiveRecord
224
248
  false
225
249
  end
226
250
 
251
+ # Does this adapter support expression indices?
252
+ def supports_expression_index?
253
+ false
254
+ end
255
+
227
256
  # Does this adapter support explain?
228
257
  def supports_explain?
229
258
  false
@@ -255,6 +284,31 @@ module ActiveRecord
255
284
  false
256
285
  end
257
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
+
258
312
  # This is meant to be implemented by the adapters that support extensions
259
313
  def disable_extension(name)
260
314
  end
@@ -263,6 +317,20 @@ module ActiveRecord
263
317
  def enable_extension(name)
264
318
  end
265
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
+
266
334
  # A list of extensions, to be filled in by adapters that support them.
267
335
  def extensions
268
336
  []
@@ -273,14 +341,6 @@ module ActiveRecord
273
341
  {}
274
342
  end
275
343
 
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
344
  # REFERENTIAL INTEGRITY ====================================
285
345
 
286
346
  # Override to turn off referential integrity while executing <tt>&block</tt>.
@@ -334,14 +394,14 @@ module ActiveRecord
334
394
  end
335
395
 
336
396
  # 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
397
+ # This is done under the hood by calling #active?. If the connection
338
398
  # is no longer active, then this method will reconnect to the database.
339
399
  def verify!(*ignored)
340
400
  reconnect! unless active?
341
401
  end
342
402
 
343
403
  # Provides access to the underlying database driver for this adapter. For
344
- # example, this method returns a Mysql object in case of MysqlAdapter,
404
+ # example, this method returns a Mysql2::Client object in case of Mysql2Adapter,
345
405
  # and a PGconn object in case of PostgreSQLAdapter.
346
406
  #
347
407
  # This is useful for when you need to call a proprietary method such as
@@ -350,29 +410,26 @@ module ActiveRecord
350
410
  @connection
351
411
  end
352
412
 
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
413
  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)
414
+ if value.nil?
415
+ table[attribute].eq(value)
416
+ else
417
+ table[attribute].eq(Arel::Nodes::BindParam.new)
418
+ end
367
419
  end
368
420
 
369
421
  def case_insensitive_comparison(table, attribute, column, value)
370
- 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
371
427
  end
372
428
 
373
- def current_savepoint_name
374
- current_transaction.savepoint_name
429
+ def can_perform_case_insensitive_comparison_for?(column)
430
+ true
375
431
  end
432
+ private :can_perform_case_insensitive_comparison_for?
376
433
 
377
434
  # Check the connection back in to the connection pool
378
435
  def close
@@ -385,8 +442,8 @@ module ActiveRecord
385
442
  end
386
443
  end
387
444
 
388
- def new_column(name, default, cast_type, sql_type = nil, null = true)
389
- 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)
390
447
  end
391
448
 
392
449
  def lookup_cast_type(sql_type) # :nodoc:
@@ -397,18 +454,36 @@ module ActiveRecord
397
454
  visitor.accept(node, collector).value
398
455
  end
399
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
+
400
475
  protected
401
476
 
402
477
  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
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
412
487
 
413
488
  m.alias_type %r(blob)i, 'binary'
414
489
  m.alias_type %r(clob)i, 'text'
@@ -442,6 +517,13 @@ module ActiveRecord
442
517
  end
443
518
  end
444
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
+
445
527
  def extract_scale(sql_type) # :nodoc:
446
528
  case sql_type
447
529
  when /\((\d+)\)/ then 0
@@ -488,7 +570,7 @@ module ActiveRecord
488
570
 
489
571
  def translate_exception(exception, message)
490
572
  # override in derived class
491
- ActiveRecord::StatementInvalid.new(message, exception)
573
+ ActiveRecord::StatementInvalid.new(message)
492
574
  end
493
575
 
494
576
  def without_prepared_statement?(binds)