activerecord 7.0.4.3 → 7.1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1657 -1274
- data/MIT-LICENSE +1 -1
- data/README.rdoc +18 -18
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/association.rb +20 -4
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +14 -6
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +21 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +16 -10
- data/lib/active_record/associations/collection_proxy.rb +20 -10
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +20 -13
- data/lib/active_record/associations/has_many_through_association.rb +10 -6
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency.rb +10 -8
- data/lib/active_record/associations/preloader/association.rb +31 -7
- data/lib/active_record/associations/preloader/through_association.rb +1 -1
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +327 -222
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/dirty.rb +52 -34
- data/lib/active_record/attribute_methods/primary_key.rb +76 -24
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +18 -5
- data/lib/active_record/attribute_methods/serialization.rb +150 -31
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +0 -4
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +108 -26
- data/lib/active_record/attributes.rb +3 -3
- data/lib/active_record/autosave_association.rb +55 -9
- data/lib/active_record/base.rb +7 -2
- data/lib/active_record/callbacks.rb +16 -32
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +163 -88
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +74 -51
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +129 -31
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +62 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +41 -6
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +155 -25
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +290 -124
- data/lib/active_record/connection_adapters/abstract/transaction.rb +287 -58
- data/lib/active_record/connection_adapters/abstract_adapter.rb +509 -102
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +217 -112
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +23 -144
- data/lib/active_record/connection_adapters/mysql/quoting.rb +29 -14
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +18 -13
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
- data/lib/active_record/connection_adapters/pool_config.rb +14 -5
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +16 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +75 -45
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +15 -8
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +362 -60
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +354 -193
- data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +52 -39
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +9 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +28 -9
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +211 -83
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +262 -0
- data/lib/active_record/connection_adapters.rb +3 -1
- data/lib/active_record/connection_handling.rb +72 -95
- data/lib/active_record/core.rb +175 -153
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/database_config.rb +9 -3
- data/lib/active_record/database_configurations/hash_config.rb +22 -12
- data/lib/active_record/database_configurations/url_config.rb +17 -11
- data/lib/active_record/database_configurations.rb +86 -33
- data/lib/active_record/delegated_type.rb +9 -4
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +2 -0
- data/lib/active_record/disable_joins_association_relation.rb +1 -1
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +42 -18
- data/lib/active_record/encryption/encrypted_attribute_type.rb +21 -6
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -69
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/message_serializer.rb +2 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/scheme.rb +19 -22
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +112 -28
- data/lib/active_record/errors.rb +112 -18
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +29 -8
- data/lib/active_record/fixtures.rb +135 -71
- data/lib/active_record/future_result.rb +31 -5
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +30 -16
- data/lib/active_record/insert_all.rb +57 -10
- data/lib/active_record/integration.rb +8 -8
- data/lib/active_record/internal_metadata.rb +120 -30
- data/lib/active_record/locking/optimistic.rb +32 -18
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +29 -12
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +9 -11
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +105 -7
- data/lib/active_record/migration/compatibility.rb +157 -58
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +271 -114
- data/lib/active_record/model_schema.rb +64 -44
- data/lib/active_record/nested_attributes.rb +24 -6
- data/lib/active_record/normalization.rb +167 -0
- data/lib/active_record/persistence.rb +195 -42
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +77 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +15 -2
- data/lib/active_record/railtie.rb +109 -47
- data/lib/active_record/railties/controller_runtime.rb +14 -9
- data/lib/active_record/railties/databases.rake +142 -148
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +182 -44
- data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
- data/lib/active_record/relation/batches.rb +190 -61
- data/lib/active_record/relation/calculations.rb +232 -81
- data/lib/active_record/relation/delegation.rb +23 -9
- data/lib/active_record/relation/finder_methods.rb +77 -16
- data/lib/active_record/relation/merger.rb +2 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +26 -14
- data/lib/active_record/relation/query_attribute.rb +25 -1
- data/lib/active_record/relation/query_methods.rb +387 -71
- data/lib/active_record/relation/spawn_methods.rb +18 -1
- data/lib/active_record/relation.rb +91 -35
- data/lib/active_record/result.rb +25 -9
- data/lib/active_record/runtime_registry.rb +24 -1
- data/lib/active_record/sanitization.rb +51 -11
- data/lib/active_record/schema.rb +2 -3
- data/lib/active_record/schema_dumper.rb +50 -7
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +2 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +7 -5
- data/lib/active_record/store.rb +9 -9
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +127 -105
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_fixtures.rb +113 -96
- data/lib/active_record/timestamp.rb +27 -15
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +39 -13
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +8 -4
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +47 -2
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +121 -16
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +1 -1
- data/lib/arel/nodes/and.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/filter.rb +1 -1
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +4 -0
- data/lib/arel/predications.rb +2 -0
- data/lib/arel/table.rb +9 -5
- data/lib/arel/visitors/mysql.rb +8 -1
- data/lib/arel/visitors/to_sql.rb +81 -17
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +16 -2
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- metadata +48 -12
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
@@ -5,10 +5,13 @@ require "concurrent/map"
|
|
5
5
|
module ActiveRecord
|
6
6
|
module ConnectionAdapters # :nodoc:
|
7
7
|
module QueryCache
|
8
|
+
DEFAULT_SIZE = 100 # :nodoc:
|
9
|
+
|
8
10
|
class << self
|
9
11
|
def included(base) # :nodoc:
|
10
|
-
dirties_query_cache base, :create, :insert, :update, :delete, :truncate,
|
11
|
-
:rollback_to_savepoint, :rollback_db_transaction, :
|
12
|
+
dirties_query_cache base, :exec_query, :execute, :create, :insert, :update, :delete, :truncate,
|
13
|
+
:truncate_tables, :rollback_to_savepoint, :rollback_db_transaction, :restart_db_transaction,
|
14
|
+
:exec_insert_all
|
12
15
|
|
13
16
|
base.set_callback :checkout, :after, :configure_query_cache!
|
14
17
|
base.set_callback :checkin, :after, :disable_query_cache!
|
@@ -17,7 +20,7 @@ module ActiveRecord
|
|
17
20
|
def dirties_query_cache(base, *method_names)
|
18
21
|
method_names.each do |method_name|
|
19
22
|
base.class_eval <<-end_code, __FILE__, __LINE__ + 1
|
20
|
-
def #{method_name}(
|
23
|
+
def #{method_name}(...)
|
21
24
|
ActiveRecord::Base.clear_query_caches_for_current_thread
|
22
25
|
super
|
23
26
|
end
|
@@ -51,8 +54,9 @@ module ActiveRecord
|
|
51
54
|
|
52
55
|
def initialize(*)
|
53
56
|
super
|
54
|
-
@query_cache =
|
57
|
+
@query_cache = {}
|
55
58
|
@query_cache_enabled = false
|
59
|
+
@query_cache_max_size = nil
|
56
60
|
end
|
57
61
|
|
58
62
|
# Enable the query cache within the block.
|
@@ -93,7 +97,7 @@ module ActiveRecord
|
|
93
97
|
end
|
94
98
|
end
|
95
99
|
|
96
|
-
def select_all(arel, name = nil, binds = [], preparable: nil, async: false)
|
100
|
+
def select_all(arel, name = nil, binds = [], preparable: nil, async: false) # :nodoc:
|
97
101
|
arel = arel_from_relation(arel)
|
98
102
|
|
99
103
|
# If arel is locked this is a SELECT ... FOR UPDATE or somesuch.
|
@@ -102,7 +106,8 @@ module ActiveRecord
|
|
102
106
|
sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
|
103
107
|
|
104
108
|
if async
|
105
|
-
lookup_sql_cache(sql, name, binds) || super(sql, name, binds, preparable: preparable, async: async)
|
109
|
+
result = lookup_sql_cache(sql, name, binds) || super(sql, name, binds, preparable: preparable, async: async)
|
110
|
+
FutureResult::Complete.new(result)
|
106
111
|
else
|
107
112
|
cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable, async: async) }
|
108
113
|
end
|
@@ -113,31 +118,52 @@ module ActiveRecord
|
|
113
118
|
|
114
119
|
private
|
115
120
|
def lookup_sql_cache(sql, name, binds)
|
121
|
+
key = binds.empty? ? sql : [sql, binds]
|
122
|
+
hit = false
|
123
|
+
result = nil
|
124
|
+
|
116
125
|
@lock.synchronize do
|
117
|
-
if @query_cache
|
118
|
-
|
119
|
-
|
120
|
-
cache_notification_info(sql, name, binds)
|
121
|
-
)
|
122
|
-
@query_cache[sql][binds]
|
126
|
+
if (result = @query_cache.delete(key))
|
127
|
+
hit = true
|
128
|
+
@query_cache[key] = result
|
123
129
|
end
|
124
130
|
end
|
131
|
+
|
132
|
+
if hit
|
133
|
+
ActiveSupport::Notifications.instrument(
|
134
|
+
"sql.active_record",
|
135
|
+
cache_notification_info(sql, name, binds)
|
136
|
+
)
|
137
|
+
|
138
|
+
result
|
139
|
+
end
|
125
140
|
end
|
126
141
|
|
127
142
|
def cache_sql(sql, name, binds)
|
143
|
+
key = binds.empty? ? sql : [sql, binds]
|
144
|
+
result = nil
|
145
|
+
hit = false
|
146
|
+
|
128
147
|
@lock.synchronize do
|
129
|
-
result =
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
@query_cache
|
136
|
-
else
|
137
|
-
@query_cache[sql][binds] = yield
|
148
|
+
if (result = @query_cache.delete(key))
|
149
|
+
hit = true
|
150
|
+
@query_cache[key] = result
|
151
|
+
else
|
152
|
+
result = @query_cache[key] = yield
|
153
|
+
if @query_cache_max_size && @query_cache.size > @query_cache_max_size
|
154
|
+
@query_cache.shift
|
138
155
|
end
|
139
|
-
|
156
|
+
end
|
140
157
|
end
|
158
|
+
|
159
|
+
if hit
|
160
|
+
ActiveSupport::Notifications.instrument(
|
161
|
+
"sql.active_record",
|
162
|
+
cache_notification_info(sql, name, binds)
|
163
|
+
)
|
164
|
+
end
|
165
|
+
|
166
|
+
result.dup
|
141
167
|
end
|
142
168
|
|
143
169
|
# Database adapters can override this method to
|
@@ -154,7 +180,20 @@ module ActiveRecord
|
|
154
180
|
end
|
155
181
|
|
156
182
|
def configure_query_cache!
|
157
|
-
|
183
|
+
case query_cache = pool.db_config.query_cache
|
184
|
+
when 0, false
|
185
|
+
return
|
186
|
+
when Integer
|
187
|
+
@query_cache_max_size = query_cache
|
188
|
+
when nil
|
189
|
+
@query_cache_max_size = DEFAULT_SIZE
|
190
|
+
else
|
191
|
+
@query_cache_max_size = nil # no limit
|
192
|
+
end
|
193
|
+
|
194
|
+
if pool.query_cache_enabled
|
195
|
+
enable_query_cache!
|
196
|
+
end
|
158
197
|
end
|
159
198
|
end
|
160
199
|
end
|
@@ -5,6 +5,7 @@ require "active_support/multibyte/chars"
|
|
5
5
|
|
6
6
|
module ActiveRecord
|
7
7
|
module ConnectionAdapters # :nodoc:
|
8
|
+
# = Active Record Connection Adapters \Quoting
|
8
9
|
module Quoting
|
9
10
|
# Quotes the column value to help prevent
|
10
11
|
# {SQL injection attacks}[https://en.wikipedia.org/wiki/SQL_injection].
|
@@ -17,11 +18,14 @@ module ActiveRecord
|
|
17
18
|
when nil then "NULL"
|
18
19
|
# BigDecimals need to be put in a non-normalized form and quoted.
|
19
20
|
when BigDecimal then value.to_s("F")
|
20
|
-
when Numeric
|
21
|
+
when Numeric then value.to_s
|
21
22
|
when Type::Binary::Data then quoted_binary(value)
|
22
23
|
when Type::Time::Value then "'#{quoted_time(value)}'"
|
23
24
|
when Date, Time then "'#{quoted_date(value)}'"
|
24
25
|
when Class then "'#{value}'"
|
26
|
+
when ActiveSupport::Duration
|
27
|
+
warn_quote_duration_deprecated
|
28
|
+
value.to_s
|
25
29
|
else raise TypeError, "can't quote #{value.class.name}"
|
26
30
|
end
|
27
31
|
end
|
@@ -47,8 +51,23 @@ module ActiveRecord
|
|
47
51
|
# Quote a value to be used as a bound parameter of unknown type. For example,
|
48
52
|
# MySQL might perform dangerous castings when comparing a string to a number,
|
49
53
|
# so this method will cast numbers to string.
|
54
|
+
#
|
55
|
+
# Deprecated: Consider `Arel.sql("... ? ...", value)` or
|
56
|
+
# +sanitize_sql+ instead.
|
50
57
|
def quote_bound_value(value)
|
51
|
-
|
58
|
+
ActiveRecord.deprecator.warn(<<~MSG.squish)
|
59
|
+
#quote_bound_value is deprecated and will be removed in Rails 7.2.
|
60
|
+
Consider Arel.sql(".. ? ..", value) or #sanitize_sql instead.
|
61
|
+
MSG
|
62
|
+
|
63
|
+
quote(cast_bound_value(value))
|
64
|
+
end
|
65
|
+
|
66
|
+
# Cast a value to be used as a bound parameter of unknown type. For example,
|
67
|
+
# MySQL might perform dangerous castings when comparing a string to a number,
|
68
|
+
# so this method will cast numbers to string.
|
69
|
+
def cast_bound_value(value) # :nodoc:
|
70
|
+
value
|
52
71
|
end
|
53
72
|
|
54
73
|
# If you are having to call this function, you are likely doing something
|
@@ -83,7 +102,7 @@ module ActiveRecord
|
|
83
102
|
# Override to return the quoted table name for assignment. Defaults to
|
84
103
|
# table quoting.
|
85
104
|
#
|
86
|
-
# This works for
|
105
|
+
# This works for MySQL where table.column can be used to
|
87
106
|
# resolve ambiguity.
|
88
107
|
#
|
89
108
|
# We override this in the sqlite3 and postgresql adapters to use only
|
@@ -121,7 +140,7 @@ module ActiveRecord
|
|
121
140
|
# if the value is a Time responding to usec.
|
122
141
|
def quoted_date(value)
|
123
142
|
if value.acts_like?(:time)
|
124
|
-
if
|
143
|
+
if default_timezone == :utc
|
125
144
|
value = value.getutc if !value.utc?
|
126
145
|
else
|
127
146
|
value = value.getlocal
|
@@ -176,7 +195,7 @@ module ActiveRecord
|
|
176
195
|
(
|
177
196
|
(?:
|
178
197
|
# table_name.column_name | function(one or no argument)
|
179
|
-
((?:\w+\.)?\w+
|
198
|
+
((?:\w+\.)?\w+ | \w+\((?:|\g<2>)\))
|
180
199
|
)
|
181
200
|
(?:(?:\s+AS)?\s+\w+)?
|
182
201
|
)
|
@@ -200,7 +219,7 @@ module ActiveRecord
|
|
200
219
|
(
|
201
220
|
(?:
|
202
221
|
# table_name.column_name | function(one or no argument)
|
203
|
-
((?:\w+\.)?\w+
|
222
|
+
((?:\w+\.)?\w+ | \w+\((?:|\g<2>)\))
|
204
223
|
)
|
205
224
|
(?:\s+ASC|\s+DESC)?
|
206
225
|
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
@@ -225,6 +244,22 @@ module ActiveRecord
|
|
225
244
|
def lookup_cast_type(sql_type)
|
226
245
|
type_map.lookup(sql_type)
|
227
246
|
end
|
247
|
+
|
248
|
+
def warn_quote_duration_deprecated
|
249
|
+
ActiveRecord.deprecator.warn(<<~MSG)
|
250
|
+
Using ActiveSupport::Duration as an interpolated bind parameter in a SQL
|
251
|
+
string template is deprecated. To avoid this warning, you should explicitly
|
252
|
+
convert the duration to a more specific database type. For example, if you
|
253
|
+
want to use a duration as an integer number of seconds:
|
254
|
+
```
|
255
|
+
Record.where("duration = ?", 1.hour.to_i)
|
256
|
+
```
|
257
|
+
If you want to use a duration as an ISO 8601 string:
|
258
|
+
```
|
259
|
+
Record.where("duration = ?", 1.hour.iso8601)
|
260
|
+
```
|
261
|
+
MSG
|
262
|
+
end
|
228
263
|
end
|
229
264
|
end
|
230
265
|
end
|
@@ -2,21 +2,22 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
5
|
+
# = Active Record Connection Adapters \Savepoints
|
5
6
|
module Savepoints
|
6
7
|
def current_savepoint_name
|
7
8
|
current_transaction.savepoint_name
|
8
9
|
end
|
9
10
|
|
10
11
|
def create_savepoint(name = current_savepoint_name)
|
11
|
-
|
12
|
+
internal_execute("SAVEPOINT #{name}", "TRANSACTION")
|
12
13
|
end
|
13
14
|
|
14
15
|
def exec_rollback_to_savepoint(name = current_savepoint_name)
|
15
|
-
|
16
|
+
internal_execute("ROLLBACK TO SAVEPOINT #{name}", "TRANSACTION")
|
16
17
|
end
|
17
18
|
|
18
19
|
def release_savepoint(name = current_savepoint_name)
|
19
|
-
|
20
|
+
internal_execute("RELEASE SAVEPOINT #{name}", "TRANSACTION")
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
@@ -14,8 +14,10 @@ module ActiveRecord
|
|
14
14
|
end
|
15
15
|
|
16
16
|
delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
|
17
|
-
:options_include_default?, :supports_indexes_in_create?, :
|
17
|
+
:options_include_default?, :supports_indexes_in_create?, :use_foreign_keys?,
|
18
18
|
:quoted_columns_for_index, :supports_partial_index?, :supports_check_constraints?,
|
19
|
+
:supports_index_include?, :supports_exclusion_constraints?, :supports_unique_constraints?,
|
20
|
+
:supports_nulls_not_distinct?,
|
19
21
|
to: :@conn, private: true
|
20
22
|
|
21
23
|
private
|
@@ -51,7 +53,7 @@ module ActiveRecord
|
|
51
53
|
statements.concat(o.indexes.map { |column_name, options| index_in_create(o.name, column_name, options) })
|
52
54
|
end
|
53
55
|
|
54
|
-
if
|
56
|
+
if use_foreign_keys?
|
55
57
|
statements.concat(o.foreign_keys.map { |fk| accept fk })
|
56
58
|
end
|
57
59
|
|
@@ -59,6 +61,14 @@ module ActiveRecord
|
|
59
61
|
statements.concat(o.check_constraints.map { |chk| accept chk })
|
60
62
|
end
|
61
63
|
|
64
|
+
if supports_exclusion_constraints?
|
65
|
+
statements.concat(o.exclusion_constraints.map { |exc| accept exc })
|
66
|
+
end
|
67
|
+
|
68
|
+
if supports_unique_constraints?
|
69
|
+
statements.concat(o.unique_constraints.map { |exc| accept exc })
|
70
|
+
end
|
71
|
+
|
62
72
|
create_sql << "(#{statements.join(', ')})" if statements.present?
|
63
73
|
add_table_options!(create_sql, o)
|
64
74
|
create_sql << " AS #{to_sql(o.as)}" if o.as
|
@@ -70,10 +80,12 @@ module ActiveRecord
|
|
70
80
|
end
|
71
81
|
|
72
82
|
def visit_ForeignKeyDefinition(o)
|
83
|
+
quoted_columns = Array(o.column).map { |c| quote_column_name(c) }
|
84
|
+
quoted_primary_keys = Array(o.primary_key).map { |c| quote_column_name(c) }
|
73
85
|
sql = +<<~SQL
|
74
86
|
CONSTRAINT #{quote_column_name(o.name)}
|
75
|
-
FOREIGN KEY (#{
|
76
|
-
REFERENCES #{quote_table_name(o.to_table)} (#{
|
87
|
+
FOREIGN KEY (#{quoted_columns.join(", ")})
|
88
|
+
REFERENCES #{quote_table_name(o.to_table)} (#{quoted_primary_keys.join(", ")})
|
77
89
|
SQL
|
78
90
|
sql << " #{action_sql('DELETE', o.on_delete)}" if o.on_delete
|
79
91
|
sql << " #{action_sql('UPDATE', o.on_update)}" if o.on_update
|
@@ -100,6 +112,8 @@ module ActiveRecord
|
|
100
112
|
sql << "#{quote_column_name(index.name)} ON #{quote_table_name(index.table)}"
|
101
113
|
sql << "USING #{index.using}" if supports_index_using? && index.using
|
102
114
|
sql << "(#{quoted_columns(index)})"
|
115
|
+
sql << "INCLUDE (#{quoted_include_columns(index.include)})" if supports_index_include? && index.include
|
116
|
+
sql << "NULLS NOT DISTINCT" if supports_nulls_not_distinct? && index.nulls_not_distinct
|
103
117
|
sql << "WHERE #{index.where}" if supports_partial_index? && index.where
|
104
118
|
|
105
119
|
sql.join(" ")
|