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
@@ -4,8 +4,228 @@ require "active_support/core_ext/file/atomic"
|
|
4
4
|
|
5
5
|
module ActiveRecord
|
6
6
|
module ConnectionAdapters
|
7
|
+
class SchemaReflection
|
8
|
+
class << self
|
9
|
+
attr_accessor :use_schema_cache_dump
|
10
|
+
attr_accessor :check_schema_cache_dump_version
|
11
|
+
end
|
12
|
+
|
13
|
+
self.use_schema_cache_dump = true
|
14
|
+
self.check_schema_cache_dump_version = true
|
15
|
+
|
16
|
+
def initialize(cache_path, cache = nil)
|
17
|
+
@cache = cache
|
18
|
+
@cache_path = cache_path
|
19
|
+
end
|
20
|
+
|
21
|
+
def clear!
|
22
|
+
@cache = empty_cache
|
23
|
+
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def load!(pool)
|
28
|
+
cache(pool)
|
29
|
+
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def primary_keys(pool, table_name)
|
34
|
+
cache(pool).primary_keys(pool, table_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def data_source_exists?(pool, name)
|
38
|
+
cache(pool).data_source_exists?(pool, name)
|
39
|
+
end
|
40
|
+
|
41
|
+
def add(pool, name)
|
42
|
+
cache(pool).add(pool, name)
|
43
|
+
end
|
44
|
+
|
45
|
+
def data_sources(pool, name)
|
46
|
+
cache(pool).data_source_exists?(pool, name)
|
47
|
+
end
|
48
|
+
|
49
|
+
def columns(pool, table_name)
|
50
|
+
cache(pool).columns(pool, table_name)
|
51
|
+
end
|
52
|
+
|
53
|
+
def columns_hash(pool, table_name)
|
54
|
+
cache(pool).columns_hash(pool, table_name)
|
55
|
+
end
|
56
|
+
|
57
|
+
def columns_hash?(pool, table_name)
|
58
|
+
cache(pool).columns_hash?(pool, table_name)
|
59
|
+
end
|
60
|
+
|
61
|
+
def indexes(pool, table_name)
|
62
|
+
cache(pool).indexes(pool, table_name)
|
63
|
+
end
|
64
|
+
|
65
|
+
def version(pool)
|
66
|
+
cache(pool).version(pool)
|
67
|
+
end
|
68
|
+
|
69
|
+
def size(pool)
|
70
|
+
cache(pool).size
|
71
|
+
end
|
72
|
+
|
73
|
+
def clear_data_source_cache!(pool, name)
|
74
|
+
return if @cache.nil? && !possible_cache_available?
|
75
|
+
|
76
|
+
cache(pool).clear_data_source_cache!(pool, name)
|
77
|
+
end
|
78
|
+
|
79
|
+
def cached?(table_name)
|
80
|
+
if @cache.nil?
|
81
|
+
# If `check_schema_cache_dump_version` is enabled we can't load
|
82
|
+
# the schema cache dump without connecting to the database.
|
83
|
+
unless self.class.check_schema_cache_dump_version
|
84
|
+
@cache = load_cache(nil)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
@cache&.cached?(table_name)
|
89
|
+
end
|
90
|
+
|
91
|
+
def dump_to(pool, filename)
|
92
|
+
fresh_cache = empty_cache
|
93
|
+
fresh_cache.add_all(pool)
|
94
|
+
fresh_cache.dump_to(filename)
|
95
|
+
|
96
|
+
@cache = fresh_cache
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
def empty_cache
|
101
|
+
new_cache = SchemaCache.allocate
|
102
|
+
new_cache.send(:initialize)
|
103
|
+
new_cache
|
104
|
+
end
|
105
|
+
|
106
|
+
def cache(pool)
|
107
|
+
@cache ||= load_cache(pool) || empty_cache
|
108
|
+
end
|
109
|
+
|
110
|
+
def possible_cache_available?
|
111
|
+
self.class.use_schema_cache_dump &&
|
112
|
+
@cache_path &&
|
113
|
+
File.file?(@cache_path)
|
114
|
+
end
|
115
|
+
|
116
|
+
def load_cache(pool)
|
117
|
+
# Can't load if schema dumps are disabled
|
118
|
+
return unless possible_cache_available?
|
119
|
+
|
120
|
+
# Check we can find one
|
121
|
+
return unless new_cache = SchemaCache._load_from(@cache_path)
|
122
|
+
|
123
|
+
if self.class.check_schema_cache_dump_version
|
124
|
+
begin
|
125
|
+
pool.with_connection do |connection|
|
126
|
+
current_version = connection.schema_version
|
127
|
+
|
128
|
+
if new_cache.version(connection) != current_version
|
129
|
+
warn "Ignoring #{@cache_path} because it has expired. The current schema version is #{current_version}, but the one in the schema cache file is #{new_cache.schema_version}."
|
130
|
+
return
|
131
|
+
end
|
132
|
+
end
|
133
|
+
rescue ActiveRecordError => error
|
134
|
+
warn "Failed to validate the schema cache because of #{error.class}: #{error.message}"
|
135
|
+
return
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
new_cache
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
class BoundSchemaReflection
|
144
|
+
class FakePool # :nodoc
|
145
|
+
def initialize(connection)
|
146
|
+
@connection = connection
|
147
|
+
end
|
148
|
+
|
149
|
+
def with_connection
|
150
|
+
yield @connection
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
class << self
|
155
|
+
def for_lone_connection(abstract_schema_reflection, connection) # :nodoc:
|
156
|
+
new(abstract_schema_reflection, FakePool.new(connection))
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def initialize(abstract_schema_reflection, pool)
|
161
|
+
@schema_reflection = abstract_schema_reflection
|
162
|
+
@pool = pool
|
163
|
+
end
|
164
|
+
|
165
|
+
def clear!
|
166
|
+
@schema_reflection.clear!
|
167
|
+
end
|
168
|
+
|
169
|
+
def load!
|
170
|
+
@schema_reflection.load!(@pool)
|
171
|
+
end
|
172
|
+
|
173
|
+
def cached?(table_name)
|
174
|
+
@schema_reflection.cached?(table_name)
|
175
|
+
end
|
176
|
+
|
177
|
+
def primary_keys(table_name)
|
178
|
+
@schema_reflection.primary_keys(@pool, table_name)
|
179
|
+
end
|
180
|
+
|
181
|
+
def data_source_exists?(name)
|
182
|
+
@schema_reflection.data_source_exists?(@pool, name)
|
183
|
+
end
|
184
|
+
|
185
|
+
def add(name)
|
186
|
+
@schema_reflection.add(@pool, name)
|
187
|
+
end
|
188
|
+
|
189
|
+
def data_sources(name)
|
190
|
+
@schema_reflection.data_sources(@pool, name)
|
191
|
+
end
|
192
|
+
|
193
|
+
def columns(table_name)
|
194
|
+
@schema_reflection.columns(@pool, table_name)
|
195
|
+
end
|
196
|
+
|
197
|
+
def columns_hash(table_name)
|
198
|
+
@schema_reflection.columns_hash(@pool, table_name)
|
199
|
+
end
|
200
|
+
|
201
|
+
def columns_hash?(table_name)
|
202
|
+
@schema_reflection.columns_hash?(@pool, table_name)
|
203
|
+
end
|
204
|
+
|
205
|
+
def indexes(table_name)
|
206
|
+
@schema_reflection.indexes(@pool, table_name)
|
207
|
+
end
|
208
|
+
|
209
|
+
def version
|
210
|
+
@schema_reflection.version(@pool)
|
211
|
+
end
|
212
|
+
|
213
|
+
def size
|
214
|
+
@schema_reflection.size(@pool)
|
215
|
+
end
|
216
|
+
|
217
|
+
def clear_data_source_cache!(name)
|
218
|
+
@schema_reflection.clear_data_source_cache!(@pool, name)
|
219
|
+
end
|
220
|
+
|
221
|
+
def dump_to(filename)
|
222
|
+
@schema_reflection.dump_to(@pool, filename)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# = Active Record Connection Adapters Schema Cache
|
7
227
|
class SchemaCache
|
8
|
-
def self.
|
228
|
+
def self._load_from(filename) # :nodoc:
|
9
229
|
return unless File.file?(filename)
|
10
230
|
|
11
231
|
read(filename) do |file|
|
@@ -32,20 +252,16 @@ module ActiveRecord
|
|
32
252
|
end
|
33
253
|
private_class_method :read
|
34
254
|
|
35
|
-
|
36
|
-
attr_accessor :connection
|
37
|
-
|
38
|
-
def initialize(conn)
|
39
|
-
@connection = conn
|
40
|
-
|
255
|
+
def initialize # :nodoc:
|
41
256
|
@columns = {}
|
42
257
|
@columns_hash = {}
|
43
258
|
@primary_keys = {}
|
44
259
|
@data_sources = {}
|
45
260
|
@indexes = {}
|
261
|
+
@version = nil
|
46
262
|
end
|
47
263
|
|
48
|
-
def initialize_dup(other)
|
264
|
+
def initialize_dup(other) # :nodoc:
|
49
265
|
super
|
50
266
|
@columns = @columns.dup
|
51
267
|
@columns_hash = @columns_hash.dup
|
@@ -54,97 +270,114 @@ module ActiveRecord
|
|
54
270
|
@indexes = @indexes.dup
|
55
271
|
end
|
56
272
|
|
57
|
-
def encode_with(coder)
|
58
|
-
|
59
|
-
|
60
|
-
coder["
|
61
|
-
coder["
|
62
|
-
coder["data_sources"] = @data_sources
|
63
|
-
coder["indexes"] = @indexes
|
273
|
+
def encode_with(coder) # :nodoc:
|
274
|
+
coder["columns"] = @columns.sort.to_h
|
275
|
+
coder["primary_keys"] = @primary_keys.sort.to_h
|
276
|
+
coder["data_sources"] = @data_sources.sort.to_h
|
277
|
+
coder["indexes"] = @indexes.sort.to_h
|
64
278
|
coder["version"] = @version
|
65
|
-
coder["database_version"] = database_version
|
66
279
|
end
|
67
280
|
|
68
|
-
def init_with(coder)
|
281
|
+
def init_with(coder) # :nodoc:
|
69
282
|
@columns = coder["columns"]
|
283
|
+
@columns_hash = coder["columns_hash"]
|
70
284
|
@primary_keys = coder["primary_keys"]
|
71
285
|
@data_sources = coder["data_sources"]
|
72
286
|
@indexes = coder["indexes"] || {}
|
73
287
|
@version = coder["version"]
|
74
|
-
@database_version = coder["database_version"]
|
75
288
|
|
76
|
-
|
289
|
+
unless coder["deduplicated"]
|
290
|
+
derive_columns_hash_and_deduplicate_values
|
291
|
+
end
|
77
292
|
end
|
78
293
|
|
79
|
-
def
|
294
|
+
def cached?(table_name)
|
295
|
+
@columns.key?(table_name)
|
296
|
+
end
|
297
|
+
|
298
|
+
def primary_keys(pool, table_name)
|
80
299
|
@primary_keys.fetch(table_name) do
|
81
|
-
|
82
|
-
|
300
|
+
pool.with_connection do |connection|
|
301
|
+
if data_source_exists?(pool, table_name)
|
302
|
+
@primary_keys[deep_deduplicate(table_name)] = deep_deduplicate(connection.primary_key(table_name))
|
303
|
+
end
|
83
304
|
end
|
84
305
|
end
|
85
306
|
end
|
86
307
|
|
87
308
|
# A cached lookup for table existence.
|
88
|
-
def data_source_exists?(name)
|
89
|
-
|
309
|
+
def data_source_exists?(pool, name)
|
310
|
+
return if ignored_table?(name)
|
311
|
+
|
312
|
+
if @data_sources.empty?
|
313
|
+
tables_to_cache(pool).each do |source|
|
314
|
+
@data_sources[source] = true
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
90
318
|
return @data_sources[name] if @data_sources.key? name
|
91
319
|
|
92
|
-
@data_sources[deep_deduplicate(name)] = connection
|
320
|
+
@data_sources[deep_deduplicate(name)] = pool.with_connection do |connection|
|
321
|
+
connection.data_source_exists?(name)
|
322
|
+
end
|
93
323
|
end
|
94
324
|
|
95
325
|
# Add internal cache for table with +table_name+.
|
96
|
-
def add(table_name)
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
326
|
+
def add(pool, table_name)
|
327
|
+
pool.with_connection do
|
328
|
+
if data_source_exists?(pool, table_name)
|
329
|
+
primary_keys(pool, table_name)
|
330
|
+
columns(pool, table_name)
|
331
|
+
columns_hash(pool, table_name)
|
332
|
+
indexes(pool, table_name)
|
333
|
+
end
|
102
334
|
end
|
103
335
|
end
|
104
336
|
|
105
|
-
def data_sources(name)
|
106
|
-
@data_sources[name]
|
107
|
-
end
|
108
|
-
|
109
337
|
# Get the columns for a table
|
110
|
-
def columns(table_name)
|
338
|
+
def columns(pool, table_name)
|
339
|
+
if ignored_table?(table_name)
|
340
|
+
raise ActiveRecord::StatementInvalid.new("Table '#{table_name}' doesn't exist", connection_pool: pool)
|
341
|
+
end
|
342
|
+
|
111
343
|
@columns.fetch(table_name) do
|
112
|
-
|
344
|
+
pool.with_connection do |connection|
|
345
|
+
@columns[deep_deduplicate(table_name)] = deep_deduplicate(connection.columns(table_name))
|
346
|
+
end
|
113
347
|
end
|
114
348
|
end
|
115
349
|
|
116
350
|
# Get the columns for a table as a hash, key is the column name
|
117
351
|
# value is the column object.
|
118
|
-
def columns_hash(table_name)
|
352
|
+
def columns_hash(pool, table_name)
|
119
353
|
@columns_hash.fetch(table_name) do
|
120
|
-
@columns_hash[deep_deduplicate(table_name)] = columns(table_name).index_by(&:name).freeze
|
354
|
+
@columns_hash[deep_deduplicate(table_name)] = columns(pool, table_name).index_by(&:name).freeze
|
121
355
|
end
|
122
356
|
end
|
123
357
|
|
124
358
|
# Checks whether the columns hash is already cached for a table.
|
125
|
-
def columns_hash?(table_name)
|
359
|
+
def columns_hash?(_pool, table_name)
|
126
360
|
@columns_hash.key?(table_name)
|
127
361
|
end
|
128
362
|
|
129
|
-
def indexes(table_name)
|
363
|
+
def indexes(pool, table_name)
|
130
364
|
@indexes.fetch(table_name) do
|
131
|
-
|
365
|
+
pool.with_connection do |connection|
|
366
|
+
if data_source_exists?(pool, table_name)
|
367
|
+
@indexes[deep_deduplicate(table_name)] = deep_deduplicate(connection.indexes(table_name))
|
368
|
+
else
|
369
|
+
[]
|
370
|
+
end
|
371
|
+
end
|
132
372
|
end
|
133
373
|
end
|
134
374
|
|
135
|
-
def
|
136
|
-
@
|
375
|
+
def version(pool)
|
376
|
+
@version ||= pool.with_connection(&:schema_version)
|
137
377
|
end
|
138
378
|
|
139
|
-
|
140
|
-
|
141
|
-
@columns.clear
|
142
|
-
@columns_hash.clear
|
143
|
-
@primary_keys.clear
|
144
|
-
@data_sources.clear
|
145
|
-
@indexes.clear
|
146
|
-
@version = nil
|
147
|
-
@database_version = nil
|
379
|
+
def schema_version
|
380
|
+
@version
|
148
381
|
end
|
149
382
|
|
150
383
|
def size
|
@@ -152,7 +385,7 @@ module ActiveRecord
|
|
152
385
|
end
|
153
386
|
|
154
387
|
# Clear out internal caches for the data source +name+.
|
155
|
-
def clear_data_source_cache!(name)
|
388
|
+
def clear_data_source_cache!(_connection, name)
|
156
389
|
@columns.delete name
|
157
390
|
@columns_hash.delete name
|
158
391
|
@primary_keys.delete name
|
@@ -160,9 +393,17 @@ module ActiveRecord
|
|
160
393
|
@indexes.delete name
|
161
394
|
end
|
162
395
|
|
396
|
+
def add_all(pool) # :nodoc:
|
397
|
+
pool.with_connection do
|
398
|
+
tables_to_cache(pool).each do |table|
|
399
|
+
add(pool, table)
|
400
|
+
end
|
401
|
+
|
402
|
+
version(pool)
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
163
406
|
def dump_to(filename)
|
164
|
-
clear!
|
165
|
-
connection.data_sources.each { |table| add(table) }
|
166
407
|
open(filename) { |f|
|
167
408
|
if filename.include?(".dump")
|
168
409
|
f.write(Marshal.dump(self))
|
@@ -172,22 +413,30 @@ module ActiveRecord
|
|
172
413
|
}
|
173
414
|
end
|
174
415
|
|
175
|
-
def marshal_dump
|
176
|
-
|
177
|
-
|
178
|
-
[@version, @columns, {}, @primary_keys, @data_sources, @indexes, database_version]
|
416
|
+
def marshal_dump # :nodoc:
|
417
|
+
[@version, @columns, {}, @primary_keys, @data_sources, @indexes]
|
179
418
|
end
|
180
419
|
|
181
|
-
def marshal_load(array)
|
182
|
-
@version, @columns, _columns_hash, @primary_keys, @data_sources, @indexes,
|
420
|
+
def marshal_load(array) # :nodoc:
|
421
|
+
@version, @columns, _columns_hash, @primary_keys, @data_sources, @indexes, _database_version = array
|
183
422
|
@indexes ||= {}
|
184
423
|
|
185
424
|
derive_columns_hash_and_deduplicate_values
|
186
425
|
end
|
187
426
|
|
188
427
|
private
|
189
|
-
def
|
190
|
-
|
428
|
+
def tables_to_cache(pool)
|
429
|
+
pool.with_connection do |connection|
|
430
|
+
connection.data_sources.reject do |table|
|
431
|
+
ignored_table?(table)
|
432
|
+
end
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
def ignored_table?(table_name)
|
437
|
+
ActiveRecord.schema_cache_ignored_tables.any? do |ignored|
|
438
|
+
ignored === table_name
|
439
|
+
end
|
191
440
|
end
|
192
441
|
|
193
442
|
def derive_columns_hash_and_deduplicate_values
|
@@ -198,51 +447,26 @@ module ActiveRecord
|
|
198
447
|
@indexes = deep_deduplicate(@indexes)
|
199
448
|
end
|
200
449
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
# In Ruby 2.6, the receiver of the String#-@ method is modified under certain
|
212
|
-
# circumstances, and this was later identified as a bug
|
213
|
-
# (https://bugs.ruby-lang.org/issues/15926) and only fixed in Ruby 2.7.
|
214
|
-
value = value.dup
|
215
|
-
end
|
216
|
-
-value
|
217
|
-
when Deduplicable
|
218
|
-
-value
|
219
|
-
else
|
220
|
-
value
|
221
|
-
end
|
222
|
-
end
|
223
|
-
else
|
224
|
-
def deep_deduplicate(value)
|
225
|
-
case value
|
226
|
-
when Hash
|
227
|
-
value.transform_keys { |k| deep_deduplicate(k) }.transform_values { |v| deep_deduplicate(v) }
|
228
|
-
when Array
|
229
|
-
value.map { |i| deep_deduplicate(i) }
|
230
|
-
when String, Deduplicable
|
231
|
-
-value
|
232
|
-
else
|
233
|
-
value
|
234
|
-
end
|
450
|
+
def deep_deduplicate(value)
|
451
|
+
case value
|
452
|
+
when Hash
|
453
|
+
value.transform_keys { |k| deep_deduplicate(k) }.transform_values { |v| deep_deduplicate(v) }
|
454
|
+
when Array
|
455
|
+
value.map { |i| deep_deduplicate(i) }
|
456
|
+
when String, Deduplicable
|
457
|
+
-value
|
458
|
+
else
|
459
|
+
value
|
235
460
|
end
|
236
461
|
end
|
237
462
|
|
238
|
-
def prepare_data_sources
|
239
|
-
connection.data_sources.each { |source| @data_sources[source] = true }
|
240
|
-
end
|
241
|
-
|
242
463
|
def open(filename)
|
464
|
+
FileUtils.mkdir_p(File.dirname(filename))
|
465
|
+
|
243
466
|
File.atomic_write(filename) do |file|
|
244
467
|
if File.extname(filename) == ".gz"
|
245
468
|
zipper = Zlib::GzipWriter.new file
|
469
|
+
zipper.mtime = 0
|
246
470
|
yield zipper
|
247
471
|
zipper.flush
|
248
472
|
zipper.close
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module SQLite3
|
6
|
+
class Column < ConnectionAdapters::Column # :nodoc:
|
7
|
+
attr_reader :rowid
|
8
|
+
|
9
|
+
def initialize(*, auto_increment: nil, rowid: false, generated_type: nil, **)
|
10
|
+
super
|
11
|
+
@auto_increment = auto_increment
|
12
|
+
@rowid = rowid
|
13
|
+
@generated_type = generated_type
|
14
|
+
end
|
15
|
+
|
16
|
+
def auto_increment?
|
17
|
+
@auto_increment
|
18
|
+
end
|
19
|
+
|
20
|
+
def auto_incremented_by_db?
|
21
|
+
auto_increment? || rowid
|
22
|
+
end
|
23
|
+
|
24
|
+
def virtual?
|
25
|
+
!@generated_type.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def virtual_stored?
|
29
|
+
virtual? && @generated_type == :stored
|
30
|
+
end
|
31
|
+
|
32
|
+
def has_default?
|
33
|
+
super && !virtual?
|
34
|
+
end
|
35
|
+
|
36
|
+
def init_with(coder)
|
37
|
+
@auto_increment = coder["auto_increment"]
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
def encode_with(coder)
|
42
|
+
coder["auto_increment"] = @auto_increment
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def ==(other)
|
47
|
+
other.is_a?(Column) &&
|
48
|
+
super &&
|
49
|
+
auto_increment? == other.auto_increment?
|
50
|
+
end
|
51
|
+
alias :eql? :==
|
52
|
+
|
53
|
+
def hash
|
54
|
+
Column.hash ^
|
55
|
+
super.hash ^
|
56
|
+
auto_increment?.hash ^
|
57
|
+
rowid.hash
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|