activerecord 6.1.7 → 7.1.5
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 +2030 -1020
- data/MIT-LICENSE +1 -1
- data/README.rdoc +18 -18
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +1 -11
- data/lib/active_record/associations/association.rb +51 -19
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +40 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +6 -2
- data/lib/active_record/associations/collection_association.rb +39 -35
- data/lib/active_record/associations/collection_proxy.rb +30 -15
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +28 -18
- data/lib/active_record/associations/has_many_through_association.rb +12 -7
- 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 +3 -2
- data/lib/active_record/associations/join_dependency.rb +28 -20
- data/lib/active_record/associations/preloader/association.rb +210 -52
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -14
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +9 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +446 -306
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -3
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/dirty.rb +73 -22
- data/lib/active_record/attribute_methods/primary_key.rb +78 -26
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +27 -12
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +161 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +65 -31
- data/lib/active_record/base.rb +25 -2
- data/lib/active_record/callbacks.rb +18 -34
- 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 +367 -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 +78 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +113 -597
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
- 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 +367 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -150
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +317 -164
- 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 +25 -134
- data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
- 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 +39 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +112 -55
- data/lib/active_record/connection_adapters/pool_config.rb +20 -11
- 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 +89 -52
- 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/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.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
- 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 +153 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +397 -75
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +508 -246
- data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +72 -53
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +296 -104
- 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 +258 -0
- data/lib/active_record/connection_adapters.rb +9 -6
- data/lib/active_record/connection_handling.rb +108 -137
- data/lib/active_record/core.rb +242 -233
- data/lib/active_record/counter_cache.rb +52 -27
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -2
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +88 -16
- data/lib/active_record/database_configurations/url_config.rb +18 -12
- data/lib/active_record/database_configurations.rb +95 -59
- data/lib/active_record/delegated_type.rb +66 -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 +1 -1
- 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 +155 -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 +155 -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_serializer.rb +92 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +154 -63
- data/lib/active_record/errors.rb +172 -15
- data/lib/active_record/explain.rb +23 -3
- 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 +147 -86
- data/lib/active_record/future_result.rb +174 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +81 -29
- data/lib/active_record/insert_all.rb +135 -22
- data/lib/active_record/integration.rb +11 -10
- data/lib/active_record/internal_metadata.rb +119 -33
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +37 -22
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- 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 +112 -14
- data/lib/active_record/migration/compatibility.rb +233 -46
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +361 -173
- data/lib/active_record/model_schema.rb +125 -101
- data/lib/active_record/nested_attributes.rb +50 -20
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +167 -0
- data/lib/active_record/persistence.rb +409 -88
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +4 -22
- data/lib/active_record/query_logs.rb +174 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +29 -6
- data/lib/active_record/railtie.rb +220 -44
- data/lib/active_record/railties/controller_runtime.rb +15 -10
- data/lib/active_record/railties/databases.rake +188 -252
- 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 +248 -81
- data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
- data/lib/active_record/relation/batches.rb +192 -63
- data/lib/active_record/relation/calculations.rb +246 -90
- data/lib/active_record/relation/delegation.rb +28 -14
- data/lib/active_record/relation/finder_methods.rb +108 -51
- data/lib/active_record/relation/merger.rb +22 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
- 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 +27 -20
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +670 -129
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +20 -3
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +287 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +32 -13
- data/lib/active_record/sanitization.rb +65 -20
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +73 -24
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +72 -15
- data/lib/active_record/scoping/named.rb +5 -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 +10 -8
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +251 -140
- 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 +15 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +117 -96
- data/lib/active_record/timestamp.rb +32 -19
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +48 -27
- data/lib/active_record/translation.rb +3 -3
- 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 -5
- 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/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +4 -4
- 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 +51 -6
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +335 -32
- data/lib/arel/attributes/attribute.rb +0 -8
- 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/and.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/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/node.rb +111 -2
- 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 +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +5 -0
- data/lib/arel/predications.rb +13 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +5 -13
- data/lib/arel/update_manager.rb +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +16 -3
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +141 -20
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +18 -3
- 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.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 +96 -16
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
@@ -4,8 +4,234 @@ 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 set_schema_cache(cache)
|
22
|
+
@cache = cache
|
23
|
+
end
|
24
|
+
|
25
|
+
def clear!
|
26
|
+
@cache = empty_cache
|
27
|
+
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def load!(connection)
|
32
|
+
cache(connection)
|
33
|
+
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def primary_keys(connection, table_name)
|
38
|
+
cache(connection).primary_keys(connection, table_name)
|
39
|
+
end
|
40
|
+
|
41
|
+
def data_source_exists?(connection, name)
|
42
|
+
cache(connection).data_source_exists?(connection, name)
|
43
|
+
end
|
44
|
+
|
45
|
+
def add(connection, name)
|
46
|
+
cache(connection).add(connection, name)
|
47
|
+
end
|
48
|
+
|
49
|
+
def data_sources(connection, name)
|
50
|
+
cache(connection).data_sources(connection, name)
|
51
|
+
end
|
52
|
+
|
53
|
+
def columns(connection, table_name)
|
54
|
+
cache(connection).columns(connection, table_name)
|
55
|
+
end
|
56
|
+
|
57
|
+
def columns_hash(connection, table_name)
|
58
|
+
cache(connection).columns_hash(connection, table_name)
|
59
|
+
end
|
60
|
+
|
61
|
+
def columns_hash?(connection, table_name)
|
62
|
+
cache(connection).columns_hash?(connection, table_name)
|
63
|
+
end
|
64
|
+
|
65
|
+
def indexes(connection, table_name)
|
66
|
+
cache(connection).indexes(connection, table_name)
|
67
|
+
end
|
68
|
+
|
69
|
+
def database_version(connection) # :nodoc:
|
70
|
+
cache(connection).database_version(connection)
|
71
|
+
end
|
72
|
+
|
73
|
+
def version(connection)
|
74
|
+
cache(connection).version(connection)
|
75
|
+
end
|
76
|
+
|
77
|
+
def size(connection)
|
78
|
+
cache(connection).size
|
79
|
+
end
|
80
|
+
|
81
|
+
def clear_data_source_cache!(connection, name)
|
82
|
+
return if @cache.nil? && !possible_cache_available?
|
83
|
+
|
84
|
+
cache(connection).clear_data_source_cache!(connection, name)
|
85
|
+
end
|
86
|
+
|
87
|
+
def cached?(table_name)
|
88
|
+
if @cache.nil?
|
89
|
+
# If `check_schema_cache_dump_version` is enabled we can't load
|
90
|
+
# the schema cache dump without connecting to the database.
|
91
|
+
unless self.class.check_schema_cache_dump_version
|
92
|
+
@cache = load_cache(nil)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
@cache&.cached?(table_name)
|
97
|
+
end
|
98
|
+
|
99
|
+
def dump_to(connection, filename)
|
100
|
+
fresh_cache = empty_cache
|
101
|
+
fresh_cache.add_all(connection)
|
102
|
+
fresh_cache.dump_to(filename)
|
103
|
+
|
104
|
+
@cache = fresh_cache
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
def empty_cache
|
109
|
+
new_cache = SchemaCache.allocate
|
110
|
+
new_cache.send(:initialize)
|
111
|
+
new_cache
|
112
|
+
end
|
113
|
+
|
114
|
+
def cache(connection)
|
115
|
+
@cache ||= load_cache(connection) || empty_cache
|
116
|
+
end
|
117
|
+
|
118
|
+
def possible_cache_available?
|
119
|
+
self.class.use_schema_cache_dump &&
|
120
|
+
@cache_path &&
|
121
|
+
File.file?(@cache_path)
|
122
|
+
end
|
123
|
+
|
124
|
+
def load_cache(connection)
|
125
|
+
# Can't load if schema dumps are disabled
|
126
|
+
return unless possible_cache_available?
|
127
|
+
|
128
|
+
# Check we can find one
|
129
|
+
return unless new_cache = SchemaCache._load_from(@cache_path)
|
130
|
+
|
131
|
+
if self.class.check_schema_cache_dump_version
|
132
|
+
begin
|
133
|
+
current_version = connection.schema_version
|
134
|
+
|
135
|
+
if new_cache.version(connection) != current_version
|
136
|
+
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}."
|
137
|
+
return
|
138
|
+
end
|
139
|
+
rescue ActiveRecordError => error
|
140
|
+
warn "Failed to validate the schema cache because of #{error.class}: #{error.message}"
|
141
|
+
return
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
new_cache
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class BoundSchemaReflection
|
150
|
+
def initialize(abstract_schema_reflection, connection)
|
151
|
+
@schema_reflection = abstract_schema_reflection
|
152
|
+
@connection = connection
|
153
|
+
end
|
154
|
+
|
155
|
+
def clear!
|
156
|
+
@schema_reflection.clear!
|
157
|
+
end
|
158
|
+
|
159
|
+
def load!
|
160
|
+
@schema_reflection.load!(@connection)
|
161
|
+
end
|
162
|
+
|
163
|
+
def cached?(table_name)
|
164
|
+
@schema_reflection.cached?(table_name)
|
165
|
+
end
|
166
|
+
|
167
|
+
def primary_keys(table_name)
|
168
|
+
@schema_reflection.primary_keys(@connection, table_name)
|
169
|
+
end
|
170
|
+
|
171
|
+
def data_source_exists?(name)
|
172
|
+
@schema_reflection.data_source_exists?(@connection, name)
|
173
|
+
end
|
174
|
+
|
175
|
+
def add(name)
|
176
|
+
@schema_reflection.add(@connection, name)
|
177
|
+
end
|
178
|
+
|
179
|
+
def data_sources(name)
|
180
|
+
@schema_reflection.data_sources(@connection, name)
|
181
|
+
end
|
182
|
+
|
183
|
+
def columns(table_name)
|
184
|
+
@schema_reflection.columns(@connection, table_name)
|
185
|
+
end
|
186
|
+
|
187
|
+
def columns_hash(table_name)
|
188
|
+
@schema_reflection.columns_hash(@connection, table_name)
|
189
|
+
end
|
190
|
+
|
191
|
+
def columns_hash?(table_name)
|
192
|
+
@schema_reflection.columns_hash?(@connection, table_name)
|
193
|
+
end
|
194
|
+
|
195
|
+
def indexes(table_name)
|
196
|
+
@schema_reflection.indexes(@connection, table_name)
|
197
|
+
end
|
198
|
+
|
199
|
+
def database_version # :nodoc:
|
200
|
+
@schema_reflection.database_version(@connection)
|
201
|
+
end
|
202
|
+
|
203
|
+
def version
|
204
|
+
@schema_reflection.version(@connection)
|
205
|
+
end
|
206
|
+
|
207
|
+
def size
|
208
|
+
@schema_reflection.size(@connection)
|
209
|
+
end
|
210
|
+
|
211
|
+
def clear_data_source_cache!(name)
|
212
|
+
@schema_reflection.clear_data_source_cache!(@connection, name)
|
213
|
+
end
|
214
|
+
|
215
|
+
def dump_to(filename)
|
216
|
+
@schema_reflection.dump_to(@connection, filename)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# = Active Record Connection Adapters Schema Cache
|
7
221
|
class SchemaCache
|
8
|
-
|
222
|
+
class << self
|
223
|
+
def new(connection)
|
224
|
+
BoundSchemaReflection.new(SchemaReflection.new(nil), connection)
|
225
|
+
end
|
226
|
+
deprecate new: "use ActiveRecord::ConnectionAdapters::SchemaReflection instead", deprecator: ActiveRecord.deprecator
|
227
|
+
|
228
|
+
def load_from(filename) # :nodoc:
|
229
|
+
BoundSchemaReflection.new(SchemaReflection.new(filename), nil)
|
230
|
+
end
|
231
|
+
deprecate load_from: "use ActiveRecord::ConnectionAdapters::SchemaReflection instead", deprecator: ActiveRecord.deprecator
|
232
|
+
end
|
233
|
+
|
234
|
+
def self._load_from(filename) # :nodoc:
|
9
235
|
return unless File.file?(filename)
|
10
236
|
|
11
237
|
read(filename) do |file|
|
@@ -32,20 +258,17 @@ module ActiveRecord
|
|
32
258
|
end
|
33
259
|
private_class_method :read
|
34
260
|
|
35
|
-
|
36
|
-
attr_accessor :connection
|
37
|
-
|
38
|
-
def initialize(conn)
|
39
|
-
@connection = conn
|
40
|
-
|
261
|
+
def initialize
|
41
262
|
@columns = {}
|
42
263
|
@columns_hash = {}
|
43
264
|
@primary_keys = {}
|
44
265
|
@data_sources = {}
|
45
266
|
@indexes = {}
|
267
|
+
@database_version = nil
|
268
|
+
@version = nil
|
46
269
|
end
|
47
270
|
|
48
|
-
def initialize_dup(other)
|
271
|
+
def initialize_dup(other) # :nodoc:
|
49
272
|
super
|
50
273
|
@columns = @columns.dup
|
51
274
|
@columns_hash = @columns_hash.dup
|
@@ -54,60 +277,71 @@ module ActiveRecord
|
|
54
277
|
@indexes = @indexes.dup
|
55
278
|
end
|
56
279
|
|
57
|
-
def encode_with(coder)
|
58
|
-
|
59
|
-
|
60
|
-
coder["
|
61
|
-
coder["
|
62
|
-
coder["data_sources"] = @data_sources
|
63
|
-
coder["indexes"] = @indexes
|
280
|
+
def encode_with(coder) # :nodoc:
|
281
|
+
coder["columns"] = @columns.sort.to_h
|
282
|
+
coder["primary_keys"] = @primary_keys.sort.to_h
|
283
|
+
coder["data_sources"] = @data_sources.sort.to_h
|
284
|
+
coder["indexes"] = @indexes.sort.to_h
|
64
285
|
coder["version"] = @version
|
65
|
-
coder["database_version"] = database_version
|
286
|
+
coder["database_version"] = @database_version
|
66
287
|
end
|
67
288
|
|
68
289
|
def init_with(coder)
|
69
290
|
@columns = coder["columns"]
|
291
|
+
@columns_hash = coder["columns_hash"]
|
70
292
|
@primary_keys = coder["primary_keys"]
|
71
293
|
@data_sources = coder["data_sources"]
|
72
294
|
@indexes = coder["indexes"] || {}
|
73
295
|
@version = coder["version"]
|
74
296
|
@database_version = coder["database_version"]
|
75
297
|
|
76
|
-
|
298
|
+
unless coder["deduplicated"]
|
299
|
+
derive_columns_hash_and_deduplicate_values
|
300
|
+
end
|
77
301
|
end
|
78
302
|
|
79
|
-
def
|
303
|
+
def cached?(table_name)
|
304
|
+
@columns.key?(table_name)
|
305
|
+
end
|
306
|
+
|
307
|
+
def primary_keys(connection, table_name)
|
80
308
|
@primary_keys.fetch(table_name) do
|
81
|
-
if data_source_exists?(table_name)
|
309
|
+
if data_source_exists?(connection, table_name)
|
82
310
|
@primary_keys[deep_deduplicate(table_name)] = deep_deduplicate(connection.primary_key(table_name))
|
83
311
|
end
|
84
312
|
end
|
85
313
|
end
|
86
314
|
|
87
315
|
# A cached lookup for table existence.
|
88
|
-
def data_source_exists?(name)
|
89
|
-
|
316
|
+
def data_source_exists?(connection, name)
|
317
|
+
return if ignored_table?(name)
|
318
|
+
prepare_data_sources(connection) if @data_sources.empty?
|
90
319
|
return @data_sources[name] if @data_sources.key? name
|
91
320
|
|
92
321
|
@data_sources[deep_deduplicate(name)] = connection.data_source_exists?(name)
|
93
322
|
end
|
94
323
|
|
95
324
|
# Add internal cache for table with +table_name+.
|
96
|
-
def add(table_name)
|
97
|
-
if data_source_exists?(table_name)
|
98
|
-
primary_keys(table_name)
|
99
|
-
columns(table_name)
|
100
|
-
columns_hash(table_name)
|
101
|
-
indexes(table_name)
|
325
|
+
def add(connection, table_name)
|
326
|
+
if data_source_exists?(connection, table_name)
|
327
|
+
primary_keys(connection, table_name)
|
328
|
+
columns(connection, table_name)
|
329
|
+
columns_hash(connection, table_name)
|
330
|
+
indexes(connection, table_name)
|
102
331
|
end
|
103
332
|
end
|
104
333
|
|
105
|
-
def data_sources(name)
|
334
|
+
def data_sources(_connection, name) # :nodoc:
|
106
335
|
@data_sources[name]
|
107
336
|
end
|
337
|
+
deprecate data_sources: :data_source_exists?, deprecator: ActiveRecord.deprecator
|
108
338
|
|
109
339
|
# Get the columns for a table
|
110
|
-
def columns(table_name)
|
340
|
+
def columns(connection, table_name)
|
341
|
+
if ignored_table?(table_name)
|
342
|
+
raise ActiveRecord::StatementInvalid, "Table '#{table_name}' doesn't exist"
|
343
|
+
end
|
344
|
+
|
111
345
|
@columns.fetch(table_name) do
|
112
346
|
@columns[deep_deduplicate(table_name)] = deep_deduplicate(connection.columns(table_name))
|
113
347
|
end
|
@@ -115,36 +349,37 @@ module ActiveRecord
|
|
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(connection, 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(connection, 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?(connection, table_name)
|
126
360
|
@columns_hash.key?(table_name)
|
127
361
|
end
|
128
362
|
|
129
|
-
def indexes(table_name)
|
363
|
+
def indexes(connection, table_name)
|
130
364
|
@indexes.fetch(table_name) do
|
131
|
-
|
365
|
+
if data_source_exists?(connection, table_name)
|
366
|
+
@indexes[deep_deduplicate(table_name)] = deep_deduplicate(connection.indexes(table_name))
|
367
|
+
else
|
368
|
+
[]
|
369
|
+
end
|
132
370
|
end
|
133
371
|
end
|
134
372
|
|
135
|
-
def database_version # :nodoc:
|
373
|
+
def database_version(connection) # :nodoc:
|
136
374
|
@database_version ||= connection.get_database_version
|
137
375
|
end
|
138
376
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
@
|
145
|
-
@indexes.clear
|
146
|
-
@version = nil
|
147
|
-
@database_version = nil
|
377
|
+
def version(connection)
|
378
|
+
@version ||= connection.schema_version
|
379
|
+
end
|
380
|
+
|
381
|
+
def schema_version
|
382
|
+
@version
|
148
383
|
end
|
149
384
|
|
150
385
|
def size
|
@@ -152,7 +387,7 @@ module ActiveRecord
|
|
152
387
|
end
|
153
388
|
|
154
389
|
# Clear out internal caches for the data source +name+.
|
155
|
-
def clear_data_source_cache!(name)
|
390
|
+
def clear_data_source_cache!(_connection, name)
|
156
391
|
@columns.delete name
|
157
392
|
@columns_hash.delete name
|
158
393
|
@primary_keys.delete name
|
@@ -160,9 +395,16 @@ module ActiveRecord
|
|
160
395
|
@indexes.delete name
|
161
396
|
end
|
162
397
|
|
398
|
+
def add_all(connection) # :nodoc:
|
399
|
+
tables_to_cache(connection).each do |table|
|
400
|
+
add(connection, table)
|
401
|
+
end
|
402
|
+
|
403
|
+
version(connection)
|
404
|
+
database_version(connection)
|
405
|
+
end
|
406
|
+
|
163
407
|
def dump_to(filename)
|
164
|
-
clear!
|
165
|
-
connection.data_sources.each { |table| add(table) }
|
166
408
|
open(filename) { |f|
|
167
409
|
if filename.include?(".dump")
|
168
410
|
f.write(Marshal.dump(self))
|
@@ -172,13 +414,11 @@ module ActiveRecord
|
|
172
414
|
}
|
173
415
|
end
|
174
416
|
|
175
|
-
def marshal_dump
|
176
|
-
|
177
|
-
|
178
|
-
[@version, @columns, {}, @primary_keys, @data_sources, @indexes, database_version]
|
417
|
+
def marshal_dump # :nodoc:
|
418
|
+
[@version, @columns, {}, @primary_keys, @data_sources, @indexes, @database_version]
|
179
419
|
end
|
180
420
|
|
181
|
-
def marshal_load(array)
|
421
|
+
def marshal_load(array) # :nodoc:
|
182
422
|
@version, @columns, _columns_hash, @primary_keys, @data_sources, @indexes, @database_version = array
|
183
423
|
@indexes ||= {}
|
184
424
|
|
@@ -186,8 +426,16 @@ module ActiveRecord
|
|
186
426
|
end
|
187
427
|
|
188
428
|
private
|
189
|
-
def
|
190
|
-
|
429
|
+
def tables_to_cache(connection)
|
430
|
+
connection.data_sources.reject do |table|
|
431
|
+
ignored_table?(table)
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
def ignored_table?(table_name)
|
436
|
+
ActiveRecord.schema_cache_ignored_tables.any? do |ignored|
|
437
|
+
ignored === table_name
|
438
|
+
end
|
191
439
|
end
|
192
440
|
|
193
441
|
def derive_columns_hash_and_deduplicate_values
|
@@ -198,51 +446,32 @@ module ActiveRecord
|
|
198
446
|
@indexes = deep_deduplicate(@indexes)
|
199
447
|
end
|
200
448
|
|
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
|
449
|
+
def deep_deduplicate(value)
|
450
|
+
case value
|
451
|
+
when Hash
|
452
|
+
value.transform_keys { |k| deep_deduplicate(k) }.transform_values { |v| deep_deduplicate(v) }
|
453
|
+
when Array
|
454
|
+
value.map { |i| deep_deduplicate(i) }
|
455
|
+
when String, Deduplicable
|
456
|
+
-value
|
457
|
+
else
|
458
|
+
value
|
235
459
|
end
|
236
460
|
end
|
237
461
|
|
238
|
-
def prepare_data_sources
|
239
|
-
connection.
|
462
|
+
def prepare_data_sources(connection)
|
463
|
+
tables_to_cache(connection).each do |source|
|
464
|
+
@data_sources[source] = true
|
465
|
+
end
|
240
466
|
end
|
241
467
|
|
242
468
|
def open(filename)
|
469
|
+
FileUtils.mkdir_p(File.dirname(filename))
|
470
|
+
|
243
471
|
File.atomic_write(filename) do |file|
|
244
472
|
if File.extname(filename) == ".gz"
|
245
473
|
zipper = Zlib::GzipWriter.new file
|
474
|
+
zipper.mtime = 0
|
246
475
|
yield zipper
|
247
476
|
zipper.flush
|
248
477
|
zipper.close
|
@@ -0,0 +1,49 @@
|
|
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, **)
|
10
|
+
super
|
11
|
+
@auto_increment = auto_increment
|
12
|
+
@rowid = rowid
|
13
|
+
end
|
14
|
+
|
15
|
+
def auto_increment?
|
16
|
+
@auto_increment
|
17
|
+
end
|
18
|
+
|
19
|
+
def auto_incremented_by_db?
|
20
|
+
auto_increment? || rowid
|
21
|
+
end
|
22
|
+
|
23
|
+
def init_with(coder)
|
24
|
+
@auto_increment = coder["auto_increment"]
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def encode_with(coder)
|
29
|
+
coder["auto_increment"] = @auto_increment
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
def ==(other)
|
34
|
+
other.is_a?(Column) &&
|
35
|
+
super &&
|
36
|
+
auto_increment? == other.auto_increment?
|
37
|
+
end
|
38
|
+
alias :eql? :==
|
39
|
+
|
40
|
+
def hash
|
41
|
+
Column.hash ^
|
42
|
+
super.hash ^
|
43
|
+
auto_increment?.hash ^
|
44
|
+
rowid.hash
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|