activerecord 6.1.7.10 → 7.0.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +726 -1404
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +0 -10
- data/lib/active_record/associations/association.rb +31 -9
- data/lib/active_record/associations/association_scope.rb +1 -3
- data/lib/active_record/associations/belongs_to_association.rb +15 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +8 -2
- data/lib/active_record/associations/builder/belongs_to.rb +19 -6
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- 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 +2 -2
- data/lib/active_record/associations/collection_association.rb +14 -23
- data/lib/active_record/associations/collection_proxy.rb +8 -3
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +2 -1
- data/lib/active_record/associations/has_one_association.rb +10 -7
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/preloader/association.rb +161 -47
- data/lib/active_record/associations/preloader/batch.rb +51 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +37 -11
- data/lib/active_record/associations/preloader.rb +46 -110
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +76 -81
- data/lib/active_record/asynchronous_queries_tracker.rb +57 -0
- data/lib/active_record/attribute_assignment.rb +1 -1
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
- data/lib/active_record/attribute_methods/dirty.rb +41 -16
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +7 -5
- data/lib/active_record/attribute_methods/serialization.rb +66 -12
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
- data/lib/active_record/attribute_methods/write.rb +7 -10
- data/lib/active_record/attribute_methods.rb +6 -9
- data/lib/active_record/attributes.rb +24 -35
- data/lib/active_record/autosave_association.rb +3 -18
- data/lib/active_record/base.rb +19 -1
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/coders/yaml_column.rb +2 -14
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +312 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -558
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +45 -21
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/quoting.rb +12 -14
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +60 -16
- data/lib/active_record/connection_adapters/abstract/transaction.rb +3 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +112 -66
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +96 -81
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +33 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
- data/lib/active_record/connection_adapters/pool_config.rb +1 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -14
- 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/range.rb +1 -1
- 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 +28 -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 +6 -32
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +12 -12
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +159 -102
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -37
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +23 -19
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -30
- data/lib/active_record/connection_adapters.rb +6 -5
- data/lib/active_record/connection_handling.rb +20 -38
- data/lib/active_record/core.rb +111 -125
- data/lib/active_record/database_configurations/connection_url_resolver.rb +0 -1
- data/lib/active_record/database_configurations/database_config.rb +12 -0
- data/lib/active_record/database_configurations/hash_config.rb +27 -1
- data/lib/active_record/database_configurations/url_config.rb +2 -2
- data/lib/active_record/database_configurations.rb +17 -9
- data/lib/active_record/delegated_type.rb +33 -11
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- 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/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +61 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +208 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -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 +160 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +29 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +42 -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 +80 -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 +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +41 -41
- data/lib/active_record/errors.rb +66 -3
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +40 -5
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +16 -11
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +55 -17
- data/lib/active_record/insert_all.rb +34 -5
- data/lib/active_record/integration.rb +1 -1
- data/lib/active_record/internal_metadata.rb +1 -5
- data/lib/active_record/locking/optimistic.rb +10 -9
- data/lib/active_record/log_subscriber.rb +6 -2
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
- data/lib/active_record/middleware/database_selector.rb +8 -3
- data/lib/active_record/migration/command_recorder.rb +4 -4
- data/lib/active_record/migration/compatibility.rb +89 -10
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +109 -79
- data/lib/active_record/model_schema.rb +45 -31
- data/lib/active_record/nested_attributes.rb +3 -3
- data/lib/active_record/no_touching.rb +2 -2
- data/lib/active_record/null_relation.rb +2 -6
- data/lib/active_record/persistence.rb +134 -45
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +203 -0
- data/lib/active_record/querying.rb +15 -5
- data/lib/active_record/railtie.rb +117 -17
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +72 -48
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +45 -44
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/calculations.rb +39 -26
- data/lib/active_record/relation/delegation.rb +6 -6
- data/lib/active_record/relation/finder_methods.rb +31 -22
- data/lib/active_record/relation/merger.rb +20 -13
- data/lib/active_record/relation/predicate_builder.rb +1 -6
- data/lib/active_record/relation/query_attribute.rb +5 -11
- data/lib/active_record/relation/query_methods.rb +230 -49
- data/lib/active_record/relation/record_fetch_warning.rb +2 -2
- data/lib/active_record/relation/spawn_methods.rb +2 -2
- data/lib/active_record/relation/where_clause.rb +8 -4
- data/lib/active_record/relation.rb +166 -77
- data/lib/active_record/result.rb +17 -2
- data/lib/active_record/runtime_registry.rb +2 -4
- data/lib/active_record/sanitization.rb +11 -7
- data/lib/active_record/schema_dumper.rb +3 -3
- data/lib/active_record/schema_migration.rb +0 -4
- data/lib/active_record/scoping/default.rb +61 -12
- data/lib/active_record/scoping/named.rb +3 -11
- data/lib/active_record/scoping.rb +40 -22
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/store.rb +1 -6
- data/lib/active_record/tasks/database_tasks.rb +106 -22
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -11
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +9 -13
- data/lib/active_record/timestamp.rb +3 -4
- data/lib/active_record/transactions.rb +9 -14
- data/lib/active_record/translation.rb +2 -2
- data/lib/active_record/type/adapter_specific_registry.rb +32 -7
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +1 -1
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record.rb +170 -2
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +18 -22
- data/lib/arel/delete_manager.rb +2 -4
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/delete_statement.rb +8 -13
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/update_statement.rb +3 -2
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +0 -1
- data/lib/arel/tree_manager.rb +0 -12
- data/lib/arel/update_manager.rb +2 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +6 -1
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +43 -2
- data/lib/arel.rb +1 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- 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
- metadata +52 -14
@@ -11,8 +11,6 @@ module ActiveRecord
|
|
11
11
|
|
12
12
|
def write_query?(sql) # :nodoc:
|
13
13
|
!READ_QUERY.match?(sql)
|
14
|
-
rescue ArgumentError # Invalid encoding
|
15
|
-
!READ_QUERY.match?(sql.b)
|
16
14
|
end
|
17
15
|
|
18
16
|
def explain(arel, binds = [])
|
@@ -20,10 +18,9 @@ module ActiveRecord
|
|
20
18
|
SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", []))
|
21
19
|
end
|
22
20
|
|
23
|
-
def execute(sql, name = nil)
|
24
|
-
|
25
|
-
|
26
|
-
end
|
21
|
+
def execute(sql, name = nil) # :nodoc:
|
22
|
+
sql = transform_query(sql)
|
23
|
+
check_if_write_query(sql)
|
27
24
|
|
28
25
|
materialize_transactions
|
29
26
|
mark_transaction_written_if_write(sql)
|
@@ -35,17 +32,16 @@ module ActiveRecord
|
|
35
32
|
end
|
36
33
|
end
|
37
34
|
|
38
|
-
def exec_query(sql, name = nil, binds = [], prepare: false)
|
39
|
-
|
40
|
-
|
41
|
-
end
|
35
|
+
def exec_query(sql, name = nil, binds = [], prepare: false, async: false) # :nodoc:
|
36
|
+
sql = transform_query(sql)
|
37
|
+
check_if_write_query(sql)
|
42
38
|
|
43
39
|
materialize_transactions
|
44
40
|
mark_transaction_written_if_write(sql)
|
45
41
|
|
46
42
|
type_casted_binds = type_casted_binds(binds)
|
47
43
|
|
48
|
-
log(sql, name, binds, type_casted_binds) do
|
44
|
+
log(sql, name, binds, type_casted_binds, async: async) do
|
49
45
|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
50
46
|
# Don't cache statements if they are not prepared
|
51
47
|
unless prepare
|
@@ -72,13 +68,13 @@ module ActiveRecord
|
|
72
68
|
end
|
73
69
|
end
|
74
70
|
|
75
|
-
def exec_delete(sql, name = "SQL", binds = [])
|
71
|
+
def exec_delete(sql, name = "SQL", binds = []) # :nodoc:
|
76
72
|
exec_query(sql, name, binds)
|
77
73
|
@connection.changes
|
78
74
|
end
|
79
75
|
alias :exec_update :exec_delete
|
80
76
|
|
81
|
-
def begin_isolated_db_transaction(isolation)
|
77
|
+
def begin_isolated_db_transaction(isolation) # :nodoc:
|
82
78
|
raise TransactionIsolationError, "SQLite3 only supports the `read_uncommitted` transaction isolation level" if isolation != :read_uncommitted
|
83
79
|
raise StandardError, "You need to enable the shared-cache mode in SQLite mode before attempting to change the transaction isolation level" unless shared_cache?
|
84
80
|
|
@@ -87,20 +83,29 @@ module ActiveRecord
|
|
87
83
|
begin_db_transaction
|
88
84
|
end
|
89
85
|
|
90
|
-
def begin_db_transaction
|
86
|
+
def begin_db_transaction # :nodoc:
|
91
87
|
log("begin transaction", "TRANSACTION") { @connection.transaction }
|
92
88
|
end
|
93
89
|
|
94
|
-
def commit_db_transaction
|
90
|
+
def commit_db_transaction # :nodoc:
|
95
91
|
log("commit transaction", "TRANSACTION") { @connection.commit }
|
96
92
|
reset_read_uncommitted
|
97
93
|
end
|
98
94
|
|
99
|
-
def exec_rollback_db_transaction
|
95
|
+
def exec_rollback_db_transaction # :nodoc:
|
100
96
|
log("rollback transaction", "TRANSACTION") { @connection.rollback }
|
101
97
|
reset_read_uncommitted
|
102
98
|
end
|
103
99
|
|
100
|
+
# https://stackoverflow.com/questions/17574784
|
101
|
+
# https://www.sqlite.org/lang_datefunc.html
|
102
|
+
HIGH_PRECISION_CURRENT_TIMESTAMP = Arel.sql("STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')").freeze # :nodoc:
|
103
|
+
private_constant :HIGH_PRECISION_CURRENT_TIMESTAMP
|
104
|
+
|
105
|
+
def high_precision_current_timestamp
|
106
|
+
HIGH_PRECISION_CURRENT_TIMESTAMP
|
107
|
+
end
|
108
|
+
|
104
109
|
private
|
105
110
|
def reset_read_uncommitted
|
106
111
|
read_uncommitted = Thread.current.thread_variable_get("read_uncommitted")
|
@@ -110,11 +115,10 @@ module ActiveRecord
|
|
110
115
|
end
|
111
116
|
|
112
117
|
def execute_batch(statements, name = nil)
|
118
|
+
statements = statements.map { |sql| transform_query(sql) }
|
113
119
|
sql = combine_multi_statements(statements)
|
114
120
|
|
115
|
-
|
116
|
-
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
117
|
-
end
|
121
|
+
check_if_write_query(sql)
|
118
122
|
|
119
123
|
materialize_transactions
|
120
124
|
mark_transaction_written_if_write(sql)
|
@@ -6,7 +6,7 @@ module ActiveRecord
|
|
6
6
|
module SchemaStatements # :nodoc:
|
7
7
|
# Returns an array of indexes for the given table.
|
8
8
|
def indexes(table_name)
|
9
|
-
exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", "SCHEMA").
|
9
|
+
exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", "SCHEMA").filter_map do |row|
|
10
10
|
# Indexes SQLite creates implicitly for internal use start with "sqlite_".
|
11
11
|
# See https://www.sqlite.org/fileformat2.html#intschema
|
12
12
|
next if row["name"].start_with?("sqlite_")
|
@@ -49,7 +49,7 @@ module ActiveRecord
|
|
49
49
|
where: where,
|
50
50
|
orders: orders
|
51
51
|
)
|
52
|
-
end
|
52
|
+
end
|
53
53
|
end
|
54
54
|
|
55
55
|
def add_foreign_key(from_table, to_table, **options)
|
@@ -60,6 +60,8 @@ module ActiveRecord
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def remove_foreign_key(from_table, to_table = nil, **options)
|
63
|
+
return if options[:if_exists] == true && !foreign_key_exists?(from_table, to_table)
|
64
|
+
|
63
65
|
to_table ||= options[:to_table]
|
64
66
|
options = options.except(:name, :to_table, :validate)
|
65
67
|
foreign_keys = foreign_keys(from_table)
|
@@ -47,7 +47,7 @@ module ActiveRecord
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
module ConnectionAdapters
|
50
|
+
module ConnectionAdapters # :nodoc:
|
51
51
|
# The SQLite3 adapter works with the sqlite3-ruby drivers
|
52
52
|
# (available as gem from https://rubygems.org/gems/sqlite3).
|
53
53
|
#
|
@@ -84,6 +84,7 @@ module ActiveRecord
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def initialize(connection, logger, connection_options, config)
|
87
|
+
@memory_database = config[:database] == ":memory:"
|
87
88
|
super(connection, logger, config)
|
88
89
|
configure_connection
|
89
90
|
end
|
@@ -153,6 +154,10 @@ module ActiveRecord
|
|
153
154
|
alias supports_insert_on_duplicate_update? supports_insert_on_conflict?
|
154
155
|
alias supports_insert_conflict_target? supports_insert_on_conflict?
|
155
156
|
|
157
|
+
def supports_concurrent_connections?
|
158
|
+
!@memory_database
|
159
|
+
end
|
160
|
+
|
156
161
|
def active?
|
157
162
|
!@connection.closed?
|
158
163
|
end
|
@@ -173,11 +178,11 @@ module ActiveRecord
|
|
173
178
|
true
|
174
179
|
end
|
175
180
|
|
176
|
-
def native_database_types
|
181
|
+
def native_database_types # :nodoc:
|
177
182
|
NATIVE_DATABASE_TYPES
|
178
183
|
end
|
179
184
|
|
180
|
-
# Returns the current database encoding format as a string,
|
185
|
+
# Returns the current database encoding format as a string, e.g. 'UTF-8'
|
181
186
|
def encoding
|
182
187
|
@connection.encoding.to_s
|
183
188
|
end
|
@@ -206,6 +211,10 @@ module ActiveRecord
|
|
206
211
|
end
|
207
212
|
end
|
208
213
|
|
214
|
+
def all_foreign_keys_valid? # :nodoc:
|
215
|
+
execute("PRAGMA foreign_key_check").blank?
|
216
|
+
end
|
217
|
+
|
209
218
|
# SCHEMA STATEMENTS ========================================
|
210
219
|
|
211
220
|
def primary_keys(table_name) # :nodoc:
|
@@ -232,7 +241,7 @@ module ActiveRecord
|
|
232
241
|
rename_table_indexes(table_name, new_name)
|
233
242
|
end
|
234
243
|
|
235
|
-
def add_column(table_name, column_name, type, **options)
|
244
|
+
def add_column(table_name, column_name, type, **options) # :nodoc:
|
236
245
|
if invalid_alter_table_type?(type, options)
|
237
246
|
alter_table(table_name) do |definition|
|
238
247
|
definition.column(column_name, type, **options)
|
@@ -242,16 +251,24 @@ module ActiveRecord
|
|
242
251
|
end
|
243
252
|
end
|
244
253
|
|
245
|
-
def remove_column(table_name, column_name, type = nil, **options)
|
254
|
+
def remove_column(table_name, column_name, type = nil, **options) # :nodoc:
|
246
255
|
alter_table(table_name) do |definition|
|
247
256
|
definition.remove_column column_name
|
248
|
-
definition.foreign_keys.delete_if
|
249
|
-
|
257
|
+
definition.foreign_keys.delete_if { |fk| fk.column == column_name.to_s }
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def remove_columns(table_name, *column_names, type: nil, **options) # :nodoc:
|
262
|
+
alter_table(table_name) do |definition|
|
263
|
+
column_names.each do |column_name|
|
264
|
+
definition.remove_column column_name
|
250
265
|
end
|
266
|
+
column_names = column_names.map(&:to_s)
|
267
|
+
definition.foreign_keys.delete_if { |fk| column_names.include?(fk.column) }
|
251
268
|
end
|
252
269
|
end
|
253
270
|
|
254
|
-
def change_column_default(table_name, column_name, default_or_changes)
|
271
|
+
def change_column_default(table_name, column_name, default_or_changes) # :nodoc:
|
255
272
|
default = extract_new_default_value(default_or_changes)
|
256
273
|
|
257
274
|
alter_table(table_name) do |definition|
|
@@ -259,7 +276,7 @@ module ActiveRecord
|
|
259
276
|
end
|
260
277
|
end
|
261
278
|
|
262
|
-
def change_column_null(table_name, column_name, null, default = nil)
|
279
|
+
def change_column_null(table_name, column_name, null, default = nil) # :nodoc:
|
263
280
|
unless null || default.nil?
|
264
281
|
exec_query("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
|
265
282
|
end
|
@@ -268,7 +285,7 @@ module ActiveRecord
|
|
268
285
|
end
|
269
286
|
end
|
270
287
|
|
271
|
-
def change_column(table_name, column_name, type, **options)
|
288
|
+
def change_column(table_name, column_name, type, **options) # :nodoc:
|
272
289
|
alter_table(table_name) do |definition|
|
273
290
|
definition[column_name].instance_eval do
|
274
291
|
self.type = aliased_types(type.to_s, type)
|
@@ -277,7 +294,7 @@ module ActiveRecord
|
|
277
294
|
end
|
278
295
|
end
|
279
296
|
|
280
|
-
def rename_column(table_name, column_name, new_column_name)
|
297
|
+
def rename_column(table_name, column_name, new_column_name) # :nodoc:
|
281
298
|
column = column_for(table_name, column_name)
|
282
299
|
alter_table(table_name, rename: { column.name => new_column_name.to_s })
|
283
300
|
rename_column_indexes(table_name, column.name, new_column_name)
|
@@ -308,8 +325,12 @@ module ActiveRecord
|
|
308
325
|
sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
|
309
326
|
elsif insert.update_duplicates?
|
310
327
|
sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
|
311
|
-
|
312
|
-
|
328
|
+
if insert.raw_update_sql?
|
329
|
+
sql << insert.raw_update_sql
|
330
|
+
else
|
331
|
+
sql << insert.touch_model_timestamps_unless { |column| "#{column} IS excluded.#{column}" }
|
332
|
+
sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
|
333
|
+
end
|
313
334
|
end
|
314
335
|
|
315
336
|
sql
|
@@ -329,18 +350,38 @@ module ActiveRecord
|
|
329
350
|
end
|
330
351
|
end
|
331
352
|
|
353
|
+
class SQLite3Integer < Type::Integer # :nodoc:
|
354
|
+
private
|
355
|
+
def _limit
|
356
|
+
# INTEGER storage class can be stored 8 bytes value.
|
357
|
+
# See https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes
|
358
|
+
limit || 8
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
ActiveRecord::Type.register(:integer, SQLite3Integer, adapter: :sqlite3)
|
363
|
+
|
364
|
+
class << self
|
365
|
+
private
|
366
|
+
def initialize_type_map(m)
|
367
|
+
super
|
368
|
+
register_class_with_limit m, %r(int)i, SQLite3Integer
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
|
373
|
+
|
332
374
|
private
|
375
|
+
def type_map
|
376
|
+
TYPE_MAP
|
377
|
+
end
|
378
|
+
|
333
379
|
# See https://www.sqlite.org/limits.html,
|
334
380
|
# the default value is 999 when not configured.
|
335
381
|
def bind_params_length
|
336
382
|
999
|
337
383
|
end
|
338
384
|
|
339
|
-
def initialize_type_map(m = type_map)
|
340
|
-
super
|
341
|
-
register_class_with_limit m, %r(int)i, SQLite3Integer
|
342
|
-
end
|
343
|
-
|
344
385
|
def table_structure(table_name)
|
345
386
|
structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", "SCHEMA")
|
346
387
|
raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
|
@@ -446,6 +487,7 @@ module ActiveRecord
|
|
446
487
|
options = { name: name.gsub(/(^|_)(#{from})_/, "\\1#{to}_"), internal: true }
|
447
488
|
options[:unique] = true if index.unique
|
448
489
|
options[:where] = index.where if index.where
|
490
|
+
options[:order] = index.orders if index.orders
|
449
491
|
add_index(to, columns, **options)
|
450
492
|
end
|
451
493
|
end
|
@@ -482,7 +524,7 @@ module ActiveRecord
|
|
482
524
|
end
|
483
525
|
end
|
484
526
|
|
485
|
-
COLLATE_REGEX =
|
527
|
+
COLLATE_REGEX = /.*"(\w+)".*collate\s+"(\w+)".*/i.freeze
|
486
528
|
|
487
529
|
def table_structure_with_collation(table_name, basic_structure)
|
488
530
|
collation_hash = {}
|
@@ -544,17 +586,6 @@ module ActiveRecord
|
|
544
586
|
|
545
587
|
execute("PRAGMA foreign_keys = ON", "SCHEMA")
|
546
588
|
end
|
547
|
-
|
548
|
-
class SQLite3Integer < Type::Integer # :nodoc:
|
549
|
-
private
|
550
|
-
def _limit
|
551
|
-
# INTEGER storage class can be stored 8 bytes value.
|
552
|
-
# See https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes
|
553
|
-
limit || 8
|
554
|
-
end
|
555
|
-
end
|
556
|
-
|
557
|
-
ActiveRecord::Type.register(:integer, SQLite3Integer, adapter: :sqlite3)
|
558
589
|
end
|
559
590
|
ActiveSupport.run_load_hooks(:active_record_sqlite3adapter, SQLite3Adapter)
|
560
591
|
end
|
@@ -27,20 +27,21 @@ module ActiveRecord
|
|
27
27
|
autoload :ReferenceDefinition
|
28
28
|
end
|
29
29
|
|
30
|
-
autoload_at "active_record/connection_adapters/abstract/connection_pool" do
|
31
|
-
autoload :ConnectionHandler
|
32
|
-
end
|
33
|
-
|
34
30
|
autoload_under "abstract" do
|
35
31
|
autoload :SchemaStatements
|
36
32
|
autoload :DatabaseStatements
|
37
33
|
autoload :DatabaseLimits
|
38
34
|
autoload :Quoting
|
39
|
-
autoload :
|
35
|
+
autoload :ConnectionHandler
|
40
36
|
autoload :QueryCache
|
41
37
|
autoload :Savepoints
|
42
38
|
end
|
43
39
|
|
40
|
+
autoload_at "active_record/connection_adapters/abstract/connection_pool" do
|
41
|
+
autoload :ConnectionPool
|
42
|
+
autoload :NullPool
|
43
|
+
end
|
44
|
+
|
44
45
|
autoload_at "active_record/connection_adapters/abstract/transaction" do
|
45
46
|
autoload :TransactionManager
|
46
47
|
autoload :NullTransaction
|
@@ -134,10 +134,8 @@ module ActiveRecord
|
|
134
134
|
# ActiveRecord::Base.connected_to(role: :reading, shard: :shard_one_replica) do
|
135
135
|
# Dog.first # finds first Dog record stored on the shard one replica
|
136
136
|
# end
|
137
|
-
|
138
|
-
|
139
|
-
def connected_to(database: nil, role: nil, shard: nil, prevent_writes: false, &blk)
|
140
|
-
if legacy_connection_handling
|
137
|
+
def connected_to(role: nil, shard: nil, prevent_writes: false, &blk)
|
138
|
+
if ActiveRecord.legacy_connection_handling
|
141
139
|
if self != Base
|
142
140
|
raise NotImplementedError, "`connected_to` can only be called on ActiveRecord::Base with legacy connection handling."
|
143
141
|
end
|
@@ -151,31 +149,15 @@ module ActiveRecord
|
|
151
149
|
end
|
152
150
|
end
|
153
151
|
|
154
|
-
|
155
|
-
raise ArgumentError, "`connected_to` cannot accept a `database` argument with any other arguments."
|
156
|
-
elsif database
|
157
|
-
ActiveSupport::Deprecation.warn("The database key in `connected_to` is deprecated. It will be removed in Rails 7.0.0 without replacement.")
|
158
|
-
|
159
|
-
if database.is_a?(Hash)
|
160
|
-
role, database = database.first
|
161
|
-
role = role.to_sym
|
162
|
-
end
|
163
|
-
|
164
|
-
db_config, owner_name = resolve_config_for_connection(database)
|
165
|
-
handler = lookup_connection_handler(role)
|
166
|
-
|
167
|
-
handler.establish_connection(db_config, owner_name: owner_name, role: role)
|
168
|
-
|
169
|
-
with_handler(role, &blk)
|
170
|
-
elsif role || shard
|
171
|
-
unless role
|
172
|
-
raise ArgumentError, "`connected_to` cannot accept a `shard` argument without a `role`."
|
173
|
-
end
|
174
|
-
|
175
|
-
with_role_and_shard(role, shard, prevent_writes, &blk)
|
176
|
-
else
|
152
|
+
unless role || shard
|
177
153
|
raise ArgumentError, "must provide a `shard` and/or `role`."
|
178
154
|
end
|
155
|
+
|
156
|
+
unless role
|
157
|
+
raise ArgumentError, "`connected_to` cannot accept a `shard` argument without a `role`."
|
158
|
+
end
|
159
|
+
|
160
|
+
with_role_and_shard(role, shard, prevent_writes, &blk)
|
179
161
|
end
|
180
162
|
|
181
163
|
# Connects a role and/or shard to the provided connection names. Optionally +prevent_writes+
|
@@ -194,7 +176,7 @@ module ActiveRecord
|
|
194
176
|
def connected_to_many(*classes, role:, shard: nil, prevent_writes: false)
|
195
177
|
classes = classes.flatten
|
196
178
|
|
197
|
-
if legacy_connection_handling
|
179
|
+
if ActiveRecord.legacy_connection_handling
|
198
180
|
raise NotImplementedError, "connected_to_many is not available with legacy connection handling"
|
199
181
|
end
|
200
182
|
|
@@ -202,7 +184,7 @@ module ActiveRecord
|
|
202
184
|
raise NotImplementedError, "connected_to_many can only be called on ActiveRecord::Base."
|
203
185
|
end
|
204
186
|
|
205
|
-
prevent_writes = true if role == reading_role
|
187
|
+
prevent_writes = true if role == ActiveRecord.reading_role
|
206
188
|
|
207
189
|
connected_to_stack << { role: role, shard: shard, prevent_writes: prevent_writes, klasses: classes }
|
208
190
|
yield
|
@@ -218,11 +200,11 @@ module ActiveRecord
|
|
218
200
|
# It is not recommended to use this method in a request since it
|
219
201
|
# does not yield to a block like +connected_to+.
|
220
202
|
def connecting_to(role: default_role, shard: default_shard, prevent_writes: false)
|
221
|
-
if legacy_connection_handling
|
203
|
+
if ActiveRecord.legacy_connection_handling
|
222
204
|
raise NotImplementedError, "`connecting_to` is not available with `legacy_connection_handling`."
|
223
205
|
end
|
224
206
|
|
225
|
-
prevent_writes = true if role == reading_role
|
207
|
+
prevent_writes = true if role == ActiveRecord.reading_role
|
226
208
|
|
227
209
|
self.connected_to_stack << { role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self] }
|
228
210
|
end
|
@@ -239,7 +221,7 @@ module ActiveRecord
|
|
239
221
|
# See +READ_QUERY+ for the queries that are blocked by this
|
240
222
|
# method.
|
241
223
|
def while_preventing_writes(enabled = true, &block)
|
242
|
-
if legacy_connection_handling
|
224
|
+
if ActiveRecord.legacy_connection_handling
|
243
225
|
connection_handler.while_preventing_writes(enabled, &block)
|
244
226
|
else
|
245
227
|
connected_to(role: current_role, prevent_writes: enabled, &block)
|
@@ -257,8 +239,8 @@ module ActiveRecord
|
|
257
239
|
end
|
258
240
|
|
259
241
|
def lookup_connection_handler(handler_key) # :nodoc:
|
260
|
-
if ActiveRecord
|
261
|
-
handler_key ||= ActiveRecord
|
242
|
+
if ActiveRecord.legacy_connection_handling
|
243
|
+
handler_key ||= ActiveRecord.writing_role
|
262
244
|
connection_handlers[handler_key] ||= ActiveRecord::ConnectionAdapters::ConnectionHandler.new
|
263
245
|
else
|
264
246
|
ActiveRecord::Base.connection_handler
|
@@ -267,7 +249,7 @@ module ActiveRecord
|
|
267
249
|
|
268
250
|
# Clears the query cache for all connections associated with the current thread.
|
269
251
|
def clear_query_caches_for_current_thread
|
270
|
-
if ActiveRecord
|
252
|
+
if ActiveRecord.legacy_connection_handling
|
271
253
|
ActiveRecord::Base.connection_handlers.each_value do |handler|
|
272
254
|
clear_on_handler(handler)
|
273
255
|
end
|
@@ -294,7 +276,7 @@ module ActiveRecord
|
|
294
276
|
end
|
295
277
|
|
296
278
|
def primary_class? # :nodoc:
|
297
|
-
self == Base ||
|
279
|
+
self == Base || application_record_class?
|
298
280
|
end
|
299
281
|
|
300
282
|
# Returns the configuration of the associated connection as a hash:
|
@@ -374,9 +356,9 @@ module ActiveRecord
|
|
374
356
|
end
|
375
357
|
|
376
358
|
def with_role_and_shard(role, shard, prevent_writes)
|
377
|
-
prevent_writes = true if role == reading_role
|
359
|
+
prevent_writes = true if role == ActiveRecord.reading_role
|
378
360
|
|
379
|
-
if ActiveRecord
|
361
|
+
if ActiveRecord.legacy_connection_handling
|
380
362
|
with_handler(role.to_sym) do
|
381
363
|
connection_handler.while_preventing_writes(prevent_writes) do
|
382
364
|
self.connected_to_stack << { shard: shard, klasses: [self] }
|