activerecord 7.2.2.1 → 8.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +564 -753
- data/README.rdoc +2 -2
- data/lib/active_record/association_relation.rb +2 -1
- data/lib/active_record/associations/alias_tracker.rb +6 -4
- data/lib/active_record/associations/association.rb +35 -11
- data/lib/active_record/associations/belongs_to_association.rb +18 -2
- data/lib/active_record/associations/builder/association.rb +23 -11
- data/lib/active_record/associations/builder/belongs_to.rb +17 -4
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +10 -8
- data/lib/active_record/associations/collection_proxy.rb +22 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +25 -27
- data/lib/active_record/associations/join_dependency.rb +4 -2
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +192 -24
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/primary_key.rb +4 -8
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +17 -4
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
- data/lib/active_record/attribute_methods.rb +24 -19
- data/lib/active_record/attributes.rb +40 -26
- data/lib/active_record/autosave_association.rb +91 -39
- data/lib/active_record/base.rb +3 -4
- data/lib/active_record/coders/json.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +51 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +458 -117
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +136 -74
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +44 -11
- data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +37 -36
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +122 -29
- data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
- data/lib/active_record/connection_adapters/abstract_adapter.rb +175 -87
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +77 -58
- data/lib/active_record/connection_adapters/column.rb +17 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +7 -9
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +73 -46
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -11
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -45
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +28 -45
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +69 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +140 -64
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -105
- data/lib/active_record/connection_adapters/schema_cache.rb +3 -5
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +13 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +112 -42
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +38 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +2 -19
- data/lib/active_record/connection_adapters.rb +1 -56
- data/lib/active_record/connection_handling.rb +37 -10
- data/lib/active_record/core.rb +61 -25
- data/lib/active_record/counter_cache.rb +34 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
- data/lib/active_record/database_configurations/database_config.rb +9 -1
- data/lib/active_record/database_configurations/hash_config.rb +67 -9
- data/lib/active_record/database_configurations/url_config.rb +13 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +19 -19
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +9 -9
- data/lib/active_record/encryption/encrypted_attribute_type.rb +12 -3
- data/lib/active_record/encryption/encryptor.rb +49 -28
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +9 -2
- data/lib/active_record/enum.rb +46 -42
- data/lib/active_record/errors.rb +36 -12
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -2
- data/lib/active_record/filter_attribute_handler.rb +73 -0
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +2 -4
- data/lib/active_record/future_result.rb +13 -9
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/insert_all.rb +12 -7
- data/lib/active_record/locking/optimistic.rb +8 -1
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +3 -13
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +44 -11
- data/lib/active_record/migration/compatibility.rb +37 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +50 -43
- data/lib/active_record/model_schema.rb +38 -13
- data/lib/active_record/nested_attributes.rb +6 -6
- data/lib/active_record/persistence.rb +162 -133
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +104 -52
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +12 -12
- data/lib/active_record/railtie.rb +37 -32
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +26 -37
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +53 -21
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +147 -73
- data/lib/active_record/relation/calculations.rb +80 -63
- data/lib/active_record/relation/delegation.rb +25 -15
- data/lib/active_record/relation/finder_methods.rb +54 -37
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +22 -7
- data/lib/active_record/relation/query_attribute.rb +4 -2
- data/lib/active_record/relation/query_methods.rb +156 -95
- data/lib/active_record/relation/spawn_methods.rb +7 -7
- data/lib/active_record/relation/where_clause.rb +10 -11
- data/lib/active_record/relation.rb +122 -80
- data/lib/active_record/result.rb +109 -24
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +9 -6
- data/lib/active_record/schema_dumper.rb +47 -22
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +47 -18
- data/lib/active_record/statement_cache.rb +24 -20
- data/lib/active_record/store.rb +51 -22
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +6 -23
- data/lib/active_record/tasks/abstract_tasks.rb +76 -0
- data/lib/active_record/tasks/database_tasks.rb +85 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
- data/lib/active_record/test_databases.rb +14 -4
- data/lib/active_record/test_fixtures.rb +39 -2
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +39 -16
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +15 -2
- data/lib/active_record/type/serialized.rb +11 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +85 -50
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/crud.rb +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/select_manager.rb +13 -4
- data/lib/arel/table.rb +3 -7
- data/lib/arel/update_manager.rb +5 -0
- data/lib/arel/visitors/dot.rb +2 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +6 -22
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +17 -17
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
- data/lib/active_record/relation/record_fetch_warning.rb +0 -52
|
@@ -5,12 +5,37 @@ module ActiveRecord
|
|
|
5
5
|
module SQLite3
|
|
6
6
|
class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
|
|
7
7
|
private
|
|
8
|
+
def virtual_tables(stream)
|
|
9
|
+
virtual_tables = @connection.virtual_tables
|
|
10
|
+
if virtual_tables.any?
|
|
11
|
+
stream.puts
|
|
12
|
+
stream.puts " # Virtual tables defined in this database."
|
|
13
|
+
stream.puts " # Note that virtual tables may not work with other database engines. Be careful if changing database."
|
|
14
|
+
virtual_tables.sort.each do |table_name, options|
|
|
15
|
+
module_name, arguments = options
|
|
16
|
+
stream.puts " create_virtual_table #{table_name.inspect}, #{module_name.inspect}, #{arguments.split(", ").inspect}"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
8
21
|
def default_primary_key?(column)
|
|
9
|
-
schema_type(column) == :integer
|
|
22
|
+
schema_type(column) == :integer && primary_key_has_autoincrement?
|
|
10
23
|
end
|
|
11
24
|
|
|
12
25
|
def explicit_primary_key_default?(column)
|
|
13
|
-
column.bigint?
|
|
26
|
+
column.bigint? || (column.type == :integer && !primary_key_has_autoincrement?)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def primary_key_has_autoincrement?
|
|
30
|
+
return false unless table_name
|
|
31
|
+
|
|
32
|
+
table_sql = @connection.query_value(<<~SQL, "SCHEMA")
|
|
33
|
+
SELECT sql FROM sqlite_master WHERE name = #{@connection.quote(table_name)} AND type = 'table'
|
|
34
|
+
UNION ALL
|
|
35
|
+
SELECT sql FROM sqlite_temp_master WHERE name = #{@connection.quote(table_name)} AND type = 'table'
|
|
36
|
+
SQL
|
|
37
|
+
|
|
38
|
+
table_sql.to_s.match?(/\bAUTOINCREMENT\b/i)
|
|
14
39
|
end
|
|
15
40
|
|
|
16
41
|
def prepare_column_options(column)
|
|
@@ -27,6 +27,7 @@ module ActiveRecord
|
|
|
27
27
|
col["name"]
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
where = where.sub(/\s*\/\*.*\*\/\z/, "") if where
|
|
30
31
|
orders = {}
|
|
31
32
|
|
|
32
33
|
if columns.any?(&:nil?) # index created with an expression
|
|
@@ -62,26 +63,21 @@ module ActiveRecord
|
|
|
62
63
|
end
|
|
63
64
|
|
|
64
65
|
def remove_foreign_key(from_table, to_table = nil, **options)
|
|
65
|
-
return if options.delete(:if_exists)
|
|
66
|
+
return if options.delete(:if_exists) && !foreign_key_exists?(from_table, to_table, **options.slice(:column))
|
|
66
67
|
|
|
67
68
|
to_table ||= options[:to_table]
|
|
68
69
|
options = options.except(:name, :to_table, :validate)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
fkey = foreign_keys.detect do |fk|
|
|
72
|
-
table = to_table || begin
|
|
73
|
-
table = options[:column].to_s.delete_suffix("_id")
|
|
74
|
-
Base.pluralize_table_names ? table.pluralize : table
|
|
75
|
-
end
|
|
76
|
-
table = strip_table_name_prefix_and_suffix(table)
|
|
77
|
-
fk_to_table = strip_table_name_prefix_and_suffix(fk.to_table)
|
|
78
|
-
fk_to_table == table && options.all? { |k, v| fk.options[k].to_s == v.to_s }
|
|
79
|
-
end || raise(ArgumentError, "Table '#{from_table}' has no foreign key for #{to_table || options}")
|
|
70
|
+
fkey = foreign_key_for!(from_table, to_table: to_table, **options)
|
|
80
71
|
|
|
72
|
+
foreign_keys = foreign_keys(from_table)
|
|
81
73
|
foreign_keys.delete(fkey)
|
|
82
74
|
alter_table(from_table, foreign_keys)
|
|
83
75
|
end
|
|
84
76
|
|
|
77
|
+
def virtual_table_exists?(table_name)
|
|
78
|
+
query_values(data_source_sql(table_name, type: "VIRTUAL TABLE"), "SCHEMA").any?
|
|
79
|
+
end
|
|
80
|
+
|
|
85
81
|
def check_constraints(table_name)
|
|
86
82
|
table_sql = query_value(<<-SQL, "SCHEMA")
|
|
87
83
|
SELECT sql
|
|
@@ -151,6 +147,7 @@ module ActiveRecord
|
|
|
151
147
|
|
|
152
148
|
Column.new(
|
|
153
149
|
field["name"],
|
|
150
|
+
lookup_cast_type(field["type"]),
|
|
154
151
|
default_value,
|
|
155
152
|
type_metadata,
|
|
156
153
|
field["notnull"].to_i == 0,
|
|
@@ -176,7 +173,8 @@ module ActiveRecord
|
|
|
176
173
|
scope = quoted_scope(name, type: type)
|
|
177
174
|
scope[:type] ||= "'table','view'"
|
|
178
175
|
|
|
179
|
-
sql = +"SELECT name FROM
|
|
176
|
+
sql = +"SELECT name FROM pragma_table_list WHERE schema <> 'temp'"
|
|
177
|
+
sql << " AND name NOT IN ('sqlite_sequence', 'sqlite_schema')"
|
|
180
178
|
sql << " AND name = #{scope[:name]}" if scope[:name]
|
|
181
179
|
sql << " AND type IN (#{scope[:type]})"
|
|
182
180
|
sql
|
|
@@ -189,6 +187,8 @@ module ActiveRecord
|
|
|
189
187
|
"'table'"
|
|
190
188
|
when "VIEW"
|
|
191
189
|
"'view'"
|
|
190
|
+
when "VIRTUAL TABLE"
|
|
191
|
+
"'virtual'"
|
|
192
192
|
end
|
|
193
193
|
scope = {}
|
|
194
194
|
scope[:name] = quote(name) if name
|
|
@@ -11,19 +11,38 @@ require "active_record/connection_adapters/sqlite3/schema_definitions"
|
|
|
11
11
|
require "active_record/connection_adapters/sqlite3/schema_dumper"
|
|
12
12
|
require "active_record/connection_adapters/sqlite3/schema_statements"
|
|
13
13
|
|
|
14
|
-
gem "sqlite3", ">= 1
|
|
14
|
+
gem "sqlite3", ">= 2.1"
|
|
15
15
|
require "sqlite3"
|
|
16
16
|
|
|
17
|
+
# Suppress the warning that SQLite3 issues when open writable connections are carried across fork()
|
|
18
|
+
SQLite3::ForkSafety.suppress_warnings!
|
|
19
|
+
|
|
17
20
|
module ActiveRecord
|
|
18
21
|
module ConnectionAdapters # :nodoc:
|
|
19
|
-
# = Active Record SQLite3 Adapter
|
|
22
|
+
# = Active Record \SQLite3 Adapter
|
|
23
|
+
#
|
|
24
|
+
# The \SQLite3 adapter works with the sqlite3[https://sparklemotion.github.io/sqlite3-ruby/]
|
|
25
|
+
# driver.
|
|
26
|
+
#
|
|
27
|
+
# ==== Options
|
|
20
28
|
#
|
|
21
|
-
#
|
|
22
|
-
# (
|
|
29
|
+
# * +:database+ (String): Filesystem path to the database file.
|
|
30
|
+
# * +:statement_limit+ (Integer): Maximum number of prepared statements to cache per database connection. (default: 1000)
|
|
31
|
+
# * +:timeout+ (Integer): Timeout in milliseconds to use when waiting for a lock. (default: no wait)
|
|
32
|
+
# * +:strict+ (Boolean): Enable or disable strict mode. When enabled, this will
|
|
33
|
+
# {disallow double-quoted string literals in SQL
|
|
34
|
+
# statements}[https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted].
|
|
35
|
+
# (default: see strict_strings_by_default)
|
|
36
|
+
# * +:extensions+ (Array): (<b>requires sqlite3 v2.4.0</b>) Each entry specifies a sqlite extension
|
|
37
|
+
# to load for this database. The entry may be a filesystem path, or the name of a class that
|
|
38
|
+
# responds to +.to_path+ to provide the filesystem path for the extension. See {sqlite3-ruby
|
|
39
|
+
# documentation}[https://sparklemotion.github.io/sqlite3-ruby/SQLite3/Database.html#class-SQLite3::Database-label-SQLite+Extensions]
|
|
40
|
+
# for more information.
|
|
23
41
|
#
|
|
24
|
-
#
|
|
42
|
+
# There may be other options available specific to the SQLite3 driver. Please read the
|
|
43
|
+
# documentation for
|
|
44
|
+
# {SQLite3::Database.new}[https://sparklemotion.github.io/sqlite3-ruby/SQLite3/Database.html#method-c-new]
|
|
25
45
|
#
|
|
26
|
-
# * <tt>:database</tt> - Path to the database file.
|
|
27
46
|
class SQLite3Adapter < AbstractAdapter
|
|
28
47
|
ADAPTER_NAME = "SQLite"
|
|
29
48
|
|
|
@@ -43,9 +62,13 @@ module ActiveRecord
|
|
|
43
62
|
|
|
44
63
|
args << "-#{options[:mode]}" if options[:mode]
|
|
45
64
|
args << "-header" if options[:header]
|
|
46
|
-
args << File.expand_path(config.database, Rails.
|
|
65
|
+
args << File.expand_path(config.database, defined?(Rails.root) ? Rails.root : nil)
|
|
66
|
+
|
|
67
|
+
find_cmd_and_exec(ActiveRecord.database_cli[:sqlite], *args)
|
|
68
|
+
end
|
|
47
69
|
|
|
48
|
-
|
|
70
|
+
def native_database_types # :nodoc:
|
|
71
|
+
NATIVE_DATABASE_TYPES
|
|
49
72
|
end
|
|
50
73
|
end
|
|
51
74
|
|
|
@@ -55,12 +78,19 @@ module ActiveRecord
|
|
|
55
78
|
|
|
56
79
|
##
|
|
57
80
|
# :singleton-method:
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
#
|
|
81
|
+
#
|
|
82
|
+
# Configure the SQLite3Adapter to be used in a "strict strings" mode. When enabled, this will
|
|
83
|
+
# {disallow double-quoted string literals in SQL
|
|
84
|
+
# statements}[https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted],
|
|
85
|
+
# which may prevent some typographical errors like creating an index for a non-existent
|
|
86
|
+
# column. The default is +false+.
|
|
87
|
+
#
|
|
61
88
|
# If you wish to enable this mode you can add the following line to your application.rb file:
|
|
62
89
|
#
|
|
63
90
|
# config.active_record.sqlite3_adapter_strict_strings_by_default = true
|
|
91
|
+
#
|
|
92
|
+
# This can also be configured on individual databases by setting the +strict:+ option.
|
|
93
|
+
#
|
|
64
94
|
class_attribute :strict_strings_by_default, default: false
|
|
65
95
|
|
|
66
96
|
NATIVE_DATABASE_TYPES = {
|
|
@@ -119,9 +149,19 @@ module ActiveRecord
|
|
|
119
149
|
end
|
|
120
150
|
end
|
|
121
151
|
|
|
152
|
+
@previous_read_uncommitted = nil
|
|
122
153
|
@config[:strict] = ConnectionAdapters::SQLite3Adapter.strict_strings_by_default unless @config.key?(:strict)
|
|
123
|
-
|
|
124
|
-
|
|
154
|
+
|
|
155
|
+
extensions = @config.fetch(:extensions, []).map do |extension|
|
|
156
|
+
extension.safe_constantize || extension
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
@connection_parameters = @config.merge(
|
|
160
|
+
database: @config[:database].to_s,
|
|
161
|
+
results_as_hash: true,
|
|
162
|
+
default_transaction_mode: :immediate,
|
|
163
|
+
extensions: extensions
|
|
164
|
+
)
|
|
125
165
|
end
|
|
126
166
|
|
|
127
167
|
def database_exists?
|
|
@@ -145,7 +185,7 @@ module ActiveRecord
|
|
|
145
185
|
end
|
|
146
186
|
|
|
147
187
|
def supports_expression_index?
|
|
148
|
-
|
|
188
|
+
true
|
|
149
189
|
end
|
|
150
190
|
|
|
151
191
|
def requires_reloading?
|
|
@@ -173,7 +213,7 @@ module ActiveRecord
|
|
|
173
213
|
end
|
|
174
214
|
|
|
175
215
|
def supports_common_table_expressions?
|
|
176
|
-
|
|
216
|
+
true
|
|
177
217
|
end
|
|
178
218
|
|
|
179
219
|
def supports_insert_returning?
|
|
@@ -199,7 +239,12 @@ module ActiveRecord
|
|
|
199
239
|
!(@raw_connection.nil? || @raw_connection.closed?)
|
|
200
240
|
end
|
|
201
241
|
|
|
202
|
-
|
|
242
|
+
def active?
|
|
243
|
+
if connected?
|
|
244
|
+
verified!
|
|
245
|
+
true
|
|
246
|
+
end
|
|
247
|
+
end
|
|
203
248
|
|
|
204
249
|
alias :reset! :reconnect!
|
|
205
250
|
|
|
@@ -216,10 +261,6 @@ module ActiveRecord
|
|
|
216
261
|
true
|
|
217
262
|
end
|
|
218
263
|
|
|
219
|
-
def native_database_types # :nodoc:
|
|
220
|
-
NATIVE_DATABASE_TYPES
|
|
221
|
-
end
|
|
222
|
-
|
|
223
264
|
# Returns the current database encoding format as a string, e.g. 'UTF-8'
|
|
224
265
|
def encoding
|
|
225
266
|
any_raw_connection.encoding.to_s
|
|
@@ -278,6 +319,38 @@ module ActiveRecord
|
|
|
278
319
|
exec_query "DROP INDEX #{quote_column_name(index_name)}"
|
|
279
320
|
end
|
|
280
321
|
|
|
322
|
+
VIRTUAL_TABLE_REGEX = /USING\s+(\w+)\s*\((.+)\)/i
|
|
323
|
+
|
|
324
|
+
# Returns a list of defined virtual tables
|
|
325
|
+
def virtual_tables
|
|
326
|
+
query = <<~SQL
|
|
327
|
+
SELECT name, sql FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL %';
|
|
328
|
+
SQL
|
|
329
|
+
|
|
330
|
+
exec_query(query, "SCHEMA").cast_values.each_with_object({}) do |row, memo|
|
|
331
|
+
table_name, sql = row[0], row[1]
|
|
332
|
+
_, module_name, arguments = sql.match(VIRTUAL_TABLE_REGEX).to_a
|
|
333
|
+
memo[table_name] = [module_name, arguments]
|
|
334
|
+
end.to_a
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
# Creates a virtual table
|
|
338
|
+
#
|
|
339
|
+
# Example:
|
|
340
|
+
# create_virtual_table :emails, :fts5, ['sender', 'title', 'body']
|
|
341
|
+
def create_virtual_table(table_name, module_name, values)
|
|
342
|
+
exec_query "CREATE VIRTUAL TABLE IF NOT EXISTS #{table_name} USING #{module_name} (#{values.join(", ")})"
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# Drops a virtual table
|
|
346
|
+
#
|
|
347
|
+
# Although this command ignores +module_name+ and +values+,
|
|
348
|
+
# it can be helpful to provide these in a migration's +change+ method so it can be reverted.
|
|
349
|
+
# In that case, +module_name+, +values+ and +options+ will be used by #create_virtual_table.
|
|
350
|
+
def drop_virtual_table(table_name, module_name, values, **options)
|
|
351
|
+
drop_table(table_name)
|
|
352
|
+
end
|
|
353
|
+
|
|
281
354
|
# Renames a table.
|
|
282
355
|
#
|
|
283
356
|
# Example:
|
|
@@ -367,7 +440,7 @@ module ActiveRecord
|
|
|
367
440
|
end
|
|
368
441
|
alias :add_belongs_to :add_reference
|
|
369
442
|
|
|
370
|
-
FK_REGEX = /.*FOREIGN KEY\s+\("(
|
|
443
|
+
FK_REGEX = /.*FOREIGN KEY\s+\("([^"]+)"\)\s+REFERENCES\s+"(\w+)"\s+\("(\w+)"\)/
|
|
371
444
|
DEFERRABLE_REGEX = /DEFERRABLE INITIALLY (\w+)/
|
|
372
445
|
def foreign_keys(table_name)
|
|
373
446
|
# SQLite returns 1 row for each column of composite foreign keys.
|
|
@@ -428,17 +501,13 @@ module ActiveRecord
|
|
|
428
501
|
@config.fetch(:flags, 0).anybits?(::SQLite3::Constants::Open::SHAREDCACHE)
|
|
429
502
|
end
|
|
430
503
|
|
|
431
|
-
def use_insert_returning?
|
|
432
|
-
@use_insert_returning
|
|
433
|
-
end
|
|
434
|
-
|
|
435
504
|
def get_database_version # :nodoc:
|
|
436
505
|
SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)", "SCHEMA"))
|
|
437
506
|
end
|
|
438
507
|
|
|
439
508
|
def check_version # :nodoc:
|
|
440
|
-
if database_version < "3.
|
|
441
|
-
raise "Your version of SQLite (#{database_version}) is too old. Active Record supports SQLite >= 3.
|
|
509
|
+
if database_version < "3.23.0"
|
|
510
|
+
raise "Your version of SQLite (#{database_version}) is too old. Active Record supports SQLite >= 3.23.0."
|
|
442
511
|
end
|
|
443
512
|
end
|
|
444
513
|
|
|
@@ -494,6 +563,8 @@ module ActiveRecord
|
|
|
494
563
|
# Binary columns
|
|
495
564
|
when /x'(.*)'/
|
|
496
565
|
[ $1 ].pack("H*")
|
|
566
|
+
when "TRUE", "FALSE"
|
|
567
|
+
default
|
|
497
568
|
else
|
|
498
569
|
# Anything else is blank or some function
|
|
499
570
|
# and we can't know the value of that, so return nil.
|
|
@@ -542,8 +613,8 @@ module ActiveRecord
|
|
|
542
613
|
yield definition if block_given?
|
|
543
614
|
end
|
|
544
615
|
|
|
545
|
-
|
|
546
|
-
|
|
616
|
+
disable_referential_integrity do
|
|
617
|
+
transaction do
|
|
547
618
|
move_table(table_name, altered_table_name, options.merge(temporary: true))
|
|
548
619
|
move_table(altered_table_name, table_name, &caller)
|
|
549
620
|
end
|
|
@@ -584,8 +655,8 @@ module ActiveRecord
|
|
|
584
655
|
column_options[:stored] = column.virtual_stored?
|
|
585
656
|
column_options[:type] = column.type
|
|
586
657
|
elsif column.has_default?
|
|
587
|
-
|
|
588
|
-
default =
|
|
658
|
+
# TODO: Remove fetch_cast_type and the need for connection after we release 8.1.
|
|
659
|
+
default = column.fetch_cast_type(self).deserialize(column.default)
|
|
589
660
|
default = -> { column.default_function } if default.nil?
|
|
590
661
|
|
|
591
662
|
unless column.auto_increment?
|
|
@@ -659,8 +730,12 @@ module ActiveRecord
|
|
|
659
730
|
NotNullViolation.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
660
731
|
elsif exception.message.match?(/FOREIGN KEY constraint failed/i)
|
|
661
732
|
InvalidForeignKey.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
733
|
+
elsif exception.message.match?(/CHECK constraint failed: .*/i)
|
|
734
|
+
CheckViolation.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
662
735
|
elsif exception.message.match?(/called on a closed database/i)
|
|
663
736
|
ConnectionNotEstablished.new(exception, connection_pool: @pool)
|
|
737
|
+
elsif exception.is_a?(::SQLite3::BusyException)
|
|
738
|
+
StatementTimeout.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
664
739
|
else
|
|
665
740
|
super
|
|
666
741
|
end
|
|
@@ -746,9 +821,9 @@ module ActiveRecord
|
|
|
746
821
|
|
|
747
822
|
def table_info(table_name)
|
|
748
823
|
if supports_virtual_columns?
|
|
749
|
-
internal_exec_query("PRAGMA table_xinfo(#{quote_table_name(table_name)})", "SCHEMA")
|
|
824
|
+
internal_exec_query("PRAGMA table_xinfo(#{quote_table_name(table_name)})", "SCHEMA", allow_retry: true)
|
|
750
825
|
else
|
|
751
|
-
internal_exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", "SCHEMA")
|
|
826
|
+
internal_exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", "SCHEMA", allow_retry: true)
|
|
752
827
|
end
|
|
753
828
|
end
|
|
754
829
|
|
|
@@ -775,15 +850,10 @@ module ActiveRecord
|
|
|
775
850
|
end
|
|
776
851
|
|
|
777
852
|
def configure_connection
|
|
778
|
-
if @config[:timeout]
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
@raw_connection.
|
|
782
|
-
elsif @config[:retries]
|
|
783
|
-
retries = self.class.type_cast_config_to_integer(@config[:retries])
|
|
784
|
-
raw_connection.busy_handler do |count|
|
|
785
|
-
count <= retries
|
|
786
|
-
end
|
|
853
|
+
if @config[:timeout]
|
|
854
|
+
timeout = self.class.type_cast_config_to_integer(@config[:timeout])
|
|
855
|
+
raise TypeError, "timeout must be integer, not #{timeout}" unless timeout.is_a?(Integer)
|
|
856
|
+
@raw_connection.busy_handler_timeout = timeout
|
|
787
857
|
end
|
|
788
858
|
|
|
789
859
|
super
|
|
@@ -4,93 +4,64 @@ module ActiveRecord
|
|
|
4
4
|
module ConnectionAdapters
|
|
5
5
|
module Trilogy
|
|
6
6
|
module DatabaseStatements
|
|
7
|
-
def internal_exec_query(sql, name = "SQL", binds = [], prepare: false, async: false, allow_retry: false) # :nodoc:
|
|
8
|
-
sql = transform_query(sql)
|
|
9
|
-
check_if_write_query(sql)
|
|
10
|
-
mark_transaction_written_if_write(sql)
|
|
11
|
-
|
|
12
|
-
result = raw_execute(sql, name, async: async, allow_retry: allow_retry)
|
|
13
|
-
ActiveRecord::Result.new(result.fields, result.to_a)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
7
|
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil, returning: nil) # :nodoc:
|
|
17
|
-
sql = transform_query(sql)
|
|
18
|
-
check_if_write_query(sql)
|
|
19
|
-
mark_transaction_written_if_write(sql)
|
|
20
|
-
|
|
21
8
|
sql, _binds = sql_for_insert(sql, pk, binds, returning)
|
|
22
|
-
|
|
9
|
+
internal_execute(sql, name)
|
|
23
10
|
end
|
|
24
11
|
|
|
25
|
-
def exec_delete(sql, name = nil, binds = []) # :nodoc:
|
|
26
|
-
sql = transform_query(sql)
|
|
27
|
-
check_if_write_query(sql)
|
|
28
|
-
mark_transaction_written_if_write(sql)
|
|
29
|
-
|
|
30
|
-
result = raw_execute(to_sql(sql, binds), name)
|
|
31
|
-
result.affected_rows
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
alias :exec_update :exec_delete # :nodoc:
|
|
35
|
-
|
|
36
12
|
private
|
|
37
|
-
def
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
result = conn.query(sql)
|
|
42
|
-
while conn.more_results_exist?
|
|
43
|
-
conn.next_result
|
|
44
|
-
end
|
|
45
|
-
verified!
|
|
46
|
-
handle_warnings(sql)
|
|
47
|
-
notification_payload[:row_count] = result.count
|
|
48
|
-
result
|
|
49
|
-
end
|
|
13
|
+
def perform_query(raw_connection, sql, binds, type_casted_binds, prepare:, notification_payload:, batch: false)
|
|
14
|
+
reset_multi_statement = if batch && !@config[:multi_statement]
|
|
15
|
+
raw_connection.set_server_option(::Trilogy::SET_SERVER_MULTI_STATEMENTS_ON)
|
|
16
|
+
true
|
|
50
17
|
end
|
|
51
|
-
end
|
|
52
18
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
19
|
+
# Make sure we carry over any changes to ActiveRecord.default_timezone that have been
|
|
20
|
+
# made since we established the connection
|
|
21
|
+
if default_timezone == :local
|
|
22
|
+
raw_connection.query_flags |= ::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
|
|
56
23
|
else
|
|
57
|
-
|
|
24
|
+
raw_connection.query_flags &= ~::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
|
|
58
25
|
end
|
|
59
|
-
end
|
|
60
26
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
27
|
+
result = raw_connection.query(sql)
|
|
28
|
+
while raw_connection.more_results_exist?
|
|
29
|
+
raw_connection.next_result
|
|
30
|
+
end
|
|
31
|
+
verified!
|
|
32
|
+
|
|
33
|
+
notification_payload[:affected_rows] = result.affected_rows
|
|
34
|
+
notification_payload[:row_count] = result.count
|
|
35
|
+
result
|
|
36
|
+
ensure
|
|
37
|
+
if reset_multi_statement && active?
|
|
38
|
+
raw_connection.set_server_option(::Trilogy::SET_SERVER_MULTI_STATEMENTS_OFF)
|
|
67
39
|
end
|
|
68
40
|
end
|
|
69
41
|
|
|
70
|
-
def
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
end
|
|
42
|
+
def cast_result(result)
|
|
43
|
+
if result.fields.empty?
|
|
44
|
+
ActiveRecord::Result.empty(affected_rows: result.affected_rows)
|
|
45
|
+
else
|
|
46
|
+
ActiveRecord::Result.new(result.fields, result.rows, affected_rows: result.affected_rows)
|
|
76
47
|
end
|
|
77
48
|
end
|
|
78
49
|
|
|
79
|
-
def
|
|
80
|
-
|
|
50
|
+
def affected_rows(result)
|
|
51
|
+
result.affected_rows
|
|
81
52
|
end
|
|
82
53
|
|
|
83
|
-
def
|
|
84
|
-
if
|
|
85
|
-
|
|
54
|
+
def last_inserted_id(result)
|
|
55
|
+
if supports_insert_returning?
|
|
56
|
+
super
|
|
57
|
+
else
|
|
58
|
+
result.last_insert_id
|
|
86
59
|
end
|
|
60
|
+
end
|
|
87
61
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
yield
|
|
92
|
-
ensure
|
|
93
|
-
conn.set_server_option(::Trilogy::SET_SERVER_MULTI_STATEMENTS_OFF) if active?
|
|
62
|
+
def execute_batch(statements, name = nil, **kwargs)
|
|
63
|
+
combine_multi_statements(statements).each do |statement|
|
|
64
|
+
raw_execute(statement, name, batch: true, **kwargs)
|
|
94
65
|
end
|
|
95
66
|
end
|
|
96
67
|
end
|
|
@@ -121,7 +121,7 @@ module ActiveRecord
|
|
|
121
121
|
end
|
|
122
122
|
|
|
123
123
|
def active?
|
|
124
|
-
connected? && @lock.synchronize { @raw_connection&.ping } || false
|
|
124
|
+
connected? && @lock.synchronize { @raw_connection&.ping; verified! } || false
|
|
125
125
|
rescue ::Trilogy::Error
|
|
126
126
|
false
|
|
127
127
|
end
|
|
@@ -149,23 +149,6 @@ module ActiveRecord
|
|
|
149
149
|
TYPE_MAP.lookup(type).is_a?(Type::String) || TYPE_MAP.lookup(type).is_a?(Type::Text)
|
|
150
150
|
end
|
|
151
151
|
|
|
152
|
-
def each_hash(result)
|
|
153
|
-
return to_enum(:each_hash, result) unless block_given?
|
|
154
|
-
|
|
155
|
-
keys = result.fields.map(&:to_sym)
|
|
156
|
-
result.rows.each do |row|
|
|
157
|
-
hash = {}
|
|
158
|
-
idx = 0
|
|
159
|
-
row.each do |value|
|
|
160
|
-
hash[keys[idx]] = value
|
|
161
|
-
idx += 1
|
|
162
|
-
end
|
|
163
|
-
yield hash
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
nil
|
|
167
|
-
end
|
|
168
|
-
|
|
169
152
|
def error_number(exception)
|
|
170
153
|
exception.error_code if exception.respond_to?(:error_code)
|
|
171
154
|
end
|
|
@@ -198,7 +181,7 @@ module ActiveRecord
|
|
|
198
181
|
end
|
|
199
182
|
|
|
200
183
|
case exception
|
|
201
|
-
when ::Trilogy::ConnectionClosed, ::Trilogy::EOFError
|
|
184
|
+
when ::Trilogy::ConnectionClosed, ::Trilogy::EOFError, ::Trilogy::SSLError
|
|
202
185
|
return ConnectionFailed.new(message, connection_pool: @pool)
|
|
203
186
|
when ::Trilogy::Error
|
|
204
187
|
if exception.is_a?(SystemCallError) || exception.message.include?("TRILOGY_INVALID_SEQUENCE_ID")
|
|
@@ -31,62 +31,6 @@ module ActiveRecord
|
|
|
31
31
|
class_name, path_to_adapter = @adapters[adapter_name.to_s]
|
|
32
32
|
|
|
33
33
|
unless class_name
|
|
34
|
-
# To provide better error messages for adapters expecting the pre-7.2 adapter registration API, we attempt
|
|
35
|
-
# to load the adapter file from the old location which was required by convention, and then raise an error
|
|
36
|
-
# describing how to upgrade the adapter to the new API.
|
|
37
|
-
legacy_adapter_path = "active_record/connection_adapters/#{adapter_name}_adapter"
|
|
38
|
-
legacy_adapter_connection_method_name = "#{adapter_name}_connection".to_sym
|
|
39
|
-
|
|
40
|
-
begin
|
|
41
|
-
require legacy_adapter_path
|
|
42
|
-
# If we reach here it means we found the found a file that may be the legacy adapter and should raise.
|
|
43
|
-
if ActiveRecord::ConnectionHandling.method_defined?(legacy_adapter_connection_method_name)
|
|
44
|
-
# If we find the connection method then we care certain it is a legacy adapter.
|
|
45
|
-
deprecation_message = <<~MSG.squish
|
|
46
|
-
Database configuration specifies '#{adapter_name}' adapter but that adapter has not been registered.
|
|
47
|
-
Rails 7.2 has changed the way Active Record database adapters are loaded. The adapter needs to be
|
|
48
|
-
updated to register itself rather than being loaded by convention.
|
|
49
|
-
Ensure that the adapter in the Gemfile is at the latest version. If it is, then the adapter may need to
|
|
50
|
-
be modified.
|
|
51
|
-
See:
|
|
52
|
-
https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters.html#method-c-register
|
|
53
|
-
MSG
|
|
54
|
-
|
|
55
|
-
exception_message = <<~MSG.squish
|
|
56
|
-
Database configuration specifies '#{adapter_name}' adapter but that adapter has not been registered.
|
|
57
|
-
Ensure that the adapter in the Gemfile is at the latest version. If it is, then the adapter may need to
|
|
58
|
-
be modified.
|
|
59
|
-
MSG
|
|
60
|
-
else
|
|
61
|
-
# If we do not find the connection method we are much less certain it is a legacy adapter. Even though the
|
|
62
|
-
# file exists in the location defined by convenntion, it does not necessarily mean that file is supposed
|
|
63
|
-
# to define the adapter the legacy way. So raise an error that explains both possibilities.
|
|
64
|
-
deprecation_message = <<~MSG.squish
|
|
65
|
-
Database configuration specifies nonexistent '#{adapter_name}' adapter.
|
|
66
|
-
Available adapters are: #{@adapters.keys.sort.join(", ")}.
|
|
67
|
-
Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary
|
|
68
|
-
adapter gem to your Gemfile if it's not in the list of available adapters.
|
|
69
|
-
Rails 7.2 has changed the way Active Record database adapters are loaded. Ensure that the adapter in
|
|
70
|
-
the Gemfile is at the latest version. If it is up to date, the adapter may need to be modified.
|
|
71
|
-
See:
|
|
72
|
-
https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters.html#method-c-register
|
|
73
|
-
MSG
|
|
74
|
-
|
|
75
|
-
exception_message = <<~MSG.squish
|
|
76
|
-
Database configuration specifies nonexistent '#{adapter_name}' adapter.
|
|
77
|
-
Available adapters are: #{@adapters.keys.sort.join(", ")}.
|
|
78
|
-
Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary
|
|
79
|
-
adapter gem to your Gemfile and that it is at its latest version. If it is up to date, the adapter may
|
|
80
|
-
need to be modified.
|
|
81
|
-
MSG
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
ActiveRecord.deprecator.warn(deprecation_message)
|
|
85
|
-
raise AdapterNotFound, exception_message
|
|
86
|
-
rescue LoadError => error
|
|
87
|
-
# The adapter was not found in the legacy location so fall through to the error handling for a missing adapter.
|
|
88
|
-
end
|
|
89
|
-
|
|
90
34
|
raise AdapterNotFound, <<~MSG.squish
|
|
91
35
|
Database configuration specifies nonexistent '#{adapter_name}' adapter.
|
|
92
36
|
Available adapters are: #{@adapters.keys.sort.join(", ")}.
|
|
@@ -140,6 +84,7 @@ module ActiveRecord
|
|
|
140
84
|
autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
|
|
141
85
|
autoload :IndexDefinition
|
|
142
86
|
autoload :ColumnDefinition
|
|
87
|
+
autoload :ColumnMethods
|
|
143
88
|
autoload :ChangeColumnDefinition
|
|
144
89
|
autoload :ChangeColumnDefaultDefinition
|
|
145
90
|
autoload :ForeignKeyDefinition
|