activerecord 7.0.8.7 → 7.2.2.1
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 +631 -1944
- data/MIT-LICENSE +1 -1
- data/README.rdoc +29 -29
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +35 -12
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +23 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +22 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +26 -14
- data/lib/active_record/associations/collection_proxy.rb +29 -11
- 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 +21 -14
- data/lib/active_record/associations/has_many_through_association.rb +17 -7
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
- data/lib/active_record/associations/join_dependency.rb +10 -10
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +33 -8
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +354 -485
- data/lib/active_record/attribute_assignment.rb +0 -4
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +53 -35
- data/lib/active_record/attribute_methods/primary_key.rb +45 -25
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +8 -7
- data/lib/active_record/attribute_methods/serialization.rb +131 -32
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -6
- data/lib/active_record/attribute_methods/write.rb +6 -6
- data/lib/active_record/attribute_methods.rb +148 -33
- data/lib/active_record/attributes.rb +64 -50
- data/lib/active_record/autosave_association.rb +69 -37
- data/lib/active_record/base.rb +9 -5
- data/lib/active_record/callbacks.rb +11 -25
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +123 -131
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +323 -88
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +217 -63
- data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -63
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +307 -129
- data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +510 -111
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +278 -125
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +26 -139
- data/lib/active_record/connection_adapters/mysql/quoting.rb +53 -54
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +25 -13
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +101 -68
- data/lib/active_record/connection_adapters/pool_config.rb +20 -10
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +14 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +100 -43
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- 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 +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +65 -61
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +151 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +370 -63
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +367 -201
- data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +45 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +14 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +50 -8
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -110
- 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 +124 -1
- data/lib/active_record/connection_handling.rb +96 -104
- data/lib/active_record/core.rb +251 -176
- data/lib/active_record/counter_cache.rb +68 -34
- data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -3
- data/lib/active_record/database_configurations/database_config.rb +26 -5
- data/lib/active_record/database_configurations/hash_config.rb +52 -34
- data/lib/active_record/database_configurations/url_config.rb +37 -12
- data/lib/active_record/database_configurations.rb +87 -34
- data/lib/active_record/delegated_type.rb +39 -10
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -1
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +45 -21
- data/lib/active_record/encryption/encrypted_attribute_type.rb +47 -12
- data/lib/active_record/encryption/encryptor.rb +18 -3
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -69
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/key_provider.rb +1 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +6 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +22 -21
- data/lib/active_record/encryption.rb +3 -0
- data/lib/active_record/enum.rb +129 -28
- data/lib/active_record/errors.rb +151 -31
- data/lib/active_record/explain.rb +21 -12
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +29 -8
- data/lib/active_record/fixtures.rb +167 -97
- data/lib/active_record/future_result.rb +47 -8
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +34 -18
- data/lib/active_record/insert_all.rb +72 -22
- data/lib/active_record/integration.rb +11 -8
- data/lib/active_record/internal_metadata.rb +124 -20
- data/lib/active_record/locking/optimistic.rb +8 -7
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +18 -22
- 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 +4 -0
- data/lib/active_record/middleware/database_selector.rb +6 -8
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +106 -8
- data/lib/active_record/migration/compatibility.rb +147 -5
- 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/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +234 -117
- data/lib/active_record/model_schema.rb +90 -102
- data/lib/active_record/nested_attributes.rb +48 -11
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +168 -339
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +18 -25
- data/lib/active_record/query_logs.rb +92 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +33 -8
- data/lib/active_record/railtie.rb +129 -85
- data/lib/active_record/railties/controller_runtime.rb +22 -7
- data/lib/active_record/railties/databases.rake +145 -154
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +267 -69
- data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
- data/lib/active_record/relation/batches.rb +198 -63
- data/lib/active_record/relation/calculations.rb +250 -93
- data/lib/active_record/relation/delegation.rb +30 -19
- data/lib/active_record/relation/finder_methods.rb +93 -18
- data/lib/active_record/relation/merger.rb +6 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +18 -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 +28 -16
- data/lib/active_record/relation/query_attribute.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +576 -107
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +5 -4
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +580 -90
- data/lib/active_record/result.rb +49 -48
- data/lib/active_record/runtime_registry.rb +63 -1
- data/lib/active_record/sanitization.rb +70 -25
- data/lib/active_record/schema.rb +8 -7
- data/lib/active_record/schema_dumper.rb +63 -14
- data/lib/active_record/schema_migration.rb +75 -24
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +3 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +27 -6
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +1 -1
- data/lib/active_record/tasks/database_tasks.rb +190 -118
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
- data/lib/active_record/test_fixtures.rb +170 -155
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +31 -17
- 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 +106 -24
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type/time.rb +4 -0
- 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 +9 -3
- 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 +61 -11
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +247 -33
- data/lib/arel/alias_predication.rb +1 -1
- 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/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +6 -2
- data/lib/arel/predications.rb +3 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/table.rb +9 -5
- data/lib/arel/tree_manager.rb +8 -3
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +17 -5
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/sqlite.rb +25 -0
- data/lib/arel/visitors/to_sql.rb +112 -34
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +21 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- 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
- metadata +54 -12
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
@@ -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,106 +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)
|
309
|
+
def data_source_exists?(pool, name)
|
89
310
|
return if ignored_table?(name)
|
90
|
-
|
311
|
+
|
312
|
+
if @data_sources.empty?
|
313
|
+
tables_to_cache(pool).each do |source|
|
314
|
+
@data_sources[source] = true
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
91
318
|
return @data_sources[name] if @data_sources.key? name
|
92
319
|
|
93
|
-
@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
|
94
323
|
end
|
95
324
|
|
96
325
|
# Add internal cache for table with +table_name+.
|
97
|
-
def add(table_name)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
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
|
103
334
|
end
|
104
335
|
end
|
105
336
|
|
106
|
-
def data_sources(name)
|
107
|
-
@data_sources[name]
|
108
|
-
end
|
109
|
-
|
110
337
|
# Get the columns for a table
|
111
|
-
def columns(table_name)
|
338
|
+
def columns(pool, table_name)
|
112
339
|
if ignored_table?(table_name)
|
113
|
-
raise ActiveRecord::StatementInvalid
|
340
|
+
raise ActiveRecord::StatementInvalid.new("Table '#{table_name}' doesn't exist", connection_pool: pool)
|
114
341
|
end
|
115
342
|
|
116
343
|
@columns.fetch(table_name) do
|
117
|
-
|
344
|
+
pool.with_connection do |connection|
|
345
|
+
@columns[deep_deduplicate(table_name)] = deep_deduplicate(connection.columns(table_name))
|
346
|
+
end
|
118
347
|
end
|
119
348
|
end
|
120
349
|
|
121
350
|
# Get the columns for a table as a hash, key is the column name
|
122
351
|
# value is the column object.
|
123
|
-
def columns_hash(table_name)
|
352
|
+
def columns_hash(pool, table_name)
|
124
353
|
@columns_hash.fetch(table_name) do
|
125
|
-
@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
|
126
355
|
end
|
127
356
|
end
|
128
357
|
|
129
358
|
# Checks whether the columns hash is already cached for a table.
|
130
|
-
def columns_hash?(table_name)
|
359
|
+
def columns_hash?(_pool, table_name)
|
131
360
|
@columns_hash.key?(table_name)
|
132
361
|
end
|
133
362
|
|
134
|
-
def indexes(table_name)
|
363
|
+
def indexes(pool, table_name)
|
135
364
|
@indexes.fetch(table_name) do
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
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
|
140
371
|
end
|
141
372
|
end
|
142
373
|
end
|
143
374
|
|
144
|
-
def
|
145
|
-
@
|
375
|
+
def version(pool)
|
376
|
+
@version ||= pool.with_connection(&:schema_version)
|
146
377
|
end
|
147
378
|
|
148
|
-
|
149
|
-
|
150
|
-
@columns.clear
|
151
|
-
@columns_hash.clear
|
152
|
-
@primary_keys.clear
|
153
|
-
@data_sources.clear
|
154
|
-
@indexes.clear
|
155
|
-
@version = nil
|
156
|
-
@database_version = nil
|
379
|
+
def schema_version
|
380
|
+
@version
|
157
381
|
end
|
158
382
|
|
159
383
|
def size
|
@@ -161,7 +385,7 @@ module ActiveRecord
|
|
161
385
|
end
|
162
386
|
|
163
387
|
# Clear out internal caches for the data source +name+.
|
164
|
-
def clear_data_source_cache!(name)
|
388
|
+
def clear_data_source_cache!(_connection, name)
|
165
389
|
@columns.delete name
|
166
390
|
@columns_hash.delete name
|
167
391
|
@primary_keys.delete name
|
@@ -169,9 +393,17 @@ module ActiveRecord
|
|
169
393
|
@indexes.delete name
|
170
394
|
end
|
171
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
|
+
|
172
406
|
def dump_to(filename)
|
173
|
-
clear!
|
174
|
-
tables_to_cache.each { |table| add(table) }
|
175
407
|
open(filename) { |f|
|
176
408
|
if filename.include?(".dump")
|
177
409
|
f.write(Marshal.dump(self))
|
@@ -181,23 +413,23 @@ module ActiveRecord
|
|
181
413
|
}
|
182
414
|
end
|
183
415
|
|
184
|
-
def marshal_dump
|
185
|
-
|
186
|
-
|
187
|
-
[@version, @columns, {}, @primary_keys, @data_sources, @indexes, database_version]
|
416
|
+
def marshal_dump # :nodoc:
|
417
|
+
[@version, @columns, {}, @primary_keys, @data_sources, @indexes]
|
188
418
|
end
|
189
419
|
|
190
|
-
def marshal_load(array)
|
191
|
-
@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
|
192
422
|
@indexes ||= {}
|
193
423
|
|
194
424
|
derive_columns_hash_and_deduplicate_values
|
195
425
|
end
|
196
426
|
|
197
427
|
private
|
198
|
-
def tables_to_cache
|
199
|
-
|
200
|
-
|
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
|
201
433
|
end
|
202
434
|
end
|
203
435
|
|
@@ -207,10 +439,6 @@ module ActiveRecord
|
|
207
439
|
end
|
208
440
|
end
|
209
441
|
|
210
|
-
def reset_version!
|
211
|
-
@version = connection.schema_version
|
212
|
-
end
|
213
|
-
|
214
442
|
def derive_columns_hash_and_deduplicate_values
|
215
443
|
@columns = deep_deduplicate(@columns)
|
216
444
|
@columns_hash = @columns.transform_values { |columns| columns.index_by(&:name) }
|
@@ -232,18 +460,13 @@ module ActiveRecord
|
|
232
460
|
end
|
233
461
|
end
|
234
462
|
|
235
|
-
def prepare_data_sources
|
236
|
-
tables_to_cache.each do |source|
|
237
|
-
@data_sources[source] = true
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
463
|
def open(filename)
|
242
464
|
FileUtils.mkdir_p(File.dirname(filename))
|
243
465
|
|
244
466
|
File.atomic_write(filename) do |file|
|
245
467
|
if File.extname(filename) == ".gz"
|
246
468
|
zipper = Zlib::GzipWriter.new file
|
469
|
+
zipper.mtime = 0
|
247
470
|
yield zipper
|
248
471
|
zipper.flush
|
249
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
|