activerecord 5.2.4.5 → 6.0.0.beta1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +299 -739
- data/MIT-LICENSE +3 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +2 -1
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/associations.rb +16 -12
- data/lib/active_record/associations/association.rb +35 -19
- data/lib/active_record/associations/association_scope.rb +4 -6
- data/lib/active_record/associations/belongs_to_association.rb +36 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
- data/lib/active_record/associations/builder/belongs_to.rb +14 -50
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/collection_association.rb +11 -25
- data/lib/active_record/associations/collection_proxy.rb +32 -6
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +25 -18
- data/lib/active_record/associations/has_one_association.rb +28 -30
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +15 -20
- data/lib/active_record/associations/join_dependency/join_association.rb +11 -26
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader.rb +32 -29
- data/lib/active_record/associations/preloader/association.rb +1 -2
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods.rb +34 -56
- data/lib/active_record/attribute_methods/dirty.rb +64 -26
- data/lib/active_record/attribute_methods/primary_key.rb +8 -7
- data/lib/active_record/attribute_methods/read.rb +16 -48
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_methods/write.rb +15 -16
- data/lib/active_record/autosave_association.rb +7 -21
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +3 -17
- data/lib/active_record/collection_cache_key.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +13 -36
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -27
- data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
- data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
- data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +95 -62
- data/lib/active_record/connection_handling.rb +132 -26
- data/lib/active_record/core.rb +76 -43
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations.rb +184 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +74 -0
- data/lib/active_record/enum.rb +22 -7
- data/lib/active_record/errors.rb +24 -21
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +140 -472
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +12 -2
- data/lib/active_record/integration.rb +56 -16
- data/lib/active_record/internal_metadata.rb +5 -1
- data/lib/active_record/locking/optimistic.rb +2 -2
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/migration.rb +38 -37
- data/lib/active_record/migration/command_recorder.rb +35 -5
- data/lib/active_record/migration/compatibility.rb +34 -16
- data/lib/active_record/model_schema.rb +30 -9
- data/lib/active_record/nested_attributes.rb +2 -2
- data/lib/active_record/no_touching.rb +7 -0
- data/lib/active_record/persistence.rb +18 -7
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +19 -11
- data/lib/active_record/railtie.rb +71 -42
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +94 -43
- data/lib/active_record/reflection.rb +60 -44
- data/lib/active_record/relation.rb +150 -69
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +38 -28
- data/lib/active_record/relation/delegation.rb +4 -13
- data/lib/active_record/relation/finder_methods.rb +12 -25
- data/lib/active_record/relation/merger.rb +2 -6
- data/lib/active_record/relation/predicate_builder.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/query_attribute.rb +15 -12
- data/lib/active_record/relation/query_methods.rb +29 -52
- data/lib/active_record/relation/where_clause.rb +4 -0
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +2 -39
- data/lib/active_record/schema.rb +1 -10
- data/lib/active_record/schema_dumper.rb +12 -6
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +10 -3
- data/lib/active_record/scoping/named.rb +10 -14
- data/lib/active_record/statement_cache.rb +32 -5
- data/lib/active_record/store.rb +39 -8
- data/lib/active_record/table_metadata.rb +1 -4
- data/lib/active_record/tasks/database_tasks.rb +89 -23
- data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
- data/lib/active_record/test_databases.rb +38 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/transactions.rb +3 -22
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type_caster/connection.rb +1 -6
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations/uniqueness.rb +13 -25
- data/lib/arel.rb +44 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +67 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +63 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values.rb +16 -0
- data/lib/arel/nodes/values_list.rb +24 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +199 -0
- data/lib/arel/visitors/dot.rb +292 -0
- data/lib/arel/visitors/ibm_db.rb +21 -0
- data/lib/arel/visitors/informix.rb +56 -0
- data/lib/arel/visitors/mssql.rb +143 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +67 -0
- data/lib/arel/visitors/postgresql.rb +116 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +913 -0
- data/lib/arel/visitors/visitor.rb +42 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- metadata +104 -26
@@ -40,24 +40,6 @@ module ActiveRecord
|
|
40
40
|
committed? || rolledback?
|
41
41
|
end
|
42
42
|
|
43
|
-
def set_state(state)
|
44
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
45
|
-
The set_state method is deprecated and will be removed in
|
46
|
-
Rails 6.0. Please use rollback! or commit! to set transaction
|
47
|
-
state directly.
|
48
|
-
MSG
|
49
|
-
case state
|
50
|
-
when :rolledback
|
51
|
-
rollback!
|
52
|
-
when :committed
|
53
|
-
commit!
|
54
|
-
when nil
|
55
|
-
nullify!
|
56
|
-
else
|
57
|
-
raise ArgumentError, "Invalid transaction state: #{state}"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
43
|
def rollback!
|
62
44
|
@children.each { |c| c.rollback! }
|
63
45
|
@state = :rolledback
|
@@ -91,13 +73,14 @@ module ActiveRecord
|
|
91
73
|
end
|
92
74
|
|
93
75
|
class Transaction #:nodoc:
|
94
|
-
attr_reader :connection, :state, :records, :savepoint_name
|
95
|
-
attr_writer :joinable
|
76
|
+
attr_reader :connection, :state, :records, :savepoint_name, :isolation_level
|
96
77
|
|
97
78
|
def initialize(connection, options, run_commit_callbacks: false)
|
98
79
|
@connection = connection
|
99
80
|
@state = TransactionState.new
|
100
81
|
@records = []
|
82
|
+
@isolation_level = options[:isolation]
|
83
|
+
@materialized = false
|
101
84
|
@joinable = options.fetch(:joinable, true)
|
102
85
|
@run_commit_callbacks = run_commit_callbacks
|
103
86
|
end
|
@@ -106,6 +89,14 @@ module ActiveRecord
|
|
106
89
|
records << record
|
107
90
|
end
|
108
91
|
|
92
|
+
def materialize!
|
93
|
+
@materialized = true
|
94
|
+
end
|
95
|
+
|
96
|
+
def materialized?
|
97
|
+
@materialized
|
98
|
+
end
|
99
|
+
|
109
100
|
def rollback_records
|
110
101
|
ite = records.uniq
|
111
102
|
while record = ite.shift
|
@@ -128,7 +119,7 @@ module ActiveRecord
|
|
128
119
|
record.committed!
|
129
120
|
else
|
130
121
|
# if not running callbacks, only adds the record to the parent transaction
|
131
|
-
record
|
122
|
+
connection.add_transaction_record(record)
|
132
123
|
end
|
133
124
|
end
|
134
125
|
ensure
|
@@ -142,24 +133,30 @@ module ActiveRecord
|
|
142
133
|
end
|
143
134
|
|
144
135
|
class SavepointTransaction < Transaction
|
145
|
-
def initialize(connection, savepoint_name, parent_transaction,
|
146
|
-
super(connection,
|
136
|
+
def initialize(connection, savepoint_name, parent_transaction, *args)
|
137
|
+
super(connection, *args)
|
147
138
|
|
148
139
|
parent_transaction.state.add_child(@state)
|
149
140
|
|
150
|
-
if
|
141
|
+
if isolation_level
|
151
142
|
raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
|
152
143
|
end
|
153
|
-
|
144
|
+
|
145
|
+
@savepoint_name = savepoint_name
|
146
|
+
end
|
147
|
+
|
148
|
+
def materialize!
|
149
|
+
connection.create_savepoint(savepoint_name)
|
150
|
+
super
|
154
151
|
end
|
155
152
|
|
156
153
|
def rollback
|
157
|
-
connection.rollback_to_savepoint(savepoint_name)
|
154
|
+
connection.rollback_to_savepoint(savepoint_name) if materialized?
|
158
155
|
@state.rollback!
|
159
156
|
end
|
160
157
|
|
161
158
|
def commit
|
162
|
-
connection.release_savepoint(savepoint_name)
|
159
|
+
connection.release_savepoint(savepoint_name) if materialized?
|
163
160
|
@state.commit!
|
164
161
|
end
|
165
162
|
|
@@ -167,22 +164,23 @@ module ActiveRecord
|
|
167
164
|
end
|
168
165
|
|
169
166
|
class RealTransaction < Transaction
|
170
|
-
def
|
171
|
-
|
172
|
-
|
173
|
-
connection.begin_isolated_db_transaction(options[:isolation])
|
167
|
+
def materialize!
|
168
|
+
if isolation_level
|
169
|
+
connection.begin_isolated_db_transaction(isolation_level)
|
174
170
|
else
|
175
171
|
connection.begin_db_transaction
|
176
172
|
end
|
173
|
+
|
174
|
+
super
|
177
175
|
end
|
178
176
|
|
179
177
|
def rollback
|
180
|
-
connection.rollback_db_transaction
|
178
|
+
connection.rollback_db_transaction if materialized?
|
181
179
|
@state.full_rollback!
|
182
180
|
end
|
183
181
|
|
184
182
|
def commit
|
185
|
-
connection.commit_db_transaction
|
183
|
+
connection.commit_db_transaction if materialized?
|
186
184
|
@state.full_commit!
|
187
185
|
end
|
188
186
|
end
|
@@ -191,6 +189,9 @@ module ActiveRecord
|
|
191
189
|
def initialize(connection)
|
192
190
|
@stack = []
|
193
191
|
@connection = connection
|
192
|
+
@has_unmaterialized_transactions = false
|
193
|
+
@materializing_transactions = false
|
194
|
+
@lazy_transactions_enabled = true
|
194
195
|
end
|
195
196
|
|
196
197
|
def begin_transaction(options = {})
|
@@ -204,11 +205,41 @@ module ActiveRecord
|
|
204
205
|
run_commit_callbacks: run_commit_callbacks)
|
205
206
|
end
|
206
207
|
|
208
|
+
transaction.materialize! unless @connection.supports_lazy_transactions? && lazy_transactions_enabled?
|
207
209
|
@stack.push(transaction)
|
210
|
+
@has_unmaterialized_transactions = true if @connection.supports_lazy_transactions?
|
208
211
|
transaction
|
209
212
|
end
|
210
213
|
end
|
211
214
|
|
215
|
+
def disable_lazy_transactions!
|
216
|
+
materialize_transactions
|
217
|
+
@lazy_transactions_enabled = false
|
218
|
+
end
|
219
|
+
|
220
|
+
def enable_lazy_transactions!
|
221
|
+
@lazy_transactions_enabled = true
|
222
|
+
end
|
223
|
+
|
224
|
+
def lazy_transactions_enabled?
|
225
|
+
@lazy_transactions_enabled
|
226
|
+
end
|
227
|
+
|
228
|
+
def materialize_transactions
|
229
|
+
return if @materializing_transactions
|
230
|
+
return unless @has_unmaterialized_transactions
|
231
|
+
|
232
|
+
@connection.lock.synchronize do
|
233
|
+
begin
|
234
|
+
@materializing_transactions = true
|
235
|
+
@stack.each { |t| t.materialize! unless t.materialized? }
|
236
|
+
ensure
|
237
|
+
@materializing_transactions = false
|
238
|
+
end
|
239
|
+
@has_unmaterialized_transactions = false
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
212
243
|
def commit_transaction
|
213
244
|
@connection.lock.synchronize do
|
214
245
|
transaction = @stack.last
|
@@ -234,26 +265,24 @@ module ActiveRecord
|
|
234
265
|
|
235
266
|
def within_new_transaction(options = {})
|
236
267
|
@connection.lock.synchronize do
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
268
|
+
transaction = begin_transaction options
|
269
|
+
yield
|
270
|
+
rescue Exception => error
|
271
|
+
if transaction
|
272
|
+
rollback_transaction
|
273
|
+
after_failure_actions(transaction, error)
|
274
|
+
end
|
275
|
+
raise
|
276
|
+
ensure
|
277
|
+
if !error && transaction
|
278
|
+
if Thread.current.status == "aborting"
|
242
279
|
rollback_transaction
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
rollback_transaction if transaction
|
250
|
-
else
|
251
|
-
begin
|
252
|
-
commit_transaction if transaction
|
253
|
-
rescue Exception
|
254
|
-
rollback_transaction(transaction) unless transaction.state.completed?
|
255
|
-
raise
|
256
|
-
end
|
280
|
+
else
|
281
|
+
begin
|
282
|
+
commit_transaction
|
283
|
+
rescue Exception
|
284
|
+
rollback_transaction(transaction) unless transaction.state.completed?
|
285
|
+
raise
|
257
286
|
end
|
258
287
|
end
|
259
288
|
end
|
@@ -6,6 +6,7 @@ require "active_record/connection_adapters/sql_type_metadata"
|
|
6
6
|
require "active_record/connection_adapters/abstract/schema_dumper"
|
7
7
|
require "active_record/connection_adapters/abstract/schema_creation"
|
8
8
|
require "active_support/concurrency/load_interlock_aware_monitor"
|
9
|
+
require "active_support/deprecation"
|
9
10
|
require "arel/collectors/bind"
|
10
11
|
require "arel/collectors/composite"
|
11
12
|
require "arel/collectors/sql_string"
|
@@ -65,7 +66,7 @@ module ActiveRecord
|
|
65
66
|
# Most of the methods in the adapter are useful during migrations. Most
|
66
67
|
# notably, the instance methods provided by SchemaStatements are very useful.
|
67
68
|
class AbstractAdapter
|
68
|
-
ADAPTER_NAME = "Abstract"
|
69
|
+
ADAPTER_NAME = "Abstract"
|
69
70
|
include ActiveSupport::Callbacks
|
70
71
|
define_callbacks :checkout, :checkin
|
71
72
|
|
@@ -76,14 +77,19 @@ module ActiveRecord
|
|
76
77
|
|
77
78
|
SIMPLE_INT = /\A\d+\z/
|
78
79
|
|
79
|
-
|
80
|
-
|
80
|
+
attr_writer :visitor
|
81
|
+
deprecate :visitor=
|
82
|
+
|
83
|
+
attr_accessor :pool
|
84
|
+
attr_reader :schema_cache, :visitor, :owner, :logger, :lock, :prepared_statements, :prevent_writes
|
81
85
|
alias :in_use? :owner
|
82
86
|
|
87
|
+
set_callback :checkin, :after, :enable_lazy_transactions!
|
88
|
+
|
83
89
|
def self.type_cast_config_to_integer(config)
|
84
90
|
if config.is_a?(Integer)
|
85
91
|
config
|
86
|
-
elsif config
|
92
|
+
elsif SIMPLE_INT.match?(config)
|
87
93
|
config.to_i
|
88
94
|
else
|
89
95
|
config
|
@@ -98,6 +104,11 @@ module ActiveRecord
|
|
98
104
|
end
|
99
105
|
end
|
100
106
|
|
107
|
+
def self.build_read_query_regexp(*parts) # :nodoc:
|
108
|
+
parts = parts.map { |part| /\A\s*#{part}/i }
|
109
|
+
Regexp.union(*parts)
|
110
|
+
end
|
111
|
+
|
101
112
|
def initialize(connection, logger = nil, config = {}) # :nodoc:
|
102
113
|
super()
|
103
114
|
|
@@ -110,6 +121,7 @@ module ActiveRecord
|
|
110
121
|
@idle_since = Concurrent.monotonic_time
|
111
122
|
@schema_cache = SchemaCache.new self
|
112
123
|
@quoted_column_names, @quoted_table_names = {}, {}
|
124
|
+
@prevent_writes = false
|
113
125
|
@visitor = arel_visitor
|
114
126
|
@lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
|
115
127
|
|
@@ -119,6 +131,36 @@ module ActiveRecord
|
|
119
131
|
else
|
120
132
|
@prepared_statements = false
|
121
133
|
end
|
134
|
+
|
135
|
+
@advisory_locks_enabled = self.class.type_cast_config_to_boolean(
|
136
|
+
config.fetch(:advisory_locks, true)
|
137
|
+
)
|
138
|
+
|
139
|
+
check_version
|
140
|
+
end
|
141
|
+
|
142
|
+
def replica?
|
143
|
+
@config[:replica] || false
|
144
|
+
end
|
145
|
+
|
146
|
+
# Determines whether writes are currently being prevents.
|
147
|
+
#
|
148
|
+
# Returns true if the connection is a replica, or if +prevent_writes+
|
149
|
+
# is set to true.
|
150
|
+
def preventing_writes?
|
151
|
+
replica? || prevent_writes
|
152
|
+
end
|
153
|
+
|
154
|
+
# Prevent writing to the database regardless of role.
|
155
|
+
#
|
156
|
+
# In some cases you may want to prevent writes to the database
|
157
|
+
# even if you are on a database that can write. `while_preventing_writes`
|
158
|
+
# will prevent writes to the database for the duration of the block.
|
159
|
+
def while_preventing_writes
|
160
|
+
original, @prevent_writes = @prevent_writes, true
|
161
|
+
yield
|
162
|
+
ensure
|
163
|
+
@prevent_writes = original
|
122
164
|
end
|
123
165
|
|
124
166
|
def migrations_paths # :nodoc:
|
@@ -139,6 +181,10 @@ module ActiveRecord
|
|
139
181
|
def <=>(version_string)
|
140
182
|
@version <=> version_string.split(".").map(&:to_i)
|
141
183
|
end
|
184
|
+
|
185
|
+
def to_s
|
186
|
+
@version.join(".")
|
187
|
+
end
|
142
188
|
end
|
143
189
|
|
144
190
|
def valid_type?(type) # :nodoc:
|
@@ -148,7 +194,7 @@ module ActiveRecord
|
|
148
194
|
# this method must only be called while holding connection pool's mutex
|
149
195
|
def lease
|
150
196
|
if in_use?
|
151
|
-
msg = "Cannot lease connection, "
|
197
|
+
msg = +"Cannot lease connection, "
|
152
198
|
if @owner == Thread.current
|
153
199
|
msg << "it is already leased by the current thread."
|
154
200
|
else
|
@@ -298,6 +344,11 @@ module ActiveRecord
|
|
298
344
|
false
|
299
345
|
end
|
300
346
|
|
347
|
+
# Does this adapter support materialized views?
|
348
|
+
def supports_materialized_views?
|
349
|
+
false
|
350
|
+
end
|
351
|
+
|
301
352
|
# Does this adapter support datetime with precision?
|
302
353
|
def supports_datetime_with_precision?
|
303
354
|
false
|
@@ -322,6 +373,7 @@ module ActiveRecord
|
|
322
373
|
def supports_multi_insert?
|
323
374
|
true
|
324
375
|
end
|
376
|
+
deprecate :supports_multi_insert?
|
325
377
|
|
326
378
|
# Does this adapter support virtual columns?
|
327
379
|
def supports_virtual_columns?
|
@@ -333,6 +385,10 @@ module ActiveRecord
|
|
333
385
|
false
|
334
386
|
end
|
335
387
|
|
388
|
+
def supports_lazy_transactions?
|
389
|
+
false
|
390
|
+
end
|
391
|
+
|
336
392
|
# This is meant to be implemented by the adapters that support extensions
|
337
393
|
def disable_extension(name)
|
338
394
|
end
|
@@ -341,6 +397,10 @@ module ActiveRecord
|
|
341
397
|
def enable_extension(name)
|
342
398
|
end
|
343
399
|
|
400
|
+
def advisory_locks_enabled? # :nodoc:
|
401
|
+
supports_advisory_locks? && @advisory_locks_enabled
|
402
|
+
end
|
403
|
+
|
344
404
|
# This is meant to be implemented by the adapters that support advisory
|
345
405
|
# locks
|
346
406
|
#
|
@@ -444,18 +504,21 @@ module ActiveRecord
|
|
444
504
|
# This is useful for when you need to call a proprietary method such as
|
445
505
|
# PostgreSQL's lo_* methods.
|
446
506
|
def raw_connection
|
507
|
+
disable_lazy_transactions!
|
447
508
|
@connection
|
448
509
|
end
|
449
510
|
|
450
|
-
def case_sensitive_comparison(
|
451
|
-
|
511
|
+
def case_sensitive_comparison(attribute, value) # :nodoc:
|
512
|
+
attribute.eq(value)
|
452
513
|
end
|
453
514
|
|
454
|
-
def case_insensitive_comparison(
|
515
|
+
def case_insensitive_comparison(attribute, value) # :nodoc:
|
516
|
+
column = column_for_attribute(attribute)
|
517
|
+
|
455
518
|
if can_perform_case_insensitive_comparison_for?(column)
|
456
|
-
|
519
|
+
attribute.lower.eq(attribute.relation.lower(value))
|
457
520
|
else
|
458
|
-
|
521
|
+
attribute.eq(value)
|
459
522
|
end
|
460
523
|
end
|
461
524
|
|
@@ -470,11 +533,7 @@ module ActiveRecord
|
|
470
533
|
end
|
471
534
|
|
472
535
|
def column_name_for_operation(operation, node) # :nodoc:
|
473
|
-
|
474
|
-
end
|
475
|
-
|
476
|
-
def column_name_from_arel_node(node) # :nodoc:
|
477
|
-
visitor.accept(node, Arel::Collectors::SQLString.new).value
|
536
|
+
visitor.compile(node)
|
478
537
|
end
|
479
538
|
|
480
539
|
def default_index_type?(index) # :nodoc:
|
@@ -482,6 +541,9 @@ module ActiveRecord
|
|
482
541
|
end
|
483
542
|
|
484
543
|
private
|
544
|
+
def check_version
|
545
|
+
end
|
546
|
+
|
485
547
|
def type_map
|
486
548
|
@type_map ||= Type::TypeMap.new.tap do |mapping|
|
487
549
|
initialize_type_map(mapping)
|
@@ -555,14 +617,12 @@ module ActiveRecord
|
|
555
617
|
$1.to_i if sql_type =~ /\((.*)\)/
|
556
618
|
end
|
557
619
|
|
558
|
-
def translate_exception_class(e, sql)
|
559
|
-
|
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
|
620
|
+
def translate_exception_class(e, sql, binds)
|
621
|
+
message = "#{e.class.name}: #{e.message}"
|
564
622
|
|
565
|
-
exception = translate_exception(
|
623
|
+
exception = translate_exception(
|
624
|
+
e, message: message, sql: sql, binds: binds
|
625
|
+
)
|
566
626
|
exception.set_backtrace e.backtrace
|
567
627
|
exception
|
568
628
|
end
|
@@ -575,24 +635,23 @@ module ActiveRecord
|
|
575
635
|
binds: binds,
|
576
636
|
type_casted_binds: type_casted_binds,
|
577
637
|
statement_name: statement_name,
|
578
|
-
connection_id: object_id
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
end
|
583
|
-
rescue => e
|
584
|
-
raise translate_exception_class(e, sql)
|
638
|
+
connection_id: object_id,
|
639
|
+
connection: self) do
|
640
|
+
@lock.synchronize do
|
641
|
+
yield
|
585
642
|
end
|
643
|
+
rescue => e
|
644
|
+
raise translate_exception_class(e, sql, binds)
|
586
645
|
end
|
587
646
|
end
|
588
647
|
|
589
|
-
def translate_exception(exception, message)
|
648
|
+
def translate_exception(exception, message:, sql:, binds:)
|
590
649
|
# override in derived class
|
591
650
|
case exception
|
592
651
|
when RuntimeError
|
593
652
|
exception
|
594
653
|
else
|
595
|
-
ActiveRecord::StatementInvalid.new(message)
|
654
|
+
ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
|
596
655
|
end
|
597
656
|
end
|
598
657
|
|
@@ -606,6 +665,11 @@ module ActiveRecord
|
|
606
665
|
raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
|
607
666
|
end
|
608
667
|
|
668
|
+
def column_for_attribute(attribute)
|
669
|
+
table_name = attribute.relation.name
|
670
|
+
schema_cache.columns_hash(table_name)[attribute.name.to_s]
|
671
|
+
end
|
672
|
+
|
609
673
|
def collector
|
610
674
|
if prepared_statements
|
611
675
|
Arel::Collectors::Composite.new(
|