activerecord 6.1.3.2 → 7.0.0.alpha2
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 +734 -1058
- 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 +35 -7
- data/lib/active_record/associations/association_scope.rb +1 -3
- data/lib/active_record/associations/belongs_to_association.rb +16 -6
- 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 +24 -25
- 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 -49
- 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 +11 -1
- 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 +14 -7
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +5 -18
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -9
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +60 -16
- data/lib/active_record/connection_adapters/abstract/transaction.rb +17 -6
- data/lib/active_record/connection_adapters/abstract_adapter.rb +115 -69
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +96 -81
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +6 -2
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +33 -21
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +3 -0
- 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/pool_manager.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -12
- 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 -6
- 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 +157 -100
- data/lib/active_record/connection_adapters/schema_cache.rb +35 -4
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +0 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +23 -17
- 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 +8 -5
- data/lib/active_record/connection_handling.rb +20 -38
- data/lib/active_record/core.rb +129 -117
- 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 +18 -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 +44 -46
- 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 +39 -6
- data/lib/active_record/integration.rb +1 -1
- data/lib/active_record/internal_metadata.rb +3 -5
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- 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 +83 -1
- 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 +46 -32
- 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 +83 -58
- 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 +42 -25
- data/lib/active_record/relation/delegation.rb +6 -6
- data/lib/active_record/relation/finder_methods.rb +32 -23
- 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 +233 -50
- 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 +22 -15
- data/lib/active_record/relation.rb +170 -87
- 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 +62 -15
- 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/statement_cache.rb +2 -2
- data/lib/active_record/tasks/database_tasks.rb +107 -23
- 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 +45 -4
- 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/validations/numericality.rb +1 -1
- data/lib/active_record.rb +170 -2
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/composite.rb +3 -3
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- 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/homogeneous_in.rb +4 -0
- 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 +3 -3
- 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 +44 -3
- 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 +55 -16
@@ -9,7 +9,15 @@ module ActiveRecord
|
|
9
9
|
return unless File.file?(filename)
|
10
10
|
|
11
11
|
read(filename) do |file|
|
12
|
-
filename.include?(".dump")
|
12
|
+
if filename.include?(".dump")
|
13
|
+
Marshal.load(file)
|
14
|
+
else
|
15
|
+
if YAML.respond_to?(:unsafe_load)
|
16
|
+
YAML.unsafe_load(file)
|
17
|
+
else
|
18
|
+
YAML.load(file)
|
19
|
+
end
|
20
|
+
end
|
13
21
|
end
|
14
22
|
end
|
15
23
|
|
@@ -78,6 +86,7 @@ module ActiveRecord
|
|
78
86
|
|
79
87
|
# A cached lookup for table existence.
|
80
88
|
def data_source_exists?(name)
|
89
|
+
return if ignored_table?(name)
|
81
90
|
prepare_data_sources if @data_sources.empty?
|
82
91
|
return @data_sources[name] if @data_sources.key? name
|
83
92
|
|
@@ -100,6 +109,10 @@ module ActiveRecord
|
|
100
109
|
|
101
110
|
# Get the columns for a table
|
102
111
|
def columns(table_name)
|
112
|
+
if ignored_table?(table_name)
|
113
|
+
raise ActiveRecord::StatementInvalid, "Table '#{table_name}' doesn't exist"
|
114
|
+
end
|
115
|
+
|
103
116
|
@columns.fetch(table_name) do
|
104
117
|
@columns[deep_deduplicate(table_name)] = deep_deduplicate(connection.columns(table_name))
|
105
118
|
end
|
@@ -120,7 +133,11 @@ module ActiveRecord
|
|
120
133
|
|
121
134
|
def indexes(table_name)
|
122
135
|
@indexes.fetch(table_name) do
|
123
|
-
|
136
|
+
if data_source_exists?(table_name)
|
137
|
+
@indexes[deep_deduplicate(table_name)] = deep_deduplicate(connection.indexes(table_name))
|
138
|
+
else
|
139
|
+
[]
|
140
|
+
end
|
124
141
|
end
|
125
142
|
end
|
126
143
|
|
@@ -154,7 +171,7 @@ module ActiveRecord
|
|
154
171
|
|
155
172
|
def dump_to(filename)
|
156
173
|
clear!
|
157
|
-
|
174
|
+
tables_to_cache.each { |table| add(table) }
|
158
175
|
open(filename) { |f|
|
159
176
|
if filename.include?(".dump")
|
160
177
|
f.write(Marshal.dump(self))
|
@@ -178,6 +195,18 @@ module ActiveRecord
|
|
178
195
|
end
|
179
196
|
|
180
197
|
private
|
198
|
+
def tables_to_cache
|
199
|
+
connection.data_sources.reject do |table|
|
200
|
+
ignored_table?(table)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def ignored_table?(table_name)
|
205
|
+
ActiveRecord.schema_cache_ignored_tables.any? do |ignored|
|
206
|
+
ignored === table_name
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
181
210
|
def reset_version!
|
182
211
|
@version = connection.migration_context.current_version
|
183
212
|
end
|
@@ -204,7 +233,9 @@ module ActiveRecord
|
|
204
233
|
end
|
205
234
|
|
206
235
|
def prepare_data_sources
|
207
|
-
|
236
|
+
tables_to_cache.each do |source|
|
237
|
+
@data_sources[source] = true
|
238
|
+
end
|
208
239
|
end
|
209
240
|
|
210
241
|
def open(filename)
|
@@ -18,10 +18,9 @@ module ActiveRecord
|
|
18
18
|
SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", []))
|
19
19
|
end
|
20
20
|
|
21
|
-
def execute(sql, name = nil)
|
22
|
-
|
23
|
-
|
24
|
-
end
|
21
|
+
def execute(sql, name = nil) # :nodoc:
|
22
|
+
sql = transform_query(sql)
|
23
|
+
check_if_write_query(sql)
|
25
24
|
|
26
25
|
materialize_transactions
|
27
26
|
mark_transaction_written_if_write(sql)
|
@@ -33,17 +32,16 @@ module ActiveRecord
|
|
33
32
|
end
|
34
33
|
end
|
35
34
|
|
36
|
-
def exec_query(sql, name = nil, binds = [], prepare: false)
|
37
|
-
|
38
|
-
|
39
|
-
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)
|
40
38
|
|
41
39
|
materialize_transactions
|
42
40
|
mark_transaction_written_if_write(sql)
|
43
41
|
|
44
42
|
type_casted_binds = type_casted_binds(binds)
|
45
43
|
|
46
|
-
log(sql, name, binds, type_casted_binds) do
|
44
|
+
log(sql, name, binds, type_casted_binds, async: async) do
|
47
45
|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
48
46
|
# Don't cache statements if they are not prepared
|
49
47
|
unless prepare
|
@@ -70,13 +68,13 @@ module ActiveRecord
|
|
70
68
|
end
|
71
69
|
end
|
72
70
|
|
73
|
-
def exec_delete(sql, name = "SQL", binds = [])
|
71
|
+
def exec_delete(sql, name = "SQL", binds = []) # :nodoc:
|
74
72
|
exec_query(sql, name, binds)
|
75
73
|
@connection.changes
|
76
74
|
end
|
77
75
|
alias :exec_update :exec_delete
|
78
76
|
|
79
|
-
def begin_isolated_db_transaction(isolation)
|
77
|
+
def begin_isolated_db_transaction(isolation) # :nodoc:
|
80
78
|
raise TransactionIsolationError, "SQLite3 only supports the `read_uncommitted` transaction isolation level" if isolation != :read_uncommitted
|
81
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?
|
82
80
|
|
@@ -85,20 +83,29 @@ module ActiveRecord
|
|
85
83
|
begin_db_transaction
|
86
84
|
end
|
87
85
|
|
88
|
-
def begin_db_transaction
|
86
|
+
def begin_db_transaction # :nodoc:
|
89
87
|
log("begin transaction", "TRANSACTION") { @connection.transaction }
|
90
88
|
end
|
91
89
|
|
92
|
-
def commit_db_transaction
|
90
|
+
def commit_db_transaction # :nodoc:
|
93
91
|
log("commit transaction", "TRANSACTION") { @connection.commit }
|
94
92
|
reset_read_uncommitted
|
95
93
|
end
|
96
94
|
|
97
|
-
def exec_rollback_db_transaction
|
95
|
+
def exec_rollback_db_transaction # :nodoc:
|
98
96
|
log("rollback transaction", "TRANSACTION") { @connection.rollback }
|
99
97
|
reset_read_uncommitted
|
100
98
|
end
|
101
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
|
+
|
102
109
|
private
|
103
110
|
def reset_read_uncommitted
|
104
111
|
read_uncommitted = Thread.current.thread_variable_get("read_uncommitted")
|
@@ -108,11 +115,10 @@ module ActiveRecord
|
|
108
115
|
end
|
109
116
|
|
110
117
|
def execute_batch(statements, name = nil)
|
118
|
+
statements = statements.map { |sql| transform_query(sql) }
|
111
119
|
sql = combine_multi_statements(statements)
|
112
120
|
|
113
|
-
|
114
|
-
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
115
|
-
end
|
121
|
+
check_if_write_query(sql)
|
116
122
|
|
117
123
|
materialize_transactions
|
118
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
|
@@ -12,6 +12,8 @@ module ActiveRecord
|
|
12
12
|
autoload :PoolConfig
|
13
13
|
autoload :PoolManager
|
14
14
|
autoload :LegacyPoolManager
|
15
|
+
autoload :SchemaCache
|
16
|
+
autoload :Deduplicable
|
15
17
|
|
16
18
|
autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
|
17
19
|
autoload :IndexDefinition
|
@@ -25,20 +27,21 @@ module ActiveRecord
|
|
25
27
|
autoload :ReferenceDefinition
|
26
28
|
end
|
27
29
|
|
28
|
-
autoload_at "active_record/connection_adapters/abstract/connection_pool" do
|
29
|
-
autoload :ConnectionHandler
|
30
|
-
end
|
31
|
-
|
32
30
|
autoload_under "abstract" do
|
33
31
|
autoload :SchemaStatements
|
34
32
|
autoload :DatabaseStatements
|
35
33
|
autoload :DatabaseLimits
|
36
34
|
autoload :Quoting
|
37
|
-
autoload :
|
35
|
+
autoload :ConnectionHandler
|
38
36
|
autoload :QueryCache
|
39
37
|
autoload :Savepoints
|
40
38
|
end
|
41
39
|
|
40
|
+
autoload_at "active_record/connection_adapters/abstract/connection_pool" do
|
41
|
+
autoload :ConnectionPool
|
42
|
+
autoload :NullPool
|
43
|
+
end
|
44
|
+
|
42
45
|
autoload_at "active_record/connection_adapters/abstract/transaction" do
|
43
46
|
autoload :TransactionManager
|
44
47
|
autoload :NullTransaction
|