activerecord 7.0.8.6 → 7.2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +631 -1939
- data/MIT-LICENSE +1 -1
- data/README.rdoc +29 -29
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +35 -12
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +23 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +22 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +26 -14
- data/lib/active_record/associations/collection_proxy.rb +29 -11
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +21 -14
- data/lib/active_record/associations/has_many_through_association.rb +17 -7
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
- data/lib/active_record/associations/join_dependency.rb +10 -10
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +33 -8
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +354 -485
- data/lib/active_record/attribute_assignment.rb +0 -4
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +53 -35
- data/lib/active_record/attribute_methods/primary_key.rb +45 -25
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +8 -7
- data/lib/active_record/attribute_methods/serialization.rb +131 -32
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -6
- data/lib/active_record/attribute_methods/write.rb +6 -6
- data/lib/active_record/attribute_methods.rb +148 -33
- data/lib/active_record/attributes.rb +64 -50
- data/lib/active_record/autosave_association.rb +69 -37
- data/lib/active_record/base.rb +9 -5
- data/lib/active_record/callbacks.rb +11 -25
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +123 -131
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +323 -88
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +217 -63
- data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -63
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +307 -129
- data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +510 -111
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +278 -125
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +26 -139
- data/lib/active_record/connection_adapters/mysql/quoting.rb +53 -54
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +25 -13
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +101 -68
- data/lib/active_record/connection_adapters/pool_config.rb +20 -10
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +14 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +100 -43
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +65 -61
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +151 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +370 -63
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +367 -201
- data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +45 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +14 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +50 -8
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -110
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
- data/lib/active_record/connection_adapters.rb +124 -1
- data/lib/active_record/connection_handling.rb +96 -104
- data/lib/active_record/core.rb +251 -176
- data/lib/active_record/counter_cache.rb +68 -34
- data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -3
- data/lib/active_record/database_configurations/database_config.rb +26 -5
- data/lib/active_record/database_configurations/hash_config.rb +52 -34
- data/lib/active_record/database_configurations/url_config.rb +37 -12
- data/lib/active_record/database_configurations.rb +87 -34
- data/lib/active_record/delegated_type.rb +39 -10
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -1
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +45 -21
- data/lib/active_record/encryption/encrypted_attribute_type.rb +47 -12
- data/lib/active_record/encryption/encryptor.rb +18 -3
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -69
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/key_provider.rb +1 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +6 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +22 -21
- data/lib/active_record/encryption.rb +3 -0
- data/lib/active_record/enum.rb +129 -28
- data/lib/active_record/errors.rb +151 -31
- data/lib/active_record/explain.rb +21 -12
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +29 -8
- data/lib/active_record/fixtures.rb +167 -97
- data/lib/active_record/future_result.rb +47 -8
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +34 -18
- data/lib/active_record/insert_all.rb +72 -22
- data/lib/active_record/integration.rb +11 -8
- data/lib/active_record/internal_metadata.rb +124 -20
- data/lib/active_record/locking/optimistic.rb +8 -7
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +18 -22
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +6 -8
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +106 -8
- data/lib/active_record/migration/compatibility.rb +147 -5
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +234 -117
- data/lib/active_record/model_schema.rb +90 -102
- data/lib/active_record/nested_attributes.rb +48 -11
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +168 -339
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +18 -25
- data/lib/active_record/query_logs.rb +92 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +33 -8
- data/lib/active_record/railtie.rb +129 -85
- data/lib/active_record/railties/controller_runtime.rb +22 -7
- data/lib/active_record/railties/databases.rake +145 -154
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +267 -69
- data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
- data/lib/active_record/relation/batches.rb +198 -63
- data/lib/active_record/relation/calculations.rb +250 -93
- data/lib/active_record/relation/delegation.rb +30 -19
- data/lib/active_record/relation/finder_methods.rb +93 -18
- data/lib/active_record/relation/merger.rb +6 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +18 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +28 -16
- data/lib/active_record/relation/query_attribute.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +576 -107
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +5 -4
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +580 -90
- data/lib/active_record/result.rb +49 -48
- data/lib/active_record/runtime_registry.rb +63 -1
- data/lib/active_record/sanitization.rb +70 -25
- data/lib/active_record/schema.rb +8 -7
- data/lib/active_record/schema_dumper.rb +63 -14
- data/lib/active_record/schema_migration.rb +75 -24
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +3 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +27 -6
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +1 -1
- data/lib/active_record/tasks/database_tasks.rb +190 -118
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
- data/lib/active_record/test_fixtures.rb +170 -155
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +31 -17
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +12 -7
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +106 -24
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +9 -3
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +61 -11
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +247 -33
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +6 -2
- data/lib/arel/predications.rb +3 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/table.rb +9 -5
- data/lib/arel/tree_manager.rb +8 -3
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +17 -5
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/sqlite.rb +25 -0
- data/lib/arel/visitors/to_sql.rb +112 -34
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +21 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- metadata +56 -14
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "active_record/connection_adapters/abstract_adapter"
|
4
4
|
require "active_record/connection_adapters/statement_pool"
|
5
|
+
require "active_record/connection_adapters/sqlite3/column"
|
5
6
|
require "active_record/connection_adapters/sqlite3/explain_pretty_printer"
|
6
7
|
require "active_record/connection_adapters/sqlite3/quoting"
|
7
8
|
require "active_record/connection_adapters/sqlite3/database_statements"
|
@@ -10,44 +11,13 @@ require "active_record/connection_adapters/sqlite3/schema_definitions"
|
|
10
11
|
require "active_record/connection_adapters/sqlite3/schema_dumper"
|
11
12
|
require "active_record/connection_adapters/sqlite3/schema_statements"
|
12
13
|
|
13
|
-
gem "sqlite3", "
|
14
|
+
gem "sqlite3", ">= 1.4"
|
14
15
|
require "sqlite3"
|
15
16
|
|
16
17
|
module ActiveRecord
|
17
|
-
module ConnectionHandling # :nodoc:
|
18
|
-
def sqlite3_connection(config)
|
19
|
-
config = config.symbolize_keys
|
20
|
-
|
21
|
-
# Require database.
|
22
|
-
unless config[:database]
|
23
|
-
raise ArgumentError, "No database file specified. Missing argument: database"
|
24
|
-
end
|
25
|
-
|
26
|
-
# Allow database path relative to Rails.root, but only if the database
|
27
|
-
# path is not the special path that tells sqlite to build a database only
|
28
|
-
# in memory.
|
29
|
-
if ":memory:" != config[:database] && !config[:database].to_s.start_with?("file:")
|
30
|
-
config[:database] = File.expand_path(config[:database], Rails.root) if defined?(Rails.root)
|
31
|
-
dirname = File.dirname(config[:database])
|
32
|
-
Dir.mkdir(dirname) unless File.directory?(dirname)
|
33
|
-
end
|
34
|
-
|
35
|
-
db = SQLite3::Database.new(
|
36
|
-
config[:database].to_s,
|
37
|
-
config.merge(results_as_hash: true)
|
38
|
-
)
|
39
|
-
|
40
|
-
ConnectionAdapters::SQLite3Adapter.new(db, logger, nil, config)
|
41
|
-
rescue Errno::ENOENT => error
|
42
|
-
if error.message.include?("No such file or directory")
|
43
|
-
raise ActiveRecord::NoDatabaseError
|
44
|
-
else
|
45
|
-
raise
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
18
|
module ConnectionAdapters # :nodoc:
|
19
|
+
# = Active Record SQLite3 Adapter
|
20
|
+
#
|
51
21
|
# The SQLite3 adapter works with the sqlite3-ruby drivers
|
52
22
|
# (available as gem from https://rubygems.org/gems/sqlite3).
|
53
23
|
#
|
@@ -57,10 +27,42 @@ module ActiveRecord
|
|
57
27
|
class SQLite3Adapter < AbstractAdapter
|
58
28
|
ADAPTER_NAME = "SQLite"
|
59
29
|
|
30
|
+
class << self
|
31
|
+
def new_client(config)
|
32
|
+
::SQLite3::Database.new(config[:database].to_s, config)
|
33
|
+
rescue Errno::ENOENT => error
|
34
|
+
if error.message.include?("No such file or directory")
|
35
|
+
raise ActiveRecord::NoDatabaseError
|
36
|
+
else
|
37
|
+
raise
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def dbconsole(config, options = {})
|
42
|
+
args = []
|
43
|
+
|
44
|
+
args << "-#{options[:mode]}" if options[:mode]
|
45
|
+
args << "-header" if options[:header]
|
46
|
+
args << File.expand_path(config.database, Rails.respond_to?(:root) ? Rails.root : nil)
|
47
|
+
|
48
|
+
find_cmd_and_exec("sqlite3", *args)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
60
52
|
include SQLite3::Quoting
|
61
53
|
include SQLite3::SchemaStatements
|
62
54
|
include SQLite3::DatabaseStatements
|
63
55
|
|
56
|
+
##
|
57
|
+
# :singleton-method:
|
58
|
+
# Configure the SQLite3Adapter to be used in a strict strings mode.
|
59
|
+
# This will disable double-quoted string literals, because otherwise typos can silently go unnoticed.
|
60
|
+
# For example, it is possible to create an index for a non existing column.
|
61
|
+
# If you wish to enable this mode you can add the following line to your application.rb file:
|
62
|
+
#
|
63
|
+
# config.active_record.sqlite3_adapter_strict_strings_by_default = true
|
64
|
+
class_attribute :strict_strings_by_default, default: false
|
65
|
+
|
64
66
|
NATIVE_DATABASE_TYPES = {
|
65
67
|
primary_key: "integer PRIMARY KEY AUTOINCREMENT NOT NULL",
|
66
68
|
string: { name: "varchar" },
|
@@ -76,27 +78,54 @@ module ActiveRecord
|
|
76
78
|
json: { name: "json" },
|
77
79
|
}
|
78
80
|
|
81
|
+
DEFAULT_PRAGMAS = {
|
82
|
+
"foreign_keys" => true,
|
83
|
+
"journal_mode" => :wal,
|
84
|
+
"synchronous" => :normal,
|
85
|
+
"mmap_size" => 134217728, # 128 megabytes
|
86
|
+
"journal_size_limit" => 67108864, # 64 megabytes
|
87
|
+
"cache_size" => 2000
|
88
|
+
}
|
89
|
+
|
79
90
|
class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
|
91
|
+
alias reset clear
|
92
|
+
|
80
93
|
private
|
81
94
|
def dealloc(stmt)
|
82
95
|
stmt.close unless stmt.closed?
|
83
96
|
end
|
84
97
|
end
|
85
98
|
|
86
|
-
def initialize(
|
87
|
-
|
88
|
-
super(connection, logger, config)
|
89
|
-
configure_connection
|
90
|
-
end
|
99
|
+
def initialize(...)
|
100
|
+
super
|
91
101
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
102
|
+
@memory_database = false
|
103
|
+
case @config[:database].to_s
|
104
|
+
when ""
|
105
|
+
raise ArgumentError, "No database file specified. Missing argument: database"
|
106
|
+
when ":memory:"
|
107
|
+
@memory_database = true
|
108
|
+
when /\Afile:/
|
96
109
|
else
|
97
|
-
|
98
|
-
File.
|
110
|
+
# Otherwise we have a path relative to Rails.root
|
111
|
+
@config[:database] = File.expand_path(@config[:database], Rails.root) if defined?(Rails.root)
|
112
|
+
dirname = File.dirname(@config[:database])
|
113
|
+
unless File.directory?(dirname)
|
114
|
+
begin
|
115
|
+
FileUtils.mkdir_p(dirname)
|
116
|
+
rescue SystemCallError
|
117
|
+
raise ActiveRecord::NoDatabaseError.new(connection_pool: @pool)
|
118
|
+
end
|
119
|
+
end
|
99
120
|
end
|
121
|
+
|
122
|
+
@config[:strict] = ConnectionAdapters::SQLite3Adapter.strict_strings_by_default unless @config.key?(:strict)
|
123
|
+
@connection_parameters = @config.merge(database: @config[:database].to_s, results_as_hash: true)
|
124
|
+
@use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
|
125
|
+
end
|
126
|
+
|
127
|
+
def database_exists?
|
128
|
+
@config[:database] == ":memory:" || File.exist?(@config[:database].to_s)
|
100
129
|
end
|
101
130
|
|
102
131
|
def supports_ddl_transactions?
|
@@ -147,6 +176,10 @@ module ActiveRecord
|
|
147
176
|
database_version >= "3.8.3"
|
148
177
|
end
|
149
178
|
|
179
|
+
def supports_insert_returning?
|
180
|
+
database_version >= "3.35.0"
|
181
|
+
end
|
182
|
+
|
150
183
|
def supports_insert_on_conflict?
|
151
184
|
database_version >= "3.24.0"
|
152
185
|
end
|
@@ -158,20 +191,25 @@ module ActiveRecord
|
|
158
191
|
!@memory_database
|
159
192
|
end
|
160
193
|
|
161
|
-
def
|
162
|
-
|
194
|
+
def supports_virtual_columns?
|
195
|
+
database_version >= "3.31.0"
|
163
196
|
end
|
164
197
|
|
165
|
-
def
|
166
|
-
|
167
|
-
connect if @connection.closed?
|
198
|
+
def connected?
|
199
|
+
!(@raw_connection.nil? || @raw_connection.closed?)
|
168
200
|
end
|
169
201
|
|
202
|
+
alias_method :active?, :connected?
|
203
|
+
|
204
|
+
alias :reset! :reconnect!
|
205
|
+
|
170
206
|
# Disconnects from the database if already connected. Otherwise, this
|
171
207
|
# method does nothing.
|
172
208
|
def disconnect!
|
173
209
|
super
|
174
|
-
|
210
|
+
|
211
|
+
@raw_connection&.close rescue nil
|
212
|
+
@raw_connection = nil
|
175
213
|
end
|
176
214
|
|
177
215
|
def supports_index_sort_order?
|
@@ -184,7 +222,7 @@ module ActiveRecord
|
|
184
222
|
|
185
223
|
# Returns the current database encoding format as a string, e.g. 'UTF-8'
|
186
224
|
def encoding
|
187
|
-
|
225
|
+
any_raw_connection.encoding.to_s
|
188
226
|
end
|
189
227
|
|
190
228
|
def supports_explain?
|
@@ -195,6 +233,10 @@ module ActiveRecord
|
|
195
233
|
true
|
196
234
|
end
|
197
235
|
|
236
|
+
def supports_deferrable_constraints?
|
237
|
+
true
|
238
|
+
end
|
239
|
+
|
198
240
|
# REFERENTIAL INTEGRITY ====================================
|
199
241
|
|
200
242
|
def disable_referential_integrity # :nodoc:
|
@@ -211,8 +253,14 @@ module ActiveRecord
|
|
211
253
|
end
|
212
254
|
end
|
213
255
|
|
214
|
-
def
|
215
|
-
|
256
|
+
def check_all_foreign_keys_valid! # :nodoc:
|
257
|
+
sql = "PRAGMA foreign_key_check"
|
258
|
+
result = execute(sql)
|
259
|
+
|
260
|
+
unless result.blank?
|
261
|
+
tables = result.map { |row| row["table"] }
|
262
|
+
raise ActiveRecord::StatementInvalid.new("Foreign key violations found: #{tables.join(", ")}", sql: sql, connection_pool: @pool)
|
263
|
+
end
|
216
264
|
end
|
217
265
|
|
218
266
|
# SCHEMA STATEMENTS ========================================
|
@@ -234,14 +282,16 @@ module ActiveRecord
|
|
234
282
|
#
|
235
283
|
# Example:
|
236
284
|
# rename_table('octopuses', 'octopi')
|
237
|
-
def rename_table(table_name, new_name)
|
285
|
+
def rename_table(table_name, new_name, **options)
|
286
|
+
validate_table_length!(new_name) unless options[:_uses_legacy_table_name]
|
238
287
|
schema_cache.clear_data_source_cache!(table_name.to_s)
|
239
288
|
schema_cache.clear_data_source_cache!(new_name.to_s)
|
240
289
|
exec_query "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
|
241
|
-
rename_table_indexes(table_name, new_name)
|
290
|
+
rename_table_indexes(table_name, new_name, **options)
|
242
291
|
end
|
243
292
|
|
244
293
|
def add_column(table_name, column_name, type, **options) # :nodoc:
|
294
|
+
type = type.to_sym
|
245
295
|
if invalid_alter_table_type?(type, options)
|
246
296
|
alter_table(table_name) do |definition|
|
247
297
|
definition.column(column_name, type, **options)
|
@@ -277,8 +327,10 @@ module ActiveRecord
|
|
277
327
|
end
|
278
328
|
|
279
329
|
def change_column_null(table_name, column_name, null, default = nil) # :nodoc:
|
330
|
+
validate_change_column_null_argument!(null)
|
331
|
+
|
280
332
|
unless null || default.nil?
|
281
|
-
|
333
|
+
internal_exec_query("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
|
282
334
|
end
|
283
335
|
alter_table(table_name) do |definition|
|
284
336
|
definition[column_name].null = null
|
@@ -297,20 +349,58 @@ module ActiveRecord
|
|
297
349
|
rename_column_indexes(table_name, column.name, new_column_name)
|
298
350
|
end
|
299
351
|
|
352
|
+
def add_timestamps(table_name, **options)
|
353
|
+
options[:null] = false if options[:null].nil?
|
354
|
+
|
355
|
+
if !options.key?(:precision)
|
356
|
+
options[:precision] = 6
|
357
|
+
end
|
358
|
+
|
359
|
+
alter_table(table_name) do |definition|
|
360
|
+
definition.column :created_at, :datetime, **options
|
361
|
+
definition.column :updated_at, :datetime, **options
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
300
365
|
def add_reference(table_name, ref_name, **options) # :nodoc:
|
301
366
|
super(table_name, ref_name, type: :integer, **options)
|
302
367
|
end
|
303
368
|
alias :add_belongs_to :add_reference
|
304
369
|
|
370
|
+
FK_REGEX = /.*FOREIGN KEY\s+\("(\w+)"\)\s+REFERENCES\s+"(\w+)"\s+\("(\w+)"\)/
|
371
|
+
DEFERRABLE_REGEX = /DEFERRABLE INITIALLY (\w+)/
|
305
372
|
def foreign_keys(table_name)
|
306
|
-
|
307
|
-
fk_info
|
373
|
+
# SQLite returns 1 row for each column of composite foreign keys.
|
374
|
+
fk_info = internal_exec_query("PRAGMA foreign_key_list(#{quote(table_name)})", "SCHEMA")
|
375
|
+
# Deferred or immediate foreign keys can only be seen in the CREATE TABLE sql
|
376
|
+
fk_defs = table_structure_sql(table_name)
|
377
|
+
.select do |column_string|
|
378
|
+
column_string.start_with?("CONSTRAINT") &&
|
379
|
+
column_string.include?("FOREIGN KEY")
|
380
|
+
end
|
381
|
+
.to_h do |fk_string|
|
382
|
+
_, from, table, to = fk_string.match(FK_REGEX).to_a
|
383
|
+
_, mode = fk_string.match(DEFERRABLE_REGEX).to_a
|
384
|
+
deferred = mode&.downcase&.to_sym || false
|
385
|
+
[[table, from, to], deferred]
|
386
|
+
end
|
387
|
+
|
388
|
+
grouped_fk = fk_info.group_by { |row| row["id"] }.values.each { |group| group.sort_by! { |row| row["seq"] } }
|
389
|
+
grouped_fk.map do |group|
|
390
|
+
row = group.first
|
308
391
|
options = {
|
309
|
-
column: row["from"],
|
310
|
-
primary_key: row["to"],
|
311
392
|
on_delete: extract_foreign_key_action(row["on_delete"]),
|
312
|
-
on_update: extract_foreign_key_action(row["on_update"])
|
393
|
+
on_update: extract_foreign_key_action(row["on_update"]),
|
394
|
+
deferrable: fk_defs[[row["table"], row["from"], row["to"]]]
|
313
395
|
}
|
396
|
+
|
397
|
+
if group.one?
|
398
|
+
options[:column] = row["from"]
|
399
|
+
options[:primary_key] = row["to"]
|
400
|
+
else
|
401
|
+
options[:column] = group.map { |row| row["from"] }
|
402
|
+
options[:primary_key] = group.map { |row| row["to"] }
|
403
|
+
end
|
314
404
|
ForeignKeyDefinition.new(table_name, row["table"], options)
|
315
405
|
end
|
316
406
|
end
|
@@ -330,6 +420,7 @@ module ActiveRecord
|
|
330
420
|
end
|
331
421
|
end
|
332
422
|
|
423
|
+
sql << " RETURNING #{insert.returning}" if insert.returning
|
333
424
|
sql
|
334
425
|
end
|
335
426
|
|
@@ -337,6 +428,10 @@ module ActiveRecord
|
|
337
428
|
@config.fetch(:flags, 0).anybits?(::SQLite3::Constants::Open::SHAREDCACHE)
|
338
429
|
end
|
339
430
|
|
431
|
+
def use_insert_returning?
|
432
|
+
@use_insert_returning
|
433
|
+
end
|
434
|
+
|
340
435
|
def get_database_version # :nodoc:
|
341
436
|
SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)", "SCHEMA"))
|
342
437
|
end
|
@@ -367,12 +462,9 @@ module ActiveRecord
|
|
367
462
|
end
|
368
463
|
|
369
464
|
TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
|
465
|
+
EXTENDED_TYPE_MAPS = Concurrent::Map.new
|
370
466
|
|
371
467
|
private
|
372
|
-
def type_map
|
373
|
-
TYPE_MAP
|
374
|
-
end
|
375
|
-
|
376
468
|
# See https://www.sqlite.org/limits.html,
|
377
469
|
# the default value is 999 when not configured.
|
378
470
|
def bind_params_length
|
@@ -380,8 +472,8 @@ module ActiveRecord
|
|
380
472
|
end
|
381
473
|
|
382
474
|
def table_structure(table_name)
|
383
|
-
structure =
|
384
|
-
raise
|
475
|
+
structure = table_info(table_name)
|
476
|
+
raise ActiveRecord::StatementInvalid.new("Could not find table '#{table_name}'", connection_pool: @pool) if structure.empty?
|
385
477
|
table_structure_with_collation(table_name, structure)
|
386
478
|
end
|
387
479
|
alias column_definitions table_structure
|
@@ -391,14 +483,17 @@ module ActiveRecord
|
|
391
483
|
when /^null$/i
|
392
484
|
nil
|
393
485
|
# Quoted types
|
394
|
-
when /^'(
|
486
|
+
when /^'([^|]*)'$/m
|
395
487
|
$1.gsub("''", "'")
|
396
488
|
# Quoted types
|
397
|
-
when /^"(
|
489
|
+
when /^"([^|]*)"$/m
|
398
490
|
$1.gsub('""', '"')
|
399
491
|
# Numeric types
|
400
492
|
when /\A-?\d+(\.\d*)?\z/
|
401
493
|
$&
|
494
|
+
# Binary columns
|
495
|
+
when /x'(.*)'/
|
496
|
+
[ $1 ].pack("H*")
|
402
497
|
else
|
403
498
|
# Anything else is blank or some function
|
404
499
|
# and we can't know the value of that, so return nil.
|
@@ -411,14 +506,15 @@ module ActiveRecord
|
|
411
506
|
end
|
412
507
|
|
413
508
|
def has_default_function?(default_value, default)
|
414
|
-
!default_value && %r{\w+\(.*\)|CURRENT_TIME|CURRENT_DATE|CURRENT_TIMESTAMP}.match?(default)
|
509
|
+
!default_value && %r{\w+\(.*\)|CURRENT_TIME|CURRENT_DATE|CURRENT_TIMESTAMP|\|\|}.match?(default)
|
415
510
|
end
|
416
511
|
|
417
512
|
# See: https://www.sqlite.org/lang_altertable.html
|
418
513
|
# SQLite has an additional restriction on the ALTER TABLE statement
|
419
514
|
def invalid_alter_table_type?(type, options)
|
420
|
-
type
|
421
|
-
options[:null] == false && options[:default].nil?
|
515
|
+
type == :primary_key || options[:primary_key] ||
|
516
|
+
options[:null] == false && options[:default].nil? ||
|
517
|
+
(type == :virtual && options[:stored])
|
422
518
|
end
|
423
519
|
|
424
520
|
def alter_table(
|
@@ -474,25 +570,40 @@ module ActiveRecord
|
|
474
570
|
options[:rename][column.name.to_sym] ||
|
475
571
|
column.name) : column.name
|
476
572
|
|
477
|
-
|
573
|
+
column_options = {
|
574
|
+
limit: column.limit,
|
575
|
+
precision: column.precision,
|
576
|
+
scale: column.scale,
|
577
|
+
null: column.null,
|
578
|
+
collation: column.collation,
|
579
|
+
primary_key: column_name == from_primary_key
|
580
|
+
}
|
581
|
+
|
582
|
+
if column.virtual?
|
583
|
+
column_options[:as] = column.default_function
|
584
|
+
column_options[:stored] = column.virtual_stored?
|
585
|
+
column_options[:type] = column.type
|
586
|
+
elsif column.has_default?
|
478
587
|
type = lookup_cast_type_from_column(column)
|
479
588
|
default = type.deserialize(column.default)
|
480
589
|
default = -> { column.default_function } if default.nil?
|
590
|
+
|
591
|
+
unless column.auto_increment?
|
592
|
+
column_options[:default] = default
|
593
|
+
end
|
481
594
|
end
|
482
595
|
|
483
|
-
|
484
|
-
|
485
|
-
precision: column.precision, scale: column.scale,
|
486
|
-
null: column.null, collation: column.collation,
|
487
|
-
primary_key: column_name == from_primary_key
|
488
|
-
)
|
596
|
+
column_type = column.virtual? ? :virtual : (column.bigint? ? :bigint : column.type)
|
597
|
+
@definition.column(column_name, column_type, **column_options)
|
489
598
|
end
|
490
599
|
|
491
600
|
yield @definition if block_given?
|
492
601
|
end
|
493
602
|
copy_table_indexes(from, to, options[:rename] || {})
|
603
|
+
|
604
|
+
columns_to_copy = @definition.columns.reject { |col| col.options.key?(:as) }.map(&:name)
|
494
605
|
copy_table_contents(from, to,
|
495
|
-
|
606
|
+
columns_to_copy,
|
496
607
|
options[:rename] || {})
|
497
608
|
end
|
498
609
|
|
@@ -533,7 +644,7 @@ module ActiveRecord
|
|
533
644
|
quoted_columns = columns.map { |col| quote_column_name(col) } * ","
|
534
645
|
quoted_from_columns = from_columns_to_copy.map { |col| quote_column_name(col) } * ","
|
535
646
|
|
536
|
-
|
647
|
+
internal_exec_query("INSERT INTO #{quote_table_name(to)} (#{quoted_columns})
|
537
648
|
SELECT #{quoted_from_columns} FROM #{quote_table_name(from)}")
|
538
649
|
end
|
539
650
|
|
@@ -543,43 +654,36 @@ module ActiveRecord
|
|
543
654
|
# Older versions of SQLite return:
|
544
655
|
# column *column_name* is not unique
|
545
656
|
if exception.message.match?(/(column(s)? .* (is|are) not unique|UNIQUE constraint failed: .*)/i)
|
546
|
-
RecordNotUnique.new(message, sql: sql, binds: binds)
|
657
|
+
RecordNotUnique.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
547
658
|
elsif exception.message.match?(/(.* may not be NULL|NOT NULL constraint failed: .*)/i)
|
548
|
-
NotNullViolation.new(message, sql: sql, binds: binds)
|
659
|
+
NotNullViolation.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
549
660
|
elsif exception.message.match?(/FOREIGN KEY constraint failed/i)
|
550
|
-
InvalidForeignKey.new(message, sql: sql, binds: binds)
|
661
|
+
InvalidForeignKey.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
551
662
|
elsif exception.message.match?(/called on a closed database/i)
|
552
|
-
ConnectionNotEstablished.new(exception)
|
663
|
+
ConnectionNotEstablished.new(exception, connection_pool: @pool)
|
553
664
|
else
|
554
665
|
super
|
555
666
|
end
|
556
667
|
end
|
557
668
|
|
558
|
-
COLLATE_REGEX = /.*"(\w+)".*collate\s+"(\w+)".*/i
|
669
|
+
COLLATE_REGEX = /.*"(\w+)".*collate\s+"(\w+)".*/i
|
670
|
+
PRIMARY_KEY_AUTOINCREMENT_REGEX = /.*"(\w+)".+PRIMARY KEY AUTOINCREMENT/i
|
671
|
+
GENERATED_ALWAYS_AS_REGEX = /.*"(\w+)".+GENERATED ALWAYS AS \((.+)\) (?:STORED|VIRTUAL)/i
|
559
672
|
|
560
673
|
def table_structure_with_collation(table_name, basic_structure)
|
561
674
|
collation_hash = {}
|
562
|
-
|
563
|
-
|
564
|
-
(SELECT * FROM sqlite_master UNION ALL
|
565
|
-
SELECT * FROM sqlite_temp_master)
|
566
|
-
WHERE type = 'table' AND name = #{quote(table_name)}
|
567
|
-
SQL
|
675
|
+
auto_increments = {}
|
676
|
+
generated_columns = {}
|
568
677
|
|
569
|
-
|
570
|
-
# CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
571
|
-
# "password_digest" varchar COLLATE "NOCASE");
|
572
|
-
result = query_value(sql, "SCHEMA")
|
573
|
-
|
574
|
-
if result
|
575
|
-
# Splitting with left parentheses and discarding the first part will return all
|
576
|
-
# columns separated with comma(,).
|
577
|
-
columns_string = result.split("(", 2).last
|
678
|
+
column_strings = table_structure_sql(table_name, basic_structure.map { |column| column["name"] })
|
578
679
|
|
579
|
-
|
680
|
+
if column_strings.any?
|
681
|
+
column_strings.each do |column_string|
|
580
682
|
# This regex will match the column name and collation type and will save
|
581
683
|
# the value in $1 and $2 respectively.
|
582
684
|
collation_hash[$1] = $2 if COLLATE_REGEX =~ column_string
|
685
|
+
auto_increments[$1] = true if PRIMARY_KEY_AUTOINCREMENT_REGEX =~ column_string
|
686
|
+
generated_columns[$1] = $2 if GENERATED_ALWAYS_AS_REGEX =~ column_string
|
583
687
|
end
|
584
688
|
|
585
689
|
basic_structure.map do |column|
|
@@ -589,6 +693,14 @@ module ActiveRecord
|
|
589
693
|
column["collation"] = collation_hash[column_name]
|
590
694
|
end
|
591
695
|
|
696
|
+
if auto_increments.has_key?(column_name)
|
697
|
+
column["auto_increment"] = true
|
698
|
+
end
|
699
|
+
|
700
|
+
if generated_columns.has_key?(column_name)
|
701
|
+
column["dflt_value"] = generated_columns[column_name]
|
702
|
+
end
|
703
|
+
|
592
704
|
column
|
593
705
|
end
|
594
706
|
else
|
@@ -596,6 +708,50 @@ module ActiveRecord
|
|
596
708
|
end
|
597
709
|
end
|
598
710
|
|
711
|
+
UNQUOTED_OPEN_PARENS_REGEX = /\((?![^'"]*['"][^'"]*$)/
|
712
|
+
FINAL_CLOSE_PARENS_REGEX = /\);*\z/
|
713
|
+
|
714
|
+
def table_structure_sql(table_name, column_names = nil)
|
715
|
+
unless column_names
|
716
|
+
column_info = table_info(table_name)
|
717
|
+
column_names = column_info.map { |column| column["name"] }
|
718
|
+
end
|
719
|
+
|
720
|
+
sql = <<~SQL
|
721
|
+
SELECT sql FROM
|
722
|
+
(SELECT * FROM sqlite_master UNION ALL
|
723
|
+
SELECT * FROM sqlite_temp_master)
|
724
|
+
WHERE type = 'table' AND name = #{quote(table_name)}
|
725
|
+
SQL
|
726
|
+
|
727
|
+
# Result will have following sample string
|
728
|
+
# CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
729
|
+
# "password_digest" varchar COLLATE "NOCASE",
|
730
|
+
# "o_id" integer,
|
731
|
+
# CONSTRAINT "fk_rails_78146ddd2e" FOREIGN KEY ("o_id") REFERENCES "os" ("id"));
|
732
|
+
result = query_value(sql, "SCHEMA")
|
733
|
+
|
734
|
+
return [] unless result
|
735
|
+
|
736
|
+
# Splitting with left parentheses and discarding the first part will return all
|
737
|
+
# columns separated with comma(,).
|
738
|
+
result.partition(UNQUOTED_OPEN_PARENS_REGEX)
|
739
|
+
.last
|
740
|
+
.sub(FINAL_CLOSE_PARENS_REGEX, "")
|
741
|
+
# column definitions can have a comma in them, so split on commas followed
|
742
|
+
# by a space and a column name in quotes or followed by the keyword CONSTRAINT
|
743
|
+
.split(/,(?=\s(?:CONSTRAINT|"(?:#{Regexp.union(column_names).source})"))/i)
|
744
|
+
.map(&:strip)
|
745
|
+
end
|
746
|
+
|
747
|
+
def table_info(table_name)
|
748
|
+
if supports_virtual_columns?
|
749
|
+
internal_exec_query("PRAGMA table_xinfo(#{quote_table_name(table_name)})", "SCHEMA")
|
750
|
+
else
|
751
|
+
internal_exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", "SCHEMA")
|
752
|
+
end
|
753
|
+
end
|
754
|
+
|
599
755
|
def arel_visitor
|
600
756
|
Arel::Visitors::SQLite.new(self)
|
601
757
|
end
|
@@ -605,17 +761,41 @@ module ActiveRecord
|
|
605
761
|
end
|
606
762
|
|
607
763
|
def connect
|
608
|
-
@
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
764
|
+
@raw_connection = self.class.new_client(@connection_parameters)
|
765
|
+
rescue ConnectionNotEstablished => ex
|
766
|
+
raise ex.set_pool(@pool)
|
767
|
+
end
|
768
|
+
|
769
|
+
def reconnect
|
770
|
+
if active?
|
771
|
+
@raw_connection.rollback rescue nil
|
772
|
+
else
|
773
|
+
connect
|
774
|
+
end
|
613
775
|
end
|
614
776
|
|
615
777
|
def configure_connection
|
616
|
-
@
|
778
|
+
if @config[:timeout] && @config[:retries]
|
779
|
+
raise ArgumentError, "Cannot specify both timeout and retries arguments"
|
780
|
+
elsif @config[:timeout]
|
781
|
+
@raw_connection.busy_timeout(self.class.type_cast_config_to_integer(@config[:timeout]))
|
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
|
787
|
+
end
|
788
|
+
|
789
|
+
super
|
617
790
|
|
618
|
-
|
791
|
+
pragmas = @config.fetch(:pragmas, {}).stringify_keys
|
792
|
+
DEFAULT_PRAGMAS.merge(pragmas).each do |pragma, value|
|
793
|
+
if ::SQLite3::Pragmas.method_defined?("#{pragma}=")
|
794
|
+
@raw_connection.public_send("#{pragma}=", value)
|
795
|
+
else
|
796
|
+
warn "Unknown SQLite pragma: #{pragma}"
|
797
|
+
end
|
798
|
+
end
|
619
799
|
end
|
620
800
|
end
|
621
801
|
ActiveSupport.run_load_hooks(:active_record_sqlite3adapter, SQLite3Adapter)
|
@@ -42,6 +42,13 @@ module ActiveRecord
|
|
42
42
|
cache.clear
|
43
43
|
end
|
44
44
|
|
45
|
+
# Clear the pool without deallocating; this is only safe when we
|
46
|
+
# know the server has independently deallocated all statements
|
47
|
+
# (e.g. due to a reconnect, or a DISCARD ALL)
|
48
|
+
def reset
|
49
|
+
cache.clear
|
50
|
+
end
|
51
|
+
|
45
52
|
def delete(key)
|
46
53
|
dealloc cache[key]
|
47
54
|
cache.delete(key)
|