activerecord 8.0.0 → 8.1.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 +1381 -241
- data/README.rdoc +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +6 -4
- data/lib/active_record/associations/association.rb +35 -17
- data/lib/active_record/associations/association_scope.rb +1 -1
- data/lib/active_record/associations/belongs_to_association.rb +20 -4
- data/lib/active_record/associations/builder/association.rb +16 -5
- data/lib/active_record/associations/builder/belongs_to.rb +36 -8
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +9 -5
- data/lib/active_record/associations/collection_proxy.rb +26 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/foreign_association.rb +3 -1
- data/lib/active_record/associations/has_one_association.rb +1 -0
- data/lib/active_record/associations/join_dependency/join_association.rb +25 -27
- data/lib/active_record/associations/join_dependency.rb +5 -4
- data/lib/active_record/associations/preloader/association.rb +1 -1
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations.rb +159 -21
- data/lib/active_record/attribute_methods/primary_key.rb +2 -1
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +19 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +10 -2
- data/lib/active_record/attribute_methods.rb +24 -17
- data/lib/active_record/attributes.rb +40 -26
- data/lib/active_record/autosave_association.rb +22 -12
- data/lib/active_record/base.rb +3 -4
- data/lib/active_record/callbacks.rb +1 -2
- data/lib/active_record/coders/column_serializer.rb +1 -1
- data/lib/active_record/coders/json.rb +16 -6
- data/lib/active_record/coders/yaml_column.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +19 -18
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +68 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +474 -112
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +68 -41
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +36 -9
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -24
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +31 -35
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +94 -28
- data/lib/active_record/connection_adapters/abstract/transaction.rb +25 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +166 -64
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +133 -40
- data/lib/active_record/connection_adapters/column.rb +14 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +7 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +42 -5
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +40 -25
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +66 -15
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +9 -3
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +29 -33
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +46 -3
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +8 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -33
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +70 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +99 -54
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +40 -12
- data/lib/active_record/connection_adapters/sqlite3/column.rb +8 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +39 -23
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +15 -3
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +7 -14
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +68 -37
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +8 -3
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +16 -2
- data/lib/active_record/connection_adapters.rb +1 -0
- data/lib/active_record/connection_handling.rb +15 -10
- data/lib/active_record/core.rb +44 -12
- data/lib/active_record/counter_cache.rb +36 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
- data/lib/active_record/database_configurations/database_config.rb +5 -1
- data/lib/active_record/database_configurations/hash_config.rb +66 -9
- data/lib/active_record/database_configurations/url_config.rb +15 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +19 -19
- data/lib/active_record/disable_joins_association_relation.rb +5 -1
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/encryptable_record.rb +5 -5
- data/lib/active_record/encryption/encrypted_attribute_type.rb +2 -2
- data/lib/active_record/encryption/encrypted_fixtures.rb +12 -7
- data/lib/active_record/encryption/encryptor.rb +39 -25
- data/lib/active_record/encryption/scheme.rb +1 -1
- data/lib/active_record/enum.rb +37 -20
- data/lib/active_record/errors.rb +23 -7
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -2
- data/lib/active_record/filter_attribute_handler.rb +76 -0
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +2 -2
- data/lib/active_record/future_result.rb +5 -3
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +9 -4
- data/lib/active_record/insert_all.rb +14 -9
- data/lib/active_record/locking/optimistic.rb +7 -0
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +30 -22
- data/lib/active_record/message_pack.rb +13 -0
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +32 -6
- data/lib/active_record/migration/compatibility.rb +34 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +31 -21
- data/lib/active_record/model_schema.rb +38 -12
- data/lib/active_record/nested_attributes.rb +10 -6
- data/lib/active_record/persistence.rb +35 -3
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +7 -7
- data/lib/active_record/querying.rb +17 -5
- data/lib/active_record/railtie.rb +35 -6
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +24 -20
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +36 -1
- data/lib/active_record/relation/batches.rb +25 -11
- data/lib/active_record/relation/calculations.rb +62 -41
- data/lib/active_record/relation/delegation.rb +0 -1
- data/lib/active_record/relation/finder_methods.rb +76 -45
- data/lib/active_record/relation/merger.rb +4 -2
- data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +7 -7
- data/lib/active_record/relation/predicate_builder.rb +10 -8
- data/lib/active_record/relation/query_attribute.rb +4 -2
- data/lib/active_record/relation/query_methods.rb +106 -45
- data/lib/active_record/relation/spawn_methods.rb +6 -6
- data/lib/active_record/relation/where_clause.rb +10 -11
- data/lib/active_record/relation.rb +63 -31
- data/lib/active_record/result.rb +44 -21
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +2 -0
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +41 -21
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +48 -19
- data/lib/active_record/statement_cache.rb +16 -12
- data/lib/active_record/store.rb +46 -19
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +5 -20
- data/lib/active_record/tasks/abstract_tasks.rb +83 -0
- data/lib/active_record/tasks/database_tasks.rb +44 -45
- data/lib/active_record/tasks/mysql_database_tasks.rb +4 -56
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -26
- data/lib/active_record/test_databases.rb +18 -4
- data/lib/active_record/test_fixtures.rb +40 -6
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +58 -32
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +13 -2
- data/lib/active_record/type/serialized.rb +16 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record.rb +72 -7
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/collectors/bind.rb +1 -1
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/crud.rb +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/predications.rb +1 -3
- data/lib/arel/select_manager.rb +13 -4
- data/lib/arel/update_manager.rb +5 -0
- data/lib/arel/visitors/dot.rb +2 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +7 -23
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +16 -15
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
|
@@ -60,7 +60,7 @@ module ActiveRecord
|
|
|
60
60
|
:reverse_order, :distinct, :create_with, :skip_query_cache]
|
|
61
61
|
|
|
62
62
|
CLAUSE_METHODS = [:where, :having, :from]
|
|
63
|
-
|
|
63
|
+
INVALID_METHODS_FOR_UPDATE_AND_DELETE_ALL = [:distinct, :with, :with_recursive]
|
|
64
64
|
|
|
65
65
|
VALUE_METHODS = MULTI_VALUE_METHODS + SINGLE_VALUE_METHODS + CLAUSE_METHODS
|
|
66
66
|
|
|
@@ -272,10 +272,15 @@ module ActiveRecord
|
|
|
272
272
|
# such situation.
|
|
273
273
|
def create_or_find_by(attributes, &block)
|
|
274
274
|
with_connection do |connection|
|
|
275
|
-
|
|
275
|
+
record = nil
|
|
276
|
+
transaction(requires_new: true) do
|
|
277
|
+
record = create(attributes, &block)
|
|
278
|
+
record._last_transaction_return_status || raise(ActiveRecord::Rollback)
|
|
279
|
+
end
|
|
280
|
+
record
|
|
276
281
|
rescue ActiveRecord::RecordNotUnique
|
|
277
282
|
if connection.transaction_open?
|
|
278
|
-
|
|
283
|
+
rewhere(attributes).lock(connection.create_or_find_by_lock).take!
|
|
279
284
|
else
|
|
280
285
|
find_by!(attributes)
|
|
281
286
|
end
|
|
@@ -287,17 +292,22 @@ module ActiveRecord
|
|
|
287
292
|
# is raised if the created record is invalid.
|
|
288
293
|
def create_or_find_by!(attributes, &block)
|
|
289
294
|
with_connection do |connection|
|
|
290
|
-
|
|
295
|
+
record = nil
|
|
296
|
+
transaction(requires_new: true) do
|
|
297
|
+
record = create!(attributes, &block)
|
|
298
|
+
record._last_transaction_return_status || raise(ActiveRecord::Rollback)
|
|
299
|
+
end
|
|
300
|
+
record
|
|
291
301
|
rescue ActiveRecord::RecordNotUnique
|
|
292
302
|
if connection.transaction_open?
|
|
293
|
-
|
|
303
|
+
rewhere(attributes).lock(connection.create_or_find_by_lock).take!
|
|
294
304
|
else
|
|
295
305
|
find_by!(attributes)
|
|
296
306
|
end
|
|
297
307
|
end
|
|
298
308
|
end
|
|
299
309
|
|
|
300
|
-
# Like #find_or_create_by, but calls {new}[rdoc-ref:Core
|
|
310
|
+
# Like #find_or_create_by, but calls {new}[rdoc-ref:Core.new]
|
|
301
311
|
# instead of {create}[rdoc-ref:Persistence::ClassMethods#create].
|
|
302
312
|
def find_or_initialize_by(attributes, &block)
|
|
303
313
|
find_by(attributes) || new(attributes, &block)
|
|
@@ -371,10 +381,11 @@ module ActiveRecord
|
|
|
371
381
|
|
|
372
382
|
# Returns true if there are no records.
|
|
373
383
|
#
|
|
374
|
-
# When
|
|
375
|
-
#
|
|
384
|
+
# When an argument is given, returns true if no records match the argument
|
|
385
|
+
# via the case-equality operator (<tt>===</tt>).
|
|
376
386
|
#
|
|
377
|
-
# posts.none?(
|
|
387
|
+
# posts.none?(Post) # => true if posts is empty
|
|
388
|
+
# posts.none?(Comment) # => true
|
|
378
389
|
def none?(*args)
|
|
379
390
|
return true if @none
|
|
380
391
|
|
|
@@ -384,10 +395,12 @@ module ActiveRecord
|
|
|
384
395
|
|
|
385
396
|
# Returns true if there are any records.
|
|
386
397
|
#
|
|
387
|
-
# When a pattern argument is given, this method checks whether elements in
|
|
388
|
-
# the Enumerable match the pattern via the case-equality operator (<tt>===</tt>).
|
|
389
398
|
#
|
|
390
|
-
#
|
|
399
|
+
# When an argument is given, returns true if at least one records matches
|
|
400
|
+
# the argument via the case-equality operator (<tt>===</tt>).
|
|
401
|
+
#
|
|
402
|
+
# posts.any?(Post) # => true if at least one record
|
|
403
|
+
# posts.any?(Comment) # => false
|
|
391
404
|
def any?(*args)
|
|
392
405
|
return false if @none
|
|
393
406
|
|
|
@@ -397,10 +410,11 @@ module ActiveRecord
|
|
|
397
410
|
|
|
398
411
|
# Returns true if there is exactly one record.
|
|
399
412
|
#
|
|
400
|
-
# When
|
|
401
|
-
#
|
|
413
|
+
# When an argument is given, returns true if exactly one records matches the
|
|
414
|
+
# argument via the case-equality operator (<tt>===</tt>).
|
|
402
415
|
#
|
|
403
|
-
# posts.one?(Post) # => true
|
|
416
|
+
# posts.one?(Post) # => true if exactly one record
|
|
417
|
+
# posts.any?(Comment) # => false
|
|
404
418
|
def one?(*args)
|
|
405
419
|
return false if @none
|
|
406
420
|
|
|
@@ -475,7 +489,7 @@ module ActiveRecord
|
|
|
475
489
|
if loaded?
|
|
476
490
|
size = records.size
|
|
477
491
|
if size > 0
|
|
478
|
-
timestamp = records.
|
|
492
|
+
timestamp = records.filter_map { |record| record.read_attribute(timestamp_column) }.max
|
|
479
493
|
end
|
|
480
494
|
else
|
|
481
495
|
collection = eager_loading? ? apply_join_dependency : self
|
|
@@ -590,6 +604,18 @@ module ActiveRecord
|
|
|
590
604
|
|
|
591
605
|
return 0 if @none
|
|
592
606
|
|
|
607
|
+
invalid_methods = INVALID_METHODS_FOR_UPDATE_AND_DELETE_ALL.select do |method|
|
|
608
|
+
value = @values[method]
|
|
609
|
+
method == :distinct ? value : value&.any?
|
|
610
|
+
end
|
|
611
|
+
if invalid_methods.any?
|
|
612
|
+
ActiveRecord.deprecator.warn <<~MESSAGE
|
|
613
|
+
`#{invalid_methods.join(', ')}` is not supported by `update_all` and was never included in the generated query.
|
|
614
|
+
|
|
615
|
+
Calling `#{invalid_methods.join(', ')}` with `update_all` will raise an error in Rails 8.2.
|
|
616
|
+
MESSAGE
|
|
617
|
+
end
|
|
618
|
+
|
|
593
619
|
if updates.is_a?(Hash)
|
|
594
620
|
if model.locking_enabled? &&
|
|
595
621
|
!updates.key?(model.locking_column) &&
|
|
@@ -603,17 +629,15 @@ module ActiveRecord
|
|
|
603
629
|
end
|
|
604
630
|
|
|
605
631
|
model.with_connection do |c|
|
|
606
|
-
arel = eager_loading? ? apply_join_dependency.arel :
|
|
632
|
+
arel = eager_loading? ? apply_join_dependency.arel : arel()
|
|
607
633
|
arel.source.left = table
|
|
608
634
|
|
|
609
|
-
group_values_arel_columns = arel_columns(group_values.uniq)
|
|
610
|
-
having_clause_ast = having_clause.ast unless having_clause.empty?
|
|
611
635
|
key = if model.composite_primary_key?
|
|
612
636
|
primary_key.map { |pk| table[pk] }
|
|
613
637
|
else
|
|
614
638
|
table[primary_key]
|
|
615
639
|
end
|
|
616
|
-
stmt = arel.compile_update(values, key
|
|
640
|
+
stmt = arel.compile_update(values, key)
|
|
617
641
|
c.update(stmt, "#{model} Update All").tap { reset }
|
|
618
642
|
end
|
|
619
643
|
end
|
|
@@ -820,7 +844,7 @@ module ActiveRecord
|
|
|
820
844
|
#
|
|
821
845
|
# [:returning]
|
|
822
846
|
# (PostgreSQL, SQLite3, and MariaDB only) An array of attributes to return for all successfully
|
|
823
|
-
#
|
|
847
|
+
# upserted records, which by default is the primary key.
|
|
824
848
|
# Pass <tt>returning: %w[ id name ]</tt> for both id and name
|
|
825
849
|
# or <tt>returning: false</tt> to omit the underlying <tt>RETURNING</tt> SQL
|
|
826
850
|
# clause entirely.
|
|
@@ -849,7 +873,9 @@ module ActiveRecord
|
|
|
849
873
|
# Active Record's schema_cache.
|
|
850
874
|
#
|
|
851
875
|
# [:on_duplicate]
|
|
852
|
-
# Configure the
|
|
876
|
+
# Configure the behavior that will be used in case of conflict. Use `:skip`
|
|
877
|
+
# to ignore any conflicts or provide a safe SQL fragment wrapped with
|
|
878
|
+
# `Arel.sql`.
|
|
853
879
|
#
|
|
854
880
|
# NOTE: If you use this option you must provide all the columns you want to update
|
|
855
881
|
# by yourself.
|
|
@@ -949,7 +975,7 @@ module ActiveRecord
|
|
|
949
975
|
# If attribute names are passed, they are updated along with +updated_at+/+updated_on+ attributes.
|
|
950
976
|
# If no time argument is passed, the current time is used as default.
|
|
951
977
|
#
|
|
952
|
-
#
|
|
978
|
+
# ==== Examples
|
|
953
979
|
#
|
|
954
980
|
# # Touch all records
|
|
955
981
|
# Person.all.touch_all
|
|
@@ -1000,7 +1026,7 @@ module ActiveRecord
|
|
|
1000
1026
|
#
|
|
1001
1027
|
# Post.where(person_id: 5).where(category: ['Something', 'Else']).delete_all
|
|
1002
1028
|
#
|
|
1003
|
-
#
|
|
1029
|
+
# This call deletes the affected posts all at once with a single DELETE statement.
|
|
1004
1030
|
# If you need to destroy dependent associations or call your <tt>before_*</tt> or
|
|
1005
1031
|
# +after_destroy+ callbacks, use the #destroy_all method instead.
|
|
1006
1032
|
#
|
|
@@ -1011,7 +1037,7 @@ module ActiveRecord
|
|
|
1011
1037
|
def delete_all
|
|
1012
1038
|
return 0 if @none
|
|
1013
1039
|
|
|
1014
|
-
invalid_methods =
|
|
1040
|
+
invalid_methods = INVALID_METHODS_FOR_UPDATE_AND_DELETE_ALL.select do |method|
|
|
1015
1041
|
value = @values[method]
|
|
1016
1042
|
method == :distinct ? value : value&.any?
|
|
1017
1043
|
end
|
|
@@ -1020,17 +1046,15 @@ module ActiveRecord
|
|
|
1020
1046
|
end
|
|
1021
1047
|
|
|
1022
1048
|
model.with_connection do |c|
|
|
1023
|
-
arel = eager_loading? ? apply_join_dependency.arel :
|
|
1049
|
+
arel = eager_loading? ? apply_join_dependency.arel : arel()
|
|
1024
1050
|
arel.source.left = table
|
|
1025
1051
|
|
|
1026
|
-
group_values_arel_columns = arel_columns(group_values.uniq)
|
|
1027
|
-
having_clause_ast = having_clause.ast unless having_clause.empty?
|
|
1028
1052
|
key = if model.composite_primary_key?
|
|
1029
1053
|
primary_key.map { |pk| table[pk] }
|
|
1030
1054
|
else
|
|
1031
1055
|
table[primary_key]
|
|
1032
1056
|
end
|
|
1033
|
-
stmt = arel.compile_delete(key
|
|
1057
|
+
stmt = arel.compile_delete(key)
|
|
1034
1058
|
|
|
1035
1059
|
c.delete(stmt, "#{model} Delete All").tap { reset }
|
|
1036
1060
|
end
|
|
@@ -1057,6 +1081,10 @@ module ActiveRecord
|
|
|
1057
1081
|
def delete(id_or_array)
|
|
1058
1082
|
return 0 if id_or_array.nil? || (id_or_array.is_a?(Array) && id_or_array.empty?)
|
|
1059
1083
|
|
|
1084
|
+
if model.composite_primary_key? && !id_or_array.first.is_a?(Array)
|
|
1085
|
+
id_or_array = [id_or_array]
|
|
1086
|
+
end
|
|
1087
|
+
|
|
1060
1088
|
where(model.primary_key => id_or_array).delete_all
|
|
1061
1089
|
end
|
|
1062
1090
|
|
|
@@ -1395,12 +1423,16 @@ module ActiveRecord
|
|
|
1395
1423
|
|
|
1396
1424
|
def _increment_attribute(attribute, value = 1)
|
|
1397
1425
|
bind = predicate_builder.build_bind_attribute(attribute.name, value.abs)
|
|
1398
|
-
expr = table.coalesce(
|
|
1426
|
+
expr = table.coalesce(attribute, 0)
|
|
1399
1427
|
expr = value < 0 ? expr - bind : expr + bind
|
|
1400
1428
|
expr.expr
|
|
1401
1429
|
end
|
|
1402
1430
|
|
|
1403
1431
|
def exec_queries(&block)
|
|
1432
|
+
if lock_value && model.current_preventing_writes
|
|
1433
|
+
raise ActiveRecord::ReadOnlyError, "Lock query attempted while in readonly mode"
|
|
1434
|
+
end
|
|
1435
|
+
|
|
1404
1436
|
skip_query_cache_if_necessary do
|
|
1405
1437
|
rows = if scheduled?
|
|
1406
1438
|
future = @future_result
|
|
@@ -1440,7 +1472,7 @@ module ActiveRecord
|
|
|
1440
1472
|
else
|
|
1441
1473
|
relation = join_dependency.apply_column_aliases(relation)
|
|
1442
1474
|
@_join_dependency = join_dependency
|
|
1443
|
-
c.select_all(relation.arel, "
|
|
1475
|
+
c.select_all(relation.arel, "#{model.name} Eager Load", async: async)
|
|
1444
1476
|
end
|
|
1445
1477
|
end
|
|
1446
1478
|
end
|
data/lib/active_record/result.rb
CHANGED
|
@@ -29,6 +29,11 @@ module ActiveRecord
|
|
|
29
29
|
# ...
|
|
30
30
|
# ]
|
|
31
31
|
#
|
|
32
|
+
# # Get the number of rows affected by the query:
|
|
33
|
+
# result = ActiveRecord::Base.lease_connection.exec_query('INSERT INTO posts (title, body) VALUES ("title_3", "body_3"), ("title_4", "body_4")')
|
|
34
|
+
# result.affected_rows
|
|
35
|
+
# # => 2
|
|
36
|
+
#
|
|
32
37
|
# # ActiveRecord::Result also includes Enumerable.
|
|
33
38
|
# result.each do |row|
|
|
34
39
|
# puts row['title'] + " " + row['body']
|
|
@@ -89,24 +94,26 @@ module ActiveRecord
|
|
|
89
94
|
alias_method :to_hash, :to_h
|
|
90
95
|
end
|
|
91
96
|
|
|
92
|
-
attr_reader :columns, :rows, :
|
|
97
|
+
attr_reader :columns, :rows, :affected_rows
|
|
93
98
|
|
|
94
|
-
def self.empty(async: false) # :nodoc:
|
|
99
|
+
def self.empty(async: false, affected_rows: nil) # :nodoc:
|
|
95
100
|
if async
|
|
96
|
-
|
|
101
|
+
FutureResult.wrap(new(EMPTY_ARRAY, EMPTY_ARRAY, EMPTY_HASH, affected_rows: affected_rows)).freeze
|
|
97
102
|
else
|
|
98
|
-
|
|
103
|
+
new(EMPTY_ARRAY, EMPTY_ARRAY, EMPTY_HASH, affected_rows: affected_rows).freeze
|
|
99
104
|
end
|
|
100
105
|
end
|
|
101
106
|
|
|
102
|
-
def initialize(columns, rows, column_types = nil)
|
|
107
|
+
def initialize(columns, rows, column_types = nil, affected_rows: nil)
|
|
103
108
|
# We freeze the strings to prevent them getting duped when
|
|
104
109
|
# used as keys in ActiveRecord::Base's @attributes hash
|
|
105
110
|
@columns = columns.each(&:-@).freeze
|
|
106
111
|
@rows = rows
|
|
107
112
|
@hash_rows = nil
|
|
108
|
-
@column_types = column_types
|
|
113
|
+
@column_types = column_types.freeze
|
|
114
|
+
@types_hash = nil
|
|
109
115
|
@column_indexes = nil
|
|
116
|
+
@affected_rows = affected_rows
|
|
110
117
|
end
|
|
111
118
|
|
|
112
119
|
# Returns true if this result set includes the column named +name+
|
|
@@ -154,6 +161,24 @@ module ActiveRecord
|
|
|
154
161
|
n ? hash_rows.last(n) : hash_rows.last
|
|
155
162
|
end
|
|
156
163
|
|
|
164
|
+
# Returns the +ActiveRecord::Type+ type of all columns.
|
|
165
|
+
# Note that not all database adapters return the result types,
|
|
166
|
+
# so the hash may be empty.
|
|
167
|
+
def column_types
|
|
168
|
+
if @column_types
|
|
169
|
+
@types_hash ||= begin
|
|
170
|
+
types = {}
|
|
171
|
+
@columns.each_with_index do |name, index|
|
|
172
|
+
type = @column_types[index] || Type.default_value
|
|
173
|
+
types[name] = types[index] = type
|
|
174
|
+
end
|
|
175
|
+
types.freeze
|
|
176
|
+
end
|
|
177
|
+
else
|
|
178
|
+
EMPTY_HASH
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
157
182
|
def result # :nodoc:
|
|
158
183
|
self
|
|
159
184
|
end
|
|
@@ -162,7 +187,7 @@ module ActiveRecord
|
|
|
162
187
|
self
|
|
163
188
|
end
|
|
164
189
|
|
|
165
|
-
def cast_values(type_overrides =
|
|
190
|
+
def cast_values(type_overrides = nil) # :nodoc:
|
|
166
191
|
if columns.one?
|
|
167
192
|
# Separated to avoid allocating an array per row
|
|
168
193
|
|
|
@@ -190,13 +215,13 @@ module ActiveRecord
|
|
|
190
215
|
|
|
191
216
|
def initialize_copy(other)
|
|
192
217
|
@rows = rows.dup
|
|
193
|
-
@column_types = column_types.dup
|
|
194
218
|
@hash_rows = nil
|
|
195
219
|
end
|
|
196
220
|
|
|
197
221
|
def freeze # :nodoc:
|
|
198
222
|
hash_rows.freeze
|
|
199
|
-
indexed_rows
|
|
223
|
+
indexed_rows
|
|
224
|
+
column_types
|
|
200
225
|
super
|
|
201
226
|
end
|
|
202
227
|
|
|
@@ -204,7 +229,7 @@ module ActiveRecord
|
|
|
204
229
|
@column_indexes ||= begin
|
|
205
230
|
index = 0
|
|
206
231
|
hash = {}
|
|
207
|
-
length
|
|
232
|
+
length = columns.length
|
|
208
233
|
while index < length
|
|
209
234
|
hash[columns[index]] = index
|
|
210
235
|
index += 1
|
|
@@ -222,10 +247,14 @@ module ActiveRecord
|
|
|
222
247
|
|
|
223
248
|
private
|
|
224
249
|
def column_type(name, index, type_overrides)
|
|
225
|
-
type_overrides
|
|
226
|
-
|
|
227
|
-
|
|
250
|
+
if type_overrides
|
|
251
|
+
type_overrides.fetch(name) do
|
|
252
|
+
column_type(name, index, nil)
|
|
228
253
|
end
|
|
254
|
+
elsif @column_types
|
|
255
|
+
@column_types[index] || Type.default_value
|
|
256
|
+
else
|
|
257
|
+
Type.default_value
|
|
229
258
|
end
|
|
230
259
|
end
|
|
231
260
|
|
|
@@ -237,14 +266,8 @@ module ActiveRecord
|
|
|
237
266
|
end
|
|
238
267
|
end
|
|
239
268
|
|
|
240
|
-
|
|
269
|
+
EMPTY_ARRAY = [].freeze
|
|
241
270
|
EMPTY_HASH = {}.freeze
|
|
242
|
-
private_constant :EMPTY_HASH
|
|
243
|
-
|
|
244
|
-
EMPTY = new(empty_array, empty_array, EMPTY_HASH).freeze
|
|
245
|
-
private_constant :EMPTY
|
|
246
|
-
|
|
247
|
-
EMPTY_ASYNC = FutureResult.wrap(EMPTY).freeze
|
|
248
|
-
private_constant :EMPTY_ASYNC
|
|
271
|
+
private_constant :EMPTY_ARRAY, :EMPTY_HASH
|
|
249
272
|
end
|
|
250
273
|
end
|
|
@@ -3,80 +3,64 @@
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
# This is a thread locals registry for Active Record. For example:
|
|
5
5
|
#
|
|
6
|
-
# ActiveRecord::RuntimeRegistry.sql_runtime
|
|
6
|
+
# ActiveRecord::RuntimeRegistry.stats.sql_runtime
|
|
7
7
|
#
|
|
8
8
|
# returns the connection handler local to the current unit of execution (either thread of fiber).
|
|
9
9
|
module RuntimeRegistry # :nodoc:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
class Stats
|
|
11
|
+
attr_accessor :sql_runtime, :async_sql_runtime, :queries_count, :cached_queries_count
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
@sql_runtime = 0.0
|
|
15
|
+
@async_sql_runtime = 0.0
|
|
16
|
+
@queries_count = 0
|
|
17
|
+
@cached_queries_count = 0
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def reset_runtimes
|
|
21
|
+
sql_runtime_was = @sql_runtime
|
|
22
|
+
@sql_runtime = 0.0
|
|
23
|
+
@async_sql_runtime = 0.0
|
|
24
|
+
sql_runtime_was
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
public alias_method :reset, :initialize
|
|
14
28
|
end
|
|
15
29
|
|
|
16
|
-
|
|
17
|
-
ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime] = runtime
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def async_sql_runtime
|
|
21
|
-
ActiveSupport::IsolatedExecutionState[:active_record_async_sql_runtime] ||= 0.0
|
|
22
|
-
end
|
|
30
|
+
extend self
|
|
23
31
|
|
|
24
|
-
def
|
|
25
|
-
|
|
32
|
+
def call(name, start, finish, id, payload)
|
|
33
|
+
record(
|
|
34
|
+
payload[:name],
|
|
35
|
+
(finish - start) * 1_000.0,
|
|
36
|
+
cached: payload[:cached],
|
|
37
|
+
async: payload[:async],
|
|
38
|
+
lock_wait: payload[:lock_wait],
|
|
39
|
+
)
|
|
26
40
|
end
|
|
27
41
|
|
|
28
|
-
def
|
|
29
|
-
|
|
30
|
-
end
|
|
42
|
+
def record(query_name, runtime, cached: false, async: false, lock_wait: nil)
|
|
43
|
+
stats = self.stats
|
|
31
44
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
45
|
+
unless query_name == "TRANSACTION" || query_name == "SCHEMA"
|
|
46
|
+
stats.queries_count += 1
|
|
47
|
+
stats.cached_queries_count += 1 if cached
|
|
48
|
+
end
|
|
35
49
|
|
|
36
|
-
|
|
37
|
-
|
|
50
|
+
if async
|
|
51
|
+
stats.async_sql_runtime += (runtime - lock_wait)
|
|
52
|
+
end
|
|
53
|
+
stats.sql_runtime += runtime
|
|
38
54
|
end
|
|
39
55
|
|
|
40
|
-
def
|
|
41
|
-
ActiveSupport::IsolatedExecutionState[:
|
|
56
|
+
def stats
|
|
57
|
+
ActiveSupport::IsolatedExecutionState[:active_record_runtime] ||= Stats.new
|
|
42
58
|
end
|
|
43
59
|
|
|
44
60
|
def reset
|
|
45
|
-
|
|
46
|
-
reset_queries_count
|
|
47
|
-
reset_cached_queries_count
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def reset_runtimes
|
|
51
|
-
rt, self.sql_runtime = sql_runtime, 0.0
|
|
52
|
-
self.async_sql_runtime = 0.0
|
|
53
|
-
rt
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def reset_queries_count
|
|
57
|
-
qc = queries_count
|
|
58
|
-
self.queries_count = 0
|
|
59
|
-
qc
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def reset_cached_queries_count
|
|
63
|
-
qc = cached_queries_count
|
|
64
|
-
self.cached_queries_count = 0
|
|
65
|
-
qc
|
|
61
|
+
stats.reset
|
|
66
62
|
end
|
|
67
63
|
end
|
|
68
64
|
end
|
|
69
65
|
|
|
70
|
-
ActiveSupport::Notifications.monotonic_subscribe("sql.active_record"
|
|
71
|
-
unless ["SCHEMA", "TRANSACTION"].include?(payload[:name])
|
|
72
|
-
ActiveRecord::RuntimeRegistry.queries_count += 1
|
|
73
|
-
ActiveRecord::RuntimeRegistry.cached_queries_count += 1 if payload[:cached]
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
runtime = (finish - start) * 1_000.0
|
|
77
|
-
|
|
78
|
-
if payload[:async]
|
|
79
|
-
ActiveRecord::RuntimeRegistry.async_sql_runtime += (runtime - payload[:lock_wait])
|
|
80
|
-
end
|
|
81
|
-
ActiveRecord::RuntimeRegistry.sql_runtime += runtime
|
|
82
|
-
end
|
|
66
|
+
ActiveSupport::Notifications.monotonic_subscribe("sql.active_record", ActiveRecord::RuntimeRegistry)
|
|
@@ -161,6 +161,8 @@ module ActiveRecord
|
|
|
161
161
|
#
|
|
162
162
|
# sanitize_sql_array(["role = ?", 0])
|
|
163
163
|
# # => "role = '0'"
|
|
164
|
+
#
|
|
165
|
+
# Before using this method, please consider if Arel.sql would be better for your use-case
|
|
164
166
|
def sanitize_sql_array(ary)
|
|
165
167
|
statement, *values = ary
|
|
166
168
|
if values.first.is_a?(Hash) && /:\w+/.match?(statement)
|
data/lib/active_record/schema.rb
CHANGED
|
@@ -165,7 +165,7 @@ module ActiveRecord
|
|
|
165
165
|
# first dump primary key column
|
|
166
166
|
pk = @connection.primary_key(table)
|
|
167
167
|
|
|
168
|
-
tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}"
|
|
168
|
+
tbl.print " create_table #{relation_name(remove_prefix_and_suffix(table)).inspect}"
|
|
169
169
|
|
|
170
170
|
case pk
|
|
171
171
|
when String
|
|
@@ -207,12 +207,17 @@ module ActiveRecord
|
|
|
207
207
|
end
|
|
208
208
|
|
|
209
209
|
indexes_in_create(table, tbl)
|
|
210
|
-
check_constraints_in_create(table, tbl) if @connection.supports_check_constraints?
|
|
210
|
+
remaining = check_constraints_in_create(table, tbl) if @connection.supports_check_constraints?
|
|
211
211
|
exclusion_constraints_in_create(table, tbl) if @connection.supports_exclusion_constraints?
|
|
212
212
|
unique_constraints_in_create(table, tbl) if @connection.supports_unique_constraints?
|
|
213
213
|
|
|
214
214
|
tbl.puts " end"
|
|
215
215
|
|
|
216
|
+
if remaining
|
|
217
|
+
tbl.puts
|
|
218
|
+
tbl.print remaining.string
|
|
219
|
+
end
|
|
220
|
+
|
|
216
221
|
stream.print tbl.string
|
|
217
222
|
rescue => e
|
|
218
223
|
stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
|
|
@@ -227,8 +232,8 @@ module ActiveRecord
|
|
|
227
232
|
def indexes(table, stream)
|
|
228
233
|
if (indexes = @connection.indexes(table)).any?
|
|
229
234
|
add_index_statements = indexes.map do |index|
|
|
230
|
-
table_name = remove_prefix_and_suffix(index.table)
|
|
231
|
-
" add_index #{([table_name] + index_parts(index)).join(', ')}"
|
|
235
|
+
table_name = remove_prefix_and_suffix(index.table)
|
|
236
|
+
" add_index #{([relation_name(table_name).inspect] + index_parts(index)).join(', ')}"
|
|
232
237
|
end
|
|
233
238
|
|
|
234
239
|
stream.puts add_index_statements.sort.join("\n")
|
|
@@ -272,35 +277,49 @@ module ActiveRecord
|
|
|
272
277
|
index_parts << "nulls_not_distinct: #{index.nulls_not_distinct.inspect}" if index.nulls_not_distinct
|
|
273
278
|
index_parts << "type: #{index.type.inspect}" if index.type
|
|
274
279
|
index_parts << "comment: #{index.comment.inspect}" if index.comment
|
|
280
|
+
index_parts << "enabled: #{index.enabled.inspect}" if @connection.supports_disabling_indexes? && index.disabled?
|
|
275
281
|
index_parts
|
|
276
282
|
end
|
|
277
283
|
|
|
278
284
|
def check_constraints_in_create(table, stream)
|
|
279
285
|
if (check_constraints = @connection.check_constraints(table)).any?
|
|
280
|
-
|
|
281
|
-
parts = [
|
|
282
|
-
"t.check_constraint #{check_constraint.expression.inspect}"
|
|
283
|
-
]
|
|
286
|
+
check_valid, check_invalid = check_constraints.partition { |chk| chk.validate? }
|
|
284
287
|
|
|
285
|
-
|
|
286
|
-
|
|
288
|
+
unless check_valid.empty?
|
|
289
|
+
check_constraint_statements = check_valid.map do |check|
|
|
290
|
+
" t.check_constraint #{check_parts(check).join(', ')}"
|
|
287
291
|
end
|
|
288
292
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
" #{parts.join(', ')}"
|
|
293
|
+
stream.puts check_constraint_statements.sort.join("\n")
|
|
292
294
|
end
|
|
293
295
|
|
|
294
|
-
|
|
296
|
+
unless check_invalid.empty?
|
|
297
|
+
remaining = StringIO.new
|
|
298
|
+
table_name = remove_prefix_and_suffix(table).inspect
|
|
299
|
+
|
|
300
|
+
add_check_constraint_statements = check_invalid.map do |check|
|
|
301
|
+
" add_check_constraint #{([table_name] + check_parts(check)).join(', ')}"
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
remaining.puts add_check_constraint_statements.sort.join("\n")
|
|
305
|
+
remaining
|
|
306
|
+
end
|
|
295
307
|
end
|
|
296
308
|
end
|
|
297
309
|
|
|
310
|
+
def check_parts(check)
|
|
311
|
+
check_parts = [ check.expression.inspect ]
|
|
312
|
+
check_parts << "name: #{check.name.inspect}" if check.export_name_on_schema_dump?
|
|
313
|
+
check_parts << "validate: #{check.validate?.inspect}" unless check.validate?
|
|
314
|
+
check_parts
|
|
315
|
+
end
|
|
316
|
+
|
|
298
317
|
def foreign_keys(table, stream)
|
|
299
318
|
if (foreign_keys = @connection.foreign_keys(table)).any?
|
|
300
319
|
add_foreign_key_statements = foreign_keys.map do |foreign_key|
|
|
301
320
|
parts = [
|
|
302
|
-
|
|
303
|
-
remove_prefix_and_suffix(foreign_key.to_table).inspect,
|
|
321
|
+
relation_name(remove_prefix_and_suffix(foreign_key.from_table)).inspect,
|
|
322
|
+
relation_name(remove_prefix_and_suffix(foreign_key.to_table)).inspect,
|
|
304
323
|
]
|
|
305
324
|
|
|
306
325
|
if foreign_key.column != @connection.foreign_key_column_for(foreign_key.to_table, "id")
|
|
@@ -311,16 +330,13 @@ module ActiveRecord
|
|
|
311
330
|
parts << "primary_key: #{foreign_key.primary_key.inspect}"
|
|
312
331
|
end
|
|
313
332
|
|
|
314
|
-
if foreign_key.export_name_on_schema_dump?
|
|
315
|
-
parts << "name: #{foreign_key.name.inspect}"
|
|
316
|
-
end
|
|
317
|
-
|
|
333
|
+
parts << "name: #{foreign_key.name.inspect}" if foreign_key.export_name_on_schema_dump?
|
|
318
334
|
parts << "on_update: #{foreign_key.on_update.inspect}" if foreign_key.on_update
|
|
319
335
|
parts << "on_delete: #{foreign_key.on_delete.inspect}" if foreign_key.on_delete
|
|
320
336
|
parts << "deferrable: #{foreign_key.deferrable.inspect}" if foreign_key.deferrable
|
|
321
337
|
parts << "validate: #{foreign_key.validate?.inspect}" unless foreign_key.validate?
|
|
322
338
|
|
|
323
|
-
" #{parts.join(', ')}"
|
|
339
|
+
" add_foreign_key #{parts.join(', ')}"
|
|
324
340
|
end
|
|
325
341
|
|
|
326
342
|
stream.puts add_foreign_key_statements.sort.join("\n")
|
|
@@ -345,6 +361,10 @@ module ActiveRecord
|
|
|
345
361
|
end
|
|
346
362
|
end
|
|
347
363
|
|
|
364
|
+
def relation_name(name)
|
|
365
|
+
name
|
|
366
|
+
end
|
|
367
|
+
|
|
348
368
|
def remove_prefix_and_suffix(table)
|
|
349
369
|
# This method appears at the top when profiling active_record test cases run.
|
|
350
370
|
# Avoid costly calculation when there are no prefix and suffix.
|
|
@@ -30,13 +30,13 @@ module ActiveRecord
|
|
|
30
30
|
# {validates_uniqueness_of}[rdoc-ref:Validations::ClassMethods#validates_uniqueness_of] can.
|
|
31
31
|
# You're encouraged to add a unique index in the database to deal with this even more unlikely scenario.
|
|
32
32
|
#
|
|
33
|
-
#
|
|
33
|
+
# ==== Options
|
|
34
34
|
#
|
|
35
|
-
# [
|
|
35
|
+
# [+:length+]
|
|
36
36
|
# Length of the Secure Random, with a minimum of 24 characters. It will
|
|
37
37
|
# default to 24.
|
|
38
38
|
#
|
|
39
|
-
# [
|
|
39
|
+
# [+:on+]
|
|
40
40
|
# The callback when the value is generated. When called with <tt>on:
|
|
41
41
|
# :initialize</tt>, the value is generated in an
|
|
42
42
|
# <tt>after_initialize</tt> callback, otherwise the value will be used
|