activerecord 6.1.7 → 7.2.2
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 +616 -1290
- data/MIT-LICENSE +1 -1
- data/README.rdoc +31 -31
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +2 -12
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +60 -21
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +37 -11
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -4
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +41 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +4 -4
- data/lib/active_record/associations/builder/singular_association.rb +6 -2
- data/lib/active_record/associations/collection_association.rb +46 -36
- data/lib/active_record/associations/collection_proxy.rb +44 -16
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +29 -19
- data/lib/active_record/associations/has_many_through_association.rb +19 -8
- data/lib/active_record/associations/has_one_association.rb +20 -10
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
- data/lib/active_record/associations/join_dependency.rb +28 -20
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +212 -53
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +153 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -16
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +15 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +429 -522
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -5
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +73 -22
- data/lib/active_record/attribute_methods/primary_key.rb +47 -27
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +14 -11
- data/lib/active_record/attribute_methods/serialization.rb +174 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +15 -9
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +164 -52
- data/lib/active_record/attributes.rb +57 -54
- data/lib/active_record/autosave_association.rb +74 -57
- data/lib/active_record/base.rb +27 -5
- data/lib/active_record/callbacks.rb +19 -35
- 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 -46
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +325 -604
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -60
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +230 -64
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -131
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +378 -143
- data/lib/active_record/connection_adapters/abstract/transaction.rb +361 -76
- data/lib/active_record/connection_adapters/abstract_adapter.rb +624 -163
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +348 -165
- data/lib/active_record/connection_adapters/column.rb +13 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -130
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -55
- 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 +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +45 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +107 -68
- data/lib/active_record/connection_adapters/pool_config.rb +26 -16
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +114 -54
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/interval.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 +12 -3
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +137 -104
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +173 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +403 -77
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +520 -253
- data/lib/active_record/connection_adapters/schema_cache.rb +326 -102
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +78 -55
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +68 -54
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +66 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +372 -130
- 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 +229 -0
- data/lib/active_record/connection_adapters.rb +130 -6
- data/lib/active_record/connection_handling.rb +132 -146
- data/lib/active_record/core.rb +310 -253
- data/lib/active_record/counter_cache.rb +68 -34
- data/lib/active_record/database_configurations/connection_url_resolver.rb +10 -4
- data/lib/active_record/database_configurations/database_config.rb +34 -10
- data/lib/active_record/database_configurations/hash_config.rb +107 -31
- data/lib/active_record/database_configurations/url_config.rb +38 -13
- data/lib/active_record/database_configurations.rb +96 -60
- data/lib/active_record/delegated_type.rb +90 -20
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +4 -2
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +3 -3
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +170 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +53 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +96 -0
- data/lib/active_record/encryption/null_encryptor.rb +25 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +170 -62
- data/lib/active_record/errors.rb +210 -27
- data/lib/active_record/explain.rb +21 -12
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +15 -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 +70 -14
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +179 -112
- data/lib/active_record/future_result.rb +178 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +85 -31
- data/lib/active_record/insert_all.rb +148 -32
- data/lib/active_record/integration.rb +14 -10
- data/lib/active_record/internal_metadata.rb +123 -23
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +43 -27
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +41 -29
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
- data/lib/active_record/middleware/database_selector.rb +23 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +113 -16
- data/lib/active_record/migration/compatibility.rb +235 -46
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +374 -177
- data/lib/active_record/model_schema.rb +145 -158
- data/lib/active_record/nested_attributes.rb +61 -23
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +282 -283
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +18 -25
- data/lib/active_record/query_logs.rb +189 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +44 -9
- data/lib/active_record/railtie.rb +229 -71
- data/lib/active_record/railties/controller_runtime.rb +25 -11
- data/lib/active_record/railties/databases.rake +189 -256
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +41 -3
- data/lib/active_record/reflection.rb +332 -103
- data/lib/active_record/relation/batches/batch_enumerator.rb +38 -9
- data/lib/active_record/relation/batches.rb +200 -65
- data/lib/active_record/relation/calculations.rb +301 -112
- data/lib/active_record/relation/delegation.rb +33 -22
- data/lib/active_record/relation/finder_methods.rb +123 -52
- data/lib/active_record/relation/merger.rb +26 -19
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +38 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +29 -22
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +870 -163
- data/lib/active_record/relation/record_fetch_warning.rb +10 -9
- data/lib/active_record/relation/spawn_methods.rb +7 -6
- data/lib/active_record/relation/where_clause.rb +15 -36
- data/lib/active_record/relation.rb +736 -145
- data/lib/active_record/result.rb +67 -54
- data/lib/active_record/runtime_registry.rb +71 -13
- data/lib/active_record/sanitization.rb +84 -34
- data/lib/active_record/schema.rb +39 -23
- data/lib/active_record/schema_dumper.rb +90 -31
- data/lib/active_record/schema_migration.rb +74 -23
- data/lib/active_record/scoping/default.rb +72 -15
- data/lib/active_record/scoping/named.rb +6 -13
- data/lib/active_record/scoping.rb +65 -34
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +30 -9
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +7 -3
- data/lib/active_record/tasks/database_tasks.rb +288 -149
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
- data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +173 -155
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +32 -19
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +12 -7
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +118 -41
- data/lib/active_record/translation.rb +3 -5
- data/lib/active_record/type/adapter_specific_registry.rb +32 -14
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +9 -7
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +13 -7
- 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 +65 -15
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +444 -32
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +7 -2
- data/lib/arel/predications.rb +14 -4
- data/lib/arel/select_manager.rb +11 -5
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +8 -15
- data/lib/arel/update_manager.rb +20 -5
- data/lib/arel/visitors/dot.rb +81 -90
- data/lib/arel/visitors/mysql.rb +23 -5
- data/lib/arel/visitors/postgresql.rb +1 -22
- data/lib/arel/visitors/sqlite.rb +25 -0
- data/lib/arel/visitors/to_sql.rb +170 -36
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +23 -4
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- 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
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +103 -17
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
@@ -7,33 +7,21 @@ module ActiveRecord
|
|
7
7
|
64
|
8
8
|
end
|
9
9
|
|
10
|
-
# Returns the maximum length of a table
|
11
|
-
def
|
10
|
+
# Returns the maximum length of a table name.
|
11
|
+
def table_name_length
|
12
12
|
max_identifier_length
|
13
13
|
end
|
14
14
|
|
15
|
-
# Returns the maximum
|
16
|
-
|
17
|
-
|
18
|
-
# #index_name_length is to allow internal \Rails
|
19
|
-
# operations to use prefixes in temporary operations.
|
20
|
-
def allowed_index_name_length
|
21
|
-
index_name_length
|
15
|
+
# Returns the maximum length of a table alias.
|
16
|
+
def table_alias_length
|
17
|
+
max_identifier_length
|
22
18
|
end
|
23
|
-
deprecate :allowed_index_name_length
|
24
19
|
|
25
20
|
# Returns the maximum length of an index name.
|
26
21
|
def index_name_length
|
27
22
|
max_identifier_length
|
28
23
|
end
|
29
24
|
|
30
|
-
# Returns the maximum number of elements in an IN (x,y,z) clause.
|
31
|
-
# +nil+ means no limit.
|
32
|
-
def in_clause_length
|
33
|
-
nil
|
34
|
-
end
|
35
|
-
deprecate :in_clause_length
|
36
|
-
|
37
25
|
private
|
38
26
|
def bind_params_length
|
39
27
|
65535
|
@@ -14,18 +14,24 @@ module ActiveRecord
|
|
14
14
|
sql
|
15
15
|
end
|
16
16
|
|
17
|
-
def to_sql_and_binds(arel_or_sql_string, binds = [], preparable = nil) # :nodoc:
|
17
|
+
def to_sql_and_binds(arel_or_sql_string, binds = [], preparable = nil, allow_retry = false) # :nodoc:
|
18
|
+
# Arel::TreeManager -> Arel::Node
|
18
19
|
if arel_or_sql_string.respond_to?(:ast)
|
20
|
+
arel_or_sql_string = arel_or_sql_string.ast
|
21
|
+
end
|
22
|
+
|
23
|
+
if Arel.arel_node?(arel_or_sql_string) && !(String === arel_or_sql_string)
|
19
24
|
unless binds.empty?
|
20
25
|
raise "Passing bind parameters with an arel AST is forbidden. " \
|
21
26
|
"The values must be stored on the AST directly"
|
22
27
|
end
|
23
28
|
|
24
29
|
collector = collector()
|
30
|
+
collector.retryable = true
|
25
31
|
|
26
32
|
if prepared_statements
|
27
33
|
collector.preparable = true
|
28
|
-
sql, binds = visitor.compile(arel_or_sql_string
|
34
|
+
sql, binds = visitor.compile(arel_or_sql_string, collector)
|
29
35
|
|
30
36
|
if binds.length > bind_params_length
|
31
37
|
unprepared_statement do
|
@@ -34,12 +40,13 @@ module ActiveRecord
|
|
34
40
|
end
|
35
41
|
preparable = collector.preparable
|
36
42
|
else
|
37
|
-
sql = visitor.compile(arel_or_sql_string
|
43
|
+
sql = visitor.compile(arel_or_sql_string, collector)
|
38
44
|
end
|
39
|
-
|
45
|
+
allow_retry = collector.retryable
|
46
|
+
[sql.freeze, binds, preparable, allow_retry]
|
40
47
|
else
|
41
48
|
arel_or_sql_string = arel_or_sql_string.dup.freeze unless arel_or_sql_string.frozen?
|
42
|
-
[arel_or_sql_string, binds, preparable]
|
49
|
+
[arel_or_sql_string, binds, preparable, allow_retry]
|
43
50
|
end
|
44
51
|
end
|
45
52
|
private :to_sql_and_binds
|
@@ -59,28 +66,28 @@ module ActiveRecord
|
|
59
66
|
end
|
60
67
|
|
61
68
|
# Returns an ActiveRecord::Result instance.
|
62
|
-
def select_all(arel, name = nil, binds = [], preparable: nil)
|
69
|
+
def select_all(arel, name = nil, binds = [], preparable: nil, async: false, allow_retry: false)
|
63
70
|
arel = arel_from_relation(arel)
|
64
|
-
sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
|
71
|
+
sql, binds, preparable, allow_retry = to_sql_and_binds(arel, binds, preparable, allow_retry)
|
65
72
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
73
|
+
select(sql, name, binds,
|
74
|
+
prepare: prepared_statements && preparable,
|
75
|
+
async: async && FutureResult::SelectAll,
|
76
|
+
allow_retry: allow_retry
|
77
|
+
)
|
71
78
|
rescue ::RangeError
|
72
|
-
ActiveRecord::Result.
|
79
|
+
ActiveRecord::Result.empty(async: async)
|
73
80
|
end
|
74
81
|
|
75
82
|
# Returns a record hash with the column names as keys and column values
|
76
83
|
# as values.
|
77
|
-
def select_one(arel, name = nil, binds = [])
|
78
|
-
select_all(arel, name, binds).first
|
84
|
+
def select_one(arel, name = nil, binds = [], async: false)
|
85
|
+
select_all(arel, name, binds, async: async).then(&:first)
|
79
86
|
end
|
80
87
|
|
81
88
|
# Returns a single value from a record
|
82
|
-
def select_value(arel, name = nil, binds = [])
|
83
|
-
|
89
|
+
def select_value(arel, name = nil, binds = [], async: false)
|
90
|
+
select_rows(arel, name, binds, async: async).then { |rows| single_value_from_rows(rows) }
|
84
91
|
end
|
85
92
|
|
86
93
|
# Returns an array of the values of the first column in a select:
|
@@ -91,8 +98,8 @@ module ActiveRecord
|
|
91
98
|
|
92
99
|
# Returns an array of arrays containing the field values.
|
93
100
|
# Order is the same as that returned by +columns+.
|
94
|
-
def select_rows(arel, name = nil, binds = [])
|
95
|
-
select_all(arel, name, binds).rows
|
101
|
+
def select_rows(arel, name = nil, binds = [], async: false)
|
102
|
+
select_all(arel, name, binds, async: async).then(&:rows)
|
96
103
|
end
|
97
104
|
|
98
105
|
def query_value(sql, name = nil) # :nodoc:
|
@@ -104,7 +111,7 @@ module ActiveRecord
|
|
104
111
|
end
|
105
112
|
|
106
113
|
def query(sql, name = nil) # :nodoc:
|
107
|
-
|
114
|
+
internal_exec_query(sql, name).rows
|
108
115
|
end
|
109
116
|
|
110
117
|
# Determines whether the SQL statement is a write query.
|
@@ -114,47 +121,63 @@ module ActiveRecord
|
|
114
121
|
|
115
122
|
# Executes the SQL statement in the context of this connection and returns
|
116
123
|
# the raw result from the connection adapter.
|
124
|
+
#
|
125
|
+
# Setting +allow_retry+ to true causes the db to reconnect and retry
|
126
|
+
# executing the SQL statement in case of a connection-related exception.
|
127
|
+
# This option should only be enabled for known idempotent queries.
|
128
|
+
#
|
129
|
+
# Note: the query is assumed to have side effects and the query cache
|
130
|
+
# will be cleared. If the query is read-only, consider using #select_all
|
131
|
+
# instead.
|
132
|
+
#
|
117
133
|
# Note: depending on your database connector, the result returned by this
|
118
|
-
# method may be manually memory managed. Consider using
|
134
|
+
# method may be manually memory managed. Consider using #exec_query
|
119
135
|
# wrapper instead.
|
120
|
-
def execute(sql, name = nil)
|
121
|
-
|
136
|
+
def execute(sql, name = nil, allow_retry: false)
|
137
|
+
internal_execute(sql, name, allow_retry: allow_retry)
|
122
138
|
end
|
123
139
|
|
124
140
|
# Executes +sql+ statement in the context of this connection using
|
125
141
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
126
142
|
# the executed +sql+ statement.
|
143
|
+
#
|
144
|
+
# Note: the query is assumed to have side effects and the query cache
|
145
|
+
# will be cleared. If the query is read-only, consider using #select_all
|
146
|
+
# instead.
|
127
147
|
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
128
|
-
|
148
|
+
internal_exec_query(sql, name, binds, prepare: prepare)
|
129
149
|
end
|
130
150
|
|
131
151
|
# Executes insert +sql+ statement in the context of this connection using
|
132
152
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
133
153
|
# the executed +sql+ statement.
|
134
|
-
|
135
|
-
|
136
|
-
|
154
|
+
# Some adapters support the `returning` keyword argument which allows to control the result of the query:
|
155
|
+
# `nil` is the default value and maintains default behavior. If an array of column names is passed -
|
156
|
+
# the result will contain values of the specified columns from the inserted row.
|
157
|
+
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil, returning: nil)
|
158
|
+
sql, binds = sql_for_insert(sql, pk, binds, returning)
|
159
|
+
internal_exec_query(sql, name, binds)
|
137
160
|
end
|
138
161
|
|
139
162
|
# Executes delete +sql+ statement in the context of this connection using
|
140
163
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
141
164
|
# the executed +sql+ statement.
|
142
165
|
def exec_delete(sql, name = nil, binds = [])
|
143
|
-
|
166
|
+
internal_exec_query(sql, name, binds)
|
144
167
|
end
|
145
168
|
|
146
169
|
# Executes update +sql+ statement in the context of this connection using
|
147
170
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
148
171
|
# the executed +sql+ statement.
|
149
172
|
def exec_update(sql, name = nil, binds = [])
|
150
|
-
|
173
|
+
internal_exec_query(sql, name, binds)
|
151
174
|
end
|
152
175
|
|
153
176
|
def exec_insert_all(sql, name) # :nodoc:
|
154
|
-
|
177
|
+
internal_exec_query(sql, name)
|
155
178
|
end
|
156
179
|
|
157
|
-
def explain(arel, binds = []) # :nodoc:
|
180
|
+
def explain(arel, binds = [], options = []) # :nodoc:
|
158
181
|
raise NotImplementedError
|
159
182
|
end
|
160
183
|
|
@@ -166,9 +189,15 @@ module ActiveRecord
|
|
166
189
|
#
|
167
190
|
# If the next id was calculated in advance (as in Oracle), it should be
|
168
191
|
# passed in as +id_value+.
|
169
|
-
|
192
|
+
# Some adapters support the `returning` keyword argument which allows defining the return value of the method:
|
193
|
+
# `nil` is the default value and maintains default behavior. If an array of column names is passed -
|
194
|
+
# an array of is returned from the method representing values of the specified columns from the inserted row.
|
195
|
+
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [], returning: nil)
|
170
196
|
sql, binds = to_sql_and_binds(arel, binds)
|
171
|
-
value = exec_insert(sql, name, binds, pk, sequence_name)
|
197
|
+
value = exec_insert(sql, name, binds, pk, sequence_name, returning: returning)
|
198
|
+
|
199
|
+
return returning_column_values(value) unless returning.nil?
|
200
|
+
|
172
201
|
id_value || last_inserted_id(value)
|
173
202
|
end
|
174
203
|
alias create insert
|
@@ -191,7 +220,7 @@ module ActiveRecord
|
|
191
220
|
end
|
192
221
|
|
193
222
|
def truncate_tables(*table_names) # :nodoc:
|
194
|
-
table_names -= [schema_migration.table_name,
|
223
|
+
table_names -= [pool.schema_migration.table_name, pool.internal_metadata.table_name]
|
195
224
|
|
196
225
|
return if table_names.empty?
|
197
226
|
|
@@ -206,6 +235,17 @@ module ActiveRecord
|
|
206
235
|
# Runs the given block in a database transaction, and returns the result
|
207
236
|
# of the block.
|
208
237
|
#
|
238
|
+
# == Transaction callbacks
|
239
|
+
#
|
240
|
+
# #transaction yields an ActiveRecord::Transaction object on which it is
|
241
|
+
# possible to register callback:
|
242
|
+
#
|
243
|
+
# ActiveRecord::Base.transaction do |transaction|
|
244
|
+
# transaction.before_commit { puts "before commit!" }
|
245
|
+
# transaction.after_commit { puts "after commit!" }
|
246
|
+
# transaction.after_rollback { puts "after rollback!" }
|
247
|
+
# end
|
248
|
+
#
|
209
249
|
# == Nested transactions support
|
210
250
|
#
|
211
251
|
# #transaction calls can be nested. By default, this makes all database
|
@@ -273,9 +313,9 @@ module ActiveRecord
|
|
273
313
|
# #transaction will raise exceptions when it tries to release the
|
274
314
|
# already-automatically-released savepoints:
|
275
315
|
#
|
276
|
-
# Model.
|
277
|
-
# Model.
|
278
|
-
# Model.
|
316
|
+
# Model.lease_connection.transaction do # BEGIN
|
317
|
+
# Model.lease_connection.transaction(requires_new: true) do # CREATE SAVEPOINT active_record_1
|
318
|
+
# Model.lease_connection.create_table(...)
|
279
319
|
# # active_record_1 now automatically released
|
280
320
|
# end # RELEASE SAVEPOINT active_record_1 <--- BOOM! database error!
|
281
321
|
# end
|
@@ -308,26 +348,28 @@ module ActiveRecord
|
|
308
348
|
# * You are joining an existing open transaction
|
309
349
|
# * You are creating a nested (savepoint) transaction
|
310
350
|
#
|
311
|
-
# The mysql2 and postgresql adapters support setting the transaction
|
351
|
+
# The mysql2, trilogy, and postgresql adapters support setting the transaction
|
312
352
|
# isolation level.
|
313
|
-
|
353
|
+
# :args: (requires_new: nil, isolation: nil, &block)
|
354
|
+
def transaction(requires_new: nil, isolation: nil, joinable: true, &block)
|
314
355
|
if !requires_new && current_transaction.joinable?
|
315
356
|
if isolation
|
316
357
|
raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
|
317
358
|
end
|
318
|
-
yield
|
359
|
+
yield current_transaction.user_transaction
|
319
360
|
else
|
320
|
-
transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable)
|
361
|
+
transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable, &block)
|
321
362
|
end
|
322
363
|
rescue ActiveRecord::Rollback
|
323
364
|
# rollbacks are silently swallowed
|
324
365
|
end
|
325
366
|
|
326
|
-
attr_reader :transaction_manager
|
367
|
+
attr_reader :transaction_manager # :nodoc:
|
327
368
|
|
328
369
|
delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
|
329
370
|
:commit_transaction, :rollback_transaction, :materialize_transactions,
|
330
|
-
:disable_lazy_transactions!, :enable_lazy_transactions!,
|
371
|
+
:disable_lazy_transactions!, :enable_lazy_transactions!, :dirty_current_transaction,
|
372
|
+
to: :transaction_manager
|
331
373
|
|
332
374
|
def mark_transaction_written_if_write(sql) # :nodoc:
|
333
375
|
transaction = current_transaction
|
@@ -340,8 +382,24 @@ module ActiveRecord
|
|
340
382
|
current_transaction.open?
|
341
383
|
end
|
342
384
|
|
343
|
-
def reset_transaction
|
385
|
+
def reset_transaction(restore: false) # :nodoc:
|
386
|
+
# Store the existing transaction state to the side
|
387
|
+
old_state = @transaction_manager if restore && @transaction_manager&.restorable?
|
388
|
+
|
344
389
|
@transaction_manager = ConnectionAdapters::TransactionManager.new(self)
|
390
|
+
|
391
|
+
if block_given?
|
392
|
+
# Reconfigure the connection without any transaction state in the way
|
393
|
+
result = yield
|
394
|
+
|
395
|
+
# Now the connection's fully established, we can swap back
|
396
|
+
if old_state
|
397
|
+
@transaction_manager = old_state
|
398
|
+
@transaction_manager.restore_transactions
|
399
|
+
end
|
400
|
+
|
401
|
+
result
|
402
|
+
end
|
345
403
|
end
|
346
404
|
|
347
405
|
# Register a record with the current transaction so that its after_commit and after_rollback callbacks
|
@@ -376,9 +434,17 @@ module ActiveRecord
|
|
376
434
|
# done if the transaction block raises an exception or returns false.
|
377
435
|
def rollback_db_transaction
|
378
436
|
exec_rollback_db_transaction
|
437
|
+
rescue ActiveRecord::ConnectionNotEstablished, ActiveRecord::ConnectionFailed
|
438
|
+
# Connection's gone; that counts as a rollback
|
439
|
+
end
|
440
|
+
|
441
|
+
def exec_rollback_db_transaction() end # :nodoc:
|
442
|
+
|
443
|
+
def restart_db_transaction
|
444
|
+
exec_restart_db_transaction
|
379
445
|
end
|
380
446
|
|
381
|
-
def
|
447
|
+
def exec_restart_db_transaction() end # :nodoc:
|
382
448
|
|
383
449
|
def rollback_to_savepoint(name = nil)
|
384
450
|
exec_rollback_to_savepoint(name)
|
@@ -397,7 +463,7 @@ module ActiveRecord
|
|
397
463
|
# something beyond a simple insert (e.g. Oracle).
|
398
464
|
# Most of adapters should implement +insert_fixtures_set+ that leverages bulk SQL insert.
|
399
465
|
# We keep this method to provide fallback
|
400
|
-
# for databases like
|
466
|
+
# for databases like SQLite that do not support bulk inserts.
|
401
467
|
def insert_fixture(fixture, table_name)
|
402
468
|
execute(build_fixture_sql(Array.wrap(fixture), table_name), "Fixture Insert")
|
403
469
|
end
|
@@ -408,8 +474,8 @@ module ActiveRecord
|
|
408
474
|
statements = table_deletes + fixture_inserts
|
409
475
|
|
410
476
|
with_multi_statements do
|
411
|
-
|
412
|
-
|
477
|
+
transaction(requires_new: true) do
|
478
|
+
disable_referential_integrity do
|
413
479
|
execute_batch(statements, "Fixtures Load")
|
414
480
|
end
|
415
481
|
end
|
@@ -445,13 +511,43 @@ module ActiveRecord
|
|
445
511
|
end
|
446
512
|
end
|
447
513
|
|
514
|
+
# This is a safe default, even if not high precision on all databases
|
515
|
+
HIGH_PRECISION_CURRENT_TIMESTAMP = Arel.sql("CURRENT_TIMESTAMP", retryable: true).freeze # :nodoc:
|
516
|
+
private_constant :HIGH_PRECISION_CURRENT_TIMESTAMP
|
517
|
+
|
518
|
+
# Returns an Arel SQL literal for the CURRENT_TIMESTAMP for usage with
|
519
|
+
# arbitrary precision date/time columns.
|
520
|
+
#
|
521
|
+
# Adapters supporting datetime with precision should override this to
|
522
|
+
# provide as much precision as is available.
|
523
|
+
def high_precision_current_timestamp
|
524
|
+
HIGH_PRECISION_CURRENT_TIMESTAMP
|
525
|
+
end
|
526
|
+
|
527
|
+
def internal_exec_query(sql, name = "SQL", binds = [], prepare: false, async: false, allow_retry: false) # :nodoc:
|
528
|
+
raise NotImplementedError
|
529
|
+
end
|
530
|
+
|
448
531
|
private
|
532
|
+
def internal_execute(sql, name = "SCHEMA", allow_retry: false, materialize_transactions: true)
|
533
|
+
sql = transform_query(sql)
|
534
|
+
check_if_write_query(sql)
|
535
|
+
|
536
|
+
mark_transaction_written_if_write(sql)
|
537
|
+
|
538
|
+
raw_execute(sql, name, allow_retry: allow_retry, materialize_transactions: materialize_transactions)
|
539
|
+
end
|
540
|
+
|
449
541
|
def execute_batch(statements, name = nil)
|
450
542
|
statements.each do |statement|
|
451
|
-
|
543
|
+
internal_execute(statement, name)
|
452
544
|
end
|
453
545
|
end
|
454
546
|
|
547
|
+
def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: true)
|
548
|
+
raise NotImplementedError
|
549
|
+
end
|
550
|
+
|
455
551
|
DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
|
456
552
|
private_constant :DEFAULT_INSERT_VALUE
|
457
553
|
|
@@ -460,7 +556,7 @@ module ActiveRecord
|
|
460
556
|
end
|
461
557
|
|
462
558
|
def build_fixture_sql(fixtures, table_name)
|
463
|
-
columns = schema_cache.columns_hash(table_name)
|
559
|
+
columns = schema_cache.columns_hash(table_name).reject { |_, column| supports_virtual_columns? && column.virtual? }
|
464
560
|
|
465
561
|
values_list = fixtures.map do |fixture|
|
466
562
|
fixture = fixture.stringify_keys
|
@@ -481,8 +577,7 @@ module ActiveRecord
|
|
481
577
|
end
|
482
578
|
|
483
579
|
table = Arel::Table.new(table_name)
|
484
|
-
manager = Arel::InsertManager.new
|
485
|
-
manager.into(table)
|
580
|
+
manager = Arel::InsertManager.new(table)
|
486
581
|
|
487
582
|
if values_list.size == 1
|
488
583
|
values = values_list.shift
|
@@ -503,10 +598,10 @@ module ActiveRecord
|
|
503
598
|
end
|
504
599
|
|
505
600
|
def build_fixture_statements(fixture_set)
|
506
|
-
fixture_set.
|
601
|
+
fixture_set.filter_map do |table_name, fixtures|
|
507
602
|
next if fixtures.empty?
|
508
603
|
build_fixture_sql(fixtures, table_name)
|
509
|
-
end
|
604
|
+
end
|
510
605
|
end
|
511
606
|
|
512
607
|
def build_truncate_statement(table_name)
|
@@ -528,15 +623,49 @@ module ActiveRecord
|
|
528
623
|
end
|
529
624
|
|
530
625
|
# Returns an ActiveRecord::Result instance.
|
531
|
-
def select(sql, name = nil, binds = [])
|
532
|
-
|
533
|
-
|
626
|
+
def select(sql, name = nil, binds = [], prepare: false, async: false, allow_retry: false)
|
627
|
+
if async && async_enabled?
|
628
|
+
if current_transaction.joinable?
|
629
|
+
raise AsynchronousQueryInsideTransactionError, "Asynchronous queries are not allowed inside transactions"
|
630
|
+
end
|
534
631
|
|
535
|
-
|
536
|
-
|
632
|
+
future_result = async.new(
|
633
|
+
pool,
|
634
|
+
sql,
|
635
|
+
name,
|
636
|
+
binds,
|
637
|
+
prepare: prepare,
|
638
|
+
)
|
639
|
+
if supports_concurrent_connections? && current_transaction.closed?
|
640
|
+
future_result.schedule!(ActiveRecord::Base.asynchronous_queries_session)
|
641
|
+
else
|
642
|
+
future_result.execute!(self)
|
643
|
+
end
|
644
|
+
return future_result
|
645
|
+
end
|
646
|
+
|
647
|
+
result = internal_exec_query(sql, name, binds, prepare: prepare, allow_retry: allow_retry)
|
648
|
+
if async
|
649
|
+
FutureResult.wrap(result)
|
650
|
+
else
|
651
|
+
result
|
652
|
+
end
|
537
653
|
end
|
538
654
|
|
539
|
-
def sql_for_insert(sql, pk, binds)
|
655
|
+
def sql_for_insert(sql, pk, binds, returning) # :nodoc:
|
656
|
+
if supports_insert_returning?
|
657
|
+
if pk.nil?
|
658
|
+
# Extract the table from the insert sql. Yuck.
|
659
|
+
table_ref = extract_table_ref_from_insert_sql(sql)
|
660
|
+
pk = primary_key(table_ref) if table_ref
|
661
|
+
end
|
662
|
+
|
663
|
+
returning_columns = returning || Array(pk)
|
664
|
+
|
665
|
+
returning_columns_statement = returning_columns.map { |c| quote_column_name(c) }.join(", ")
|
666
|
+
sql = "#{sql} RETURNING #{returning_columns_statement}" if returning_columns.any?
|
667
|
+
end
|
668
|
+
|
540
669
|
[sql, binds]
|
541
670
|
end
|
542
671
|
|
@@ -544,6 +673,10 @@ module ActiveRecord
|
|
544
673
|
single_value_from_rows(result.rows)
|
545
674
|
end
|
546
675
|
|
676
|
+
def returning_column_values(result)
|
677
|
+
[last_inserted_id(result)]
|
678
|
+
end
|
679
|
+
|
547
680
|
def single_value_from_rows(rows)
|
548
681
|
row = rows.first
|
549
682
|
row && row.first
|
@@ -556,6 +689,12 @@ module ActiveRecord
|
|
556
689
|
relation
|
557
690
|
end
|
558
691
|
end
|
692
|
+
|
693
|
+
def extract_table_ref_from_insert_sql(sql)
|
694
|
+
if sql =~ /into\s("[A-Za-z0-9_."\[\]\s]+"|[A-Za-z0-9_."\[\]]+)\s*/im
|
695
|
+
$1.delete('"').strip
|
696
|
+
end
|
697
|
+
end
|
559
698
|
end
|
560
699
|
end
|
561
700
|
end
|