activerecord 6.1.7 → 7.1.5
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 +2030 -1020
- data/MIT-LICENSE +1 -1
- data/README.rdoc +18 -18
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +1 -11
- data/lib/active_record/associations/association.rb +51 -19
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +40 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- 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 +6 -2
- data/lib/active_record/associations/collection_association.rb +39 -35
- data/lib/active_record/associations/collection_proxy.rb +30 -15
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +28 -18
- data/lib/active_record/associations/has_many_through_association.rb +12 -7
- data/lib/active_record/associations/has_one_association.rb +20 -10
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +3 -2
- data/lib/active_record/associations/join_dependency.rb +28 -20
- data/lib/active_record/associations/preloader/association.rb +210 -52
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -14
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +9 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +446 -306
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -3
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/dirty.rb +73 -22
- data/lib/active_record/attribute_methods/primary_key.rb +78 -26
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +27 -12
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +161 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +65 -31
- data/lib/active_record/base.rb +25 -2
- data/lib/active_record/callbacks.rb +18 -34
- 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 -46
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +113 -597
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +367 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -150
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +317 -164
- data/lib/active_record/connection_adapters/column.rb +13 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
- data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +39 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +112 -55
- data/lib/active_record/connection_adapters/pool_config.rb +20 -11
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +89 -52
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- 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/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
- 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 +30 -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 +89 -56
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +397 -75
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +508 -246
- data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +72 -53
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +296 -104
- 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 +258 -0
- data/lib/active_record/connection_adapters.rb +9 -6
- data/lib/active_record/connection_handling.rb +108 -137
- data/lib/active_record/core.rb +242 -233
- data/lib/active_record/counter_cache.rb +52 -27
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -2
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +88 -16
- data/lib/active_record/database_configurations/url_config.rb +18 -12
- data/lib/active_record/database_configurations.rb +95 -59
- data/lib/active_record/delegated_type.rb +66 -20
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +4 -2
- 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/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +155 -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 +157 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +53 -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 +92 -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 +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +154 -63
- data/lib/active_record/errors.rb +172 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +15 -1
- 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 +70 -14
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +147 -86
- data/lib/active_record/future_result.rb +174 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +81 -29
- data/lib/active_record/insert_all.rb +135 -22
- data/lib/active_record/integration.rb +11 -10
- data/lib/active_record/internal_metadata.rb +119 -33
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +37 -22
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- 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 +10 -10
- data/lib/active_record/middleware/database_selector.rb +23 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +112 -14
- data/lib/active_record/migration/compatibility.rb +233 -46
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +361 -173
- data/lib/active_record/model_schema.rb +125 -101
- data/lib/active_record/nested_attributes.rb +50 -20
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +167 -0
- data/lib/active_record/persistence.rb +409 -88
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +4 -22
- data/lib/active_record/query_logs.rb +174 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +29 -6
- data/lib/active_record/railtie.rb +220 -44
- data/lib/active_record/railties/controller_runtime.rb +15 -10
- data/lib/active_record/railties/databases.rake +188 -252
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +41 -3
- data/lib/active_record/reflection.rb +248 -81
- data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
- data/lib/active_record/relation/batches.rb +192 -63
- data/lib/active_record/relation/calculations.rb +246 -90
- data/lib/active_record/relation/delegation.rb +28 -14
- data/lib/active_record/relation/finder_methods.rb +108 -51
- data/lib/active_record/relation/merger.rb +22 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -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 +27 -20
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +670 -129
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +20 -3
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +287 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +32 -13
- data/lib/active_record/sanitization.rb +65 -20
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +73 -24
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +72 -15
- data/lib/active_record/scoping/named.rb +5 -13
- data/lib/active_record/scoping.rb +65 -34
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +10 -8
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +251 -140
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
- data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +117 -96
- data/lib/active_record/timestamp.rb +32 -19
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +48 -27
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +32 -14
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +9 -5
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +4 -4
- 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 +51 -6
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +335 -32
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/and.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +5 -0
- data/lib/arel/predications.rb +13 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +5 -13
- data/lib/arel/update_manager.rb +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +16 -3
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +141 -20
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +18 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -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
- 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
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +96 -16
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
@@ -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,23 @@ 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
18
|
module ConnectionHandling # :nodoc:
|
18
|
-
def
|
19
|
-
|
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
|
-
)
|
19
|
+
def sqlite3_adapter_class
|
20
|
+
ConnectionAdapters::SQLite3Adapter
|
21
|
+
end
|
39
22
|
|
40
|
-
|
41
|
-
|
42
|
-
if error.message.include?("No such file or directory")
|
43
|
-
raise ActiveRecord::NoDatabaseError
|
44
|
-
else
|
45
|
-
raise
|
46
|
-
end
|
23
|
+
def sqlite3_connection(config)
|
24
|
+
sqlite3_adapter_class.new(config)
|
47
25
|
end
|
48
26
|
end
|
49
27
|
|
50
|
-
module ConnectionAdapters
|
28
|
+
module ConnectionAdapters # :nodoc:
|
29
|
+
# = Active Record SQLite3 Adapter
|
30
|
+
#
|
51
31
|
# The SQLite3 adapter works with the sqlite3-ruby drivers
|
52
32
|
# (available as gem from https://rubygems.org/gems/sqlite3).
|
53
33
|
#
|
@@ -57,10 +37,42 @@ module ActiveRecord
|
|
57
37
|
class SQLite3Adapter < AbstractAdapter
|
58
38
|
ADAPTER_NAME = "SQLite"
|
59
39
|
|
40
|
+
class << self
|
41
|
+
def new_client(config)
|
42
|
+
::SQLite3::Database.new(config[:database].to_s, config)
|
43
|
+
rescue Errno::ENOENT => error
|
44
|
+
if error.message.include?("No such file or directory")
|
45
|
+
raise ActiveRecord::NoDatabaseError
|
46
|
+
else
|
47
|
+
raise
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def dbconsole(config, options = {})
|
52
|
+
args = []
|
53
|
+
|
54
|
+
args << "-#{options[:mode]}" if options[:mode]
|
55
|
+
args << "-header" if options[:header]
|
56
|
+
args << File.expand_path(config.database, Rails.respond_to?(:root) ? Rails.root : nil)
|
57
|
+
|
58
|
+
find_cmd_and_exec("sqlite3", *args)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
60
62
|
include SQLite3::Quoting
|
61
63
|
include SQLite3::SchemaStatements
|
62
64
|
include SQLite3::DatabaseStatements
|
63
65
|
|
66
|
+
##
|
67
|
+
# :singleton-method:
|
68
|
+
# Configure the SQLite3Adapter to be used in a strict strings mode.
|
69
|
+
# This will disable double-quoted string literals, because otherwise typos can silently go unnoticed.
|
70
|
+
# For example, it is possible to create an index for a non existing column.
|
71
|
+
# If you wish to enable this mode you can add the following line to your application.rb file:
|
72
|
+
#
|
73
|
+
# config.active_record.sqlite3_adapter_strict_strings_by_default = true
|
74
|
+
class_attribute :strict_strings_by_default, default: false
|
75
|
+
|
64
76
|
NATIVE_DATABASE_TYPES = {
|
65
77
|
primary_key: "integer PRIMARY KEY AUTOINCREMENT NOT NULL",
|
66
78
|
string: { name: "varchar" },
|
@@ -77,25 +89,48 @@ module ActiveRecord
|
|
77
89
|
}
|
78
90
|
|
79
91
|
class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
|
92
|
+
alias reset clear
|
93
|
+
|
80
94
|
private
|
81
95
|
def dealloc(stmt)
|
82
96
|
stmt.close unless stmt.closed?
|
83
97
|
end
|
84
98
|
end
|
85
99
|
|
86
|
-
def initialize(
|
87
|
-
super
|
88
|
-
configure_connection
|
89
|
-
end
|
100
|
+
def initialize(...)
|
101
|
+
super
|
90
102
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
103
|
+
@memory_database = false
|
104
|
+
case @config[:database].to_s
|
105
|
+
when ""
|
106
|
+
raise ArgumentError, "No database file specified. Missing argument: database"
|
107
|
+
when ":memory:"
|
108
|
+
@memory_database = true
|
109
|
+
when /\Afile:/
|
95
110
|
else
|
96
|
-
|
97
|
-
File.
|
111
|
+
# Otherwise we have a path relative to Rails.root
|
112
|
+
@config[:database] = File.expand_path(@config[:database], Rails.root) if defined?(Rails.root)
|
113
|
+
dirname = File.dirname(@config[:database])
|
114
|
+
unless File.directory?(dirname)
|
115
|
+
begin
|
116
|
+
Dir.mkdir(dirname)
|
117
|
+
rescue Errno::ENOENT => error
|
118
|
+
if error.message.include?("No such file or directory")
|
119
|
+
raise ActiveRecord::NoDatabaseError.new(connection_pool: @pool)
|
120
|
+
else
|
121
|
+
raise
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
98
125
|
end
|
126
|
+
|
127
|
+
@config[:strict] = ConnectionAdapters::SQLite3Adapter.strict_strings_by_default unless @config.key?(:strict)
|
128
|
+
@connection_parameters = @config.merge(database: @config[:database].to_s, results_as_hash: true)
|
129
|
+
@use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
|
130
|
+
end
|
131
|
+
|
132
|
+
def database_exists?
|
133
|
+
@config[:database] == ":memory:" || File.exist?(@config[:database].to_s)
|
99
134
|
end
|
100
135
|
|
101
136
|
def supports_ddl_transactions?
|
@@ -146,6 +181,10 @@ module ActiveRecord
|
|
146
181
|
database_version >= "3.8.3"
|
147
182
|
end
|
148
183
|
|
184
|
+
def supports_insert_returning?
|
185
|
+
database_version >= "3.35.0"
|
186
|
+
end
|
187
|
+
|
149
188
|
def supports_insert_on_conflict?
|
150
189
|
database_version >= "3.24.0"
|
151
190
|
end
|
@@ -153,33 +192,40 @@ module ActiveRecord
|
|
153
192
|
alias supports_insert_on_duplicate_update? supports_insert_on_conflict?
|
154
193
|
alias supports_insert_conflict_target? supports_insert_on_conflict?
|
155
194
|
|
195
|
+
def supports_concurrent_connections?
|
196
|
+
!@memory_database
|
197
|
+
end
|
198
|
+
|
156
199
|
def active?
|
157
|
-
!@
|
200
|
+
@raw_connection && !@raw_connection.closed?
|
158
201
|
end
|
159
202
|
|
160
|
-
def
|
161
|
-
|
162
|
-
connect if @connection.closed?
|
203
|
+
def return_value_after_insert?(column) # :nodoc:
|
204
|
+
column.auto_populated?
|
163
205
|
end
|
164
206
|
|
207
|
+
alias :reset! :reconnect!
|
208
|
+
|
165
209
|
# Disconnects from the database if already connected. Otherwise, this
|
166
210
|
# method does nothing.
|
167
211
|
def disconnect!
|
168
212
|
super
|
169
|
-
|
213
|
+
|
214
|
+
@raw_connection&.close rescue nil
|
215
|
+
@raw_connection = nil
|
170
216
|
end
|
171
217
|
|
172
218
|
def supports_index_sort_order?
|
173
219
|
true
|
174
220
|
end
|
175
221
|
|
176
|
-
def native_database_types
|
222
|
+
def native_database_types # :nodoc:
|
177
223
|
NATIVE_DATABASE_TYPES
|
178
224
|
end
|
179
225
|
|
180
|
-
# Returns the current database encoding format as a string,
|
226
|
+
# Returns the current database encoding format as a string, e.g. 'UTF-8'
|
181
227
|
def encoding
|
182
|
-
|
228
|
+
any_raw_connection.encoding.to_s
|
183
229
|
end
|
184
230
|
|
185
231
|
def supports_explain?
|
@@ -206,6 +252,16 @@ module ActiveRecord
|
|
206
252
|
end
|
207
253
|
end
|
208
254
|
|
255
|
+
def check_all_foreign_keys_valid! # :nodoc:
|
256
|
+
sql = "PRAGMA foreign_key_check"
|
257
|
+
result = execute(sql)
|
258
|
+
|
259
|
+
unless result.blank?
|
260
|
+
tables = result.map { |row| row["table"] }
|
261
|
+
raise ActiveRecord::StatementInvalid.new("Foreign key violations found: #{tables.join(", ")}", sql: sql)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
209
265
|
# SCHEMA STATEMENTS ========================================
|
210
266
|
|
211
267
|
def primary_keys(table_name) # :nodoc:
|
@@ -225,14 +281,15 @@ module ActiveRecord
|
|
225
281
|
#
|
226
282
|
# Example:
|
227
283
|
# rename_table('octopuses', 'octopi')
|
228
|
-
def rename_table(table_name, new_name)
|
284
|
+
def rename_table(table_name, new_name, **options)
|
285
|
+
validate_table_length!(new_name) unless options[:_uses_legacy_table_name]
|
229
286
|
schema_cache.clear_data_source_cache!(table_name.to_s)
|
230
287
|
schema_cache.clear_data_source_cache!(new_name.to_s)
|
231
288
|
exec_query "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
|
232
|
-
rename_table_indexes(table_name, new_name)
|
289
|
+
rename_table_indexes(table_name, new_name, **options)
|
233
290
|
end
|
234
291
|
|
235
|
-
def add_column(table_name, column_name, type, **options)
|
292
|
+
def add_column(table_name, column_name, type, **options) # :nodoc:
|
236
293
|
if invalid_alter_table_type?(type, options)
|
237
294
|
alter_table(table_name) do |definition|
|
238
295
|
definition.column(column_name, type, **options)
|
@@ -242,16 +299,24 @@ module ActiveRecord
|
|
242
299
|
end
|
243
300
|
end
|
244
301
|
|
245
|
-
def remove_column(table_name, column_name, type = nil, **options)
|
302
|
+
def remove_column(table_name, column_name, type = nil, **options) # :nodoc:
|
246
303
|
alter_table(table_name) do |definition|
|
247
304
|
definition.remove_column column_name
|
248
|
-
definition.foreign_keys.delete_if
|
249
|
-
|
305
|
+
definition.foreign_keys.delete_if { |fk| fk.column == column_name.to_s }
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def remove_columns(table_name, *column_names, type: nil, **options) # :nodoc:
|
310
|
+
alter_table(table_name) do |definition|
|
311
|
+
column_names.each do |column_name|
|
312
|
+
definition.remove_column column_name
|
250
313
|
end
|
314
|
+
column_names = column_names.map(&:to_s)
|
315
|
+
definition.foreign_keys.delete_if { |fk| column_names.include?(fk.column) }
|
251
316
|
end
|
252
317
|
end
|
253
318
|
|
254
|
-
def change_column_default(table_name, column_name, default_or_changes)
|
319
|
+
def change_column_default(table_name, column_name, default_or_changes) # :nodoc:
|
255
320
|
default = extract_new_default_value(default_or_changes)
|
256
321
|
|
257
322
|
alter_table(table_name) do |definition|
|
@@ -259,44 +324,65 @@ module ActiveRecord
|
|
259
324
|
end
|
260
325
|
end
|
261
326
|
|
262
|
-
def change_column_null(table_name, column_name, null, default = nil)
|
327
|
+
def change_column_null(table_name, column_name, null, default = nil) # :nodoc:
|
328
|
+
validate_change_column_null_argument!(null)
|
329
|
+
|
263
330
|
unless null || default.nil?
|
264
|
-
|
331
|
+
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")
|
265
332
|
end
|
266
333
|
alter_table(table_name) do |definition|
|
267
334
|
definition[column_name].null = null
|
268
335
|
end
|
269
336
|
end
|
270
337
|
|
271
|
-
def change_column(table_name, column_name, type, **options)
|
338
|
+
def change_column(table_name, column_name, type, **options) # :nodoc:
|
272
339
|
alter_table(table_name) do |definition|
|
273
|
-
definition
|
274
|
-
self.type = aliased_types(type.to_s, type)
|
275
|
-
self.options.merge!(options)
|
276
|
-
end
|
340
|
+
definition.change_column(column_name, type, **options)
|
277
341
|
end
|
278
342
|
end
|
279
343
|
|
280
|
-
def rename_column(table_name, column_name, new_column_name)
|
344
|
+
def rename_column(table_name, column_name, new_column_name) # :nodoc:
|
281
345
|
column = column_for(table_name, column_name)
|
282
346
|
alter_table(table_name, rename: { column.name => new_column_name.to_s })
|
283
347
|
rename_column_indexes(table_name, column.name, new_column_name)
|
284
348
|
end
|
285
349
|
|
350
|
+
def add_timestamps(table_name, **options)
|
351
|
+
options[:null] = false if options[:null].nil?
|
352
|
+
|
353
|
+
if !options.key?(:precision)
|
354
|
+
options[:precision] = 6
|
355
|
+
end
|
356
|
+
|
357
|
+
alter_table(table_name) do |definition|
|
358
|
+
definition.column :created_at, :datetime, **options
|
359
|
+
definition.column :updated_at, :datetime, **options
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
286
363
|
def add_reference(table_name, ref_name, **options) # :nodoc:
|
287
364
|
super(table_name, ref_name, type: :integer, **options)
|
288
365
|
end
|
289
366
|
alias :add_belongs_to :add_reference
|
290
367
|
|
291
368
|
def foreign_keys(table_name)
|
292
|
-
|
293
|
-
fk_info
|
369
|
+
# SQLite returns 1 row for each column of composite foreign keys.
|
370
|
+
fk_info = internal_exec_query("PRAGMA foreign_key_list(#{quote(table_name)})", "SCHEMA")
|
371
|
+
grouped_fk = fk_info.group_by { |row| row["id"] }.values.each { |group| group.sort_by! { |row| row["seq"] } }
|
372
|
+
grouped_fk.map do |group|
|
373
|
+
row = group.first
|
294
374
|
options = {
|
295
|
-
column: row["from"],
|
296
|
-
primary_key: row["to"],
|
297
375
|
on_delete: extract_foreign_key_action(row["on_delete"]),
|
298
376
|
on_update: extract_foreign_key_action(row["on_update"])
|
299
377
|
}
|
378
|
+
|
379
|
+
if group.one?
|
380
|
+
options[:column] = row["from"]
|
381
|
+
options[:primary_key] = row["to"]
|
382
|
+
else
|
383
|
+
options[:column] = group.map { |row| row["from"] }
|
384
|
+
options[:primary_key] = group.map { |row| row["to"] }
|
385
|
+
end
|
300
386
|
ForeignKeyDefinition.new(table_name, row["table"], options)
|
301
387
|
end
|
302
388
|
end
|
@@ -308,10 +394,15 @@ module ActiveRecord
|
|
308
394
|
sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
|
309
395
|
elsif insert.update_duplicates?
|
310
396
|
sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
|
311
|
-
|
312
|
-
|
397
|
+
if insert.raw_update_sql?
|
398
|
+
sql << insert.raw_update_sql
|
399
|
+
else
|
400
|
+
sql << insert.touch_model_timestamps_unless { |column| "#{column} IS excluded.#{column}" }
|
401
|
+
sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
|
402
|
+
end
|
313
403
|
end
|
314
404
|
|
405
|
+
sql << " RETURNING #{insert.returning}" if insert.returning
|
315
406
|
sql
|
316
407
|
end
|
317
408
|
|
@@ -319,8 +410,12 @@ module ActiveRecord
|
|
319
410
|
@config.fetch(:flags, 0).anybits?(::SQLite3::Constants::Open::SHAREDCACHE)
|
320
411
|
end
|
321
412
|
|
413
|
+
def use_insert_returning?
|
414
|
+
@use_insert_returning
|
415
|
+
end
|
416
|
+
|
322
417
|
def get_database_version # :nodoc:
|
323
|
-
SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)"))
|
418
|
+
SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)", "SCHEMA"))
|
324
419
|
end
|
325
420
|
|
326
421
|
def check_version # :nodoc:
|
@@ -329,6 +424,28 @@ module ActiveRecord
|
|
329
424
|
end
|
330
425
|
end
|
331
426
|
|
427
|
+
class SQLite3Integer < Type::Integer # :nodoc:
|
428
|
+
private
|
429
|
+
def _limit
|
430
|
+
# INTEGER storage class can be stored 8 bytes value.
|
431
|
+
# See https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes
|
432
|
+
limit || 8
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
ActiveRecord::Type.register(:integer, SQLite3Integer, adapter: :sqlite3)
|
437
|
+
|
438
|
+
class << self
|
439
|
+
private
|
440
|
+
def initialize_type_map(m)
|
441
|
+
super
|
442
|
+
register_class_with_limit m, %r(int)i, SQLite3Integer
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
|
447
|
+
EXTENDED_TYPE_MAPS = Concurrent::Map.new
|
448
|
+
|
332
449
|
private
|
333
450
|
# See https://www.sqlite.org/limits.html,
|
334
451
|
# the default value is 999 when not configured.
|
@@ -336,18 +453,44 @@ module ActiveRecord
|
|
336
453
|
999
|
337
454
|
end
|
338
455
|
|
339
|
-
def initialize_type_map(m = type_map)
|
340
|
-
super
|
341
|
-
register_class_with_limit m, %r(int)i, SQLite3Integer
|
342
|
-
end
|
343
|
-
|
344
456
|
def table_structure(table_name)
|
345
|
-
structure =
|
457
|
+
structure = internal_exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", "SCHEMA")
|
346
458
|
raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
|
347
459
|
table_structure_with_collation(table_name, structure)
|
348
460
|
end
|
349
461
|
alias column_definitions table_structure
|
350
462
|
|
463
|
+
def extract_value_from_default(default)
|
464
|
+
case default
|
465
|
+
when /^null$/i
|
466
|
+
nil
|
467
|
+
# Quoted types
|
468
|
+
when /^'([^|]*)'$/m
|
469
|
+
$1.gsub("''", "'")
|
470
|
+
# Quoted types
|
471
|
+
when /^"([^|]*)"$/m
|
472
|
+
$1.gsub('""', '"')
|
473
|
+
# Numeric types
|
474
|
+
when /\A-?\d+(\.\d*)?\z/
|
475
|
+
$&
|
476
|
+
# Binary columns
|
477
|
+
when /x'(.*)'/
|
478
|
+
[ $1 ].pack("H*")
|
479
|
+
else
|
480
|
+
# Anything else is blank or some function
|
481
|
+
# and we can't know the value of that, so return nil.
|
482
|
+
nil
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
def extract_default_function(default_value, default)
|
487
|
+
default if has_default_function?(default_value, default)
|
488
|
+
end
|
489
|
+
|
490
|
+
def has_default_function?(default_value, default)
|
491
|
+
!default_value && %r{\w+\(.*\)|CURRENT_TIME|CURRENT_DATE|CURRENT_TIMESTAMP|\|\|}.match?(default)
|
492
|
+
end
|
493
|
+
|
351
494
|
# See: https://www.sqlite.org/lang_altertable.html
|
352
495
|
# SQLite has an additional restriction on the ALTER TABLE statement
|
353
496
|
def invalid_alter_table_type?(type, options)
|
@@ -408,12 +551,27 @@ module ActiveRecord
|
|
408
551
|
options[:rename][column.name.to_sym] ||
|
409
552
|
column.name) : column.name
|
410
553
|
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
554
|
+
if column.has_default?
|
555
|
+
type = lookup_cast_type_from_column(column)
|
556
|
+
default = type.deserialize(column.default)
|
557
|
+
default = -> { column.default_function } if default.nil?
|
558
|
+
end
|
559
|
+
|
560
|
+
column_options = {
|
561
|
+
limit: column.limit,
|
562
|
+
precision: column.precision,
|
563
|
+
scale: column.scale,
|
564
|
+
null: column.null,
|
565
|
+
collation: column.collation,
|
415
566
|
primary_key: column_name == from_primary_key
|
416
|
-
|
567
|
+
}
|
568
|
+
|
569
|
+
unless column.auto_increment?
|
570
|
+
column_options[:default] = default
|
571
|
+
end
|
572
|
+
|
573
|
+
column_type = column.bigint? ? :bigint : column.type
|
574
|
+
@definition.column(column_name, column_type, **column_options)
|
417
575
|
end
|
418
576
|
|
419
577
|
yield @definition if block_given?
|
@@ -446,6 +604,7 @@ module ActiveRecord
|
|
446
604
|
options = { name: name.gsub(/(^|_)(#{from})_/, "\\1#{to}_"), internal: true }
|
447
605
|
options[:unique] = true if index.unique
|
448
606
|
options[:where] = index.where if index.where
|
607
|
+
options[:order] = index.orders if index.orders
|
449
608
|
add_index(to, columns, **options)
|
450
609
|
end
|
451
610
|
end
|
@@ -460,7 +619,7 @@ module ActiveRecord
|
|
460
619
|
quoted_columns = columns.map { |col| quote_column_name(col) } * ","
|
461
620
|
quoted_from_columns = from_columns_to_copy.map { |col| quote_column_name(col) } * ","
|
462
621
|
|
463
|
-
|
622
|
+
internal_exec_query("INSERT INTO #{quote_table_name(to)} (#{quoted_columns})
|
464
623
|
SELECT #{quoted_from_columns} FROM #{quote_table_name(from)}")
|
465
624
|
end
|
466
625
|
|
@@ -470,22 +629,24 @@ module ActiveRecord
|
|
470
629
|
# Older versions of SQLite return:
|
471
630
|
# column *column_name* is not unique
|
472
631
|
if exception.message.match?(/(column(s)? .* (is|are) not unique|UNIQUE constraint failed: .*)/i)
|
473
|
-
RecordNotUnique.new(message, sql: sql, binds: binds)
|
632
|
+
RecordNotUnique.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
474
633
|
elsif exception.message.match?(/(.* may not be NULL|NOT NULL constraint failed: .*)/i)
|
475
|
-
NotNullViolation.new(message, sql: sql, binds: binds)
|
634
|
+
NotNullViolation.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
476
635
|
elsif exception.message.match?(/FOREIGN KEY constraint failed/i)
|
477
|
-
InvalidForeignKey.new(message, sql: sql, binds: binds)
|
636
|
+
InvalidForeignKey.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
478
637
|
elsif exception.message.match?(/called on a closed database/i)
|
479
|
-
ConnectionNotEstablished.new(exception)
|
638
|
+
ConnectionNotEstablished.new(exception, connection_pool: @pool)
|
480
639
|
else
|
481
640
|
super
|
482
641
|
end
|
483
642
|
end
|
484
643
|
|
485
|
-
COLLATE_REGEX =
|
644
|
+
COLLATE_REGEX = /.*"(\w+)".*collate\s+"(\w+)".*/i
|
645
|
+
PRIMARY_KEY_AUTOINCREMENT_REGEX = /.*"(\w+)".+PRIMARY KEY AUTOINCREMENT/i
|
486
646
|
|
487
647
|
def table_structure_with_collation(table_name, basic_structure)
|
488
648
|
collation_hash = {}
|
649
|
+
auto_increments = {}
|
489
650
|
sql = <<~SQL
|
490
651
|
SELECT sql FROM
|
491
652
|
(SELECT * FROM sqlite_master UNION ALL
|
@@ -507,6 +668,7 @@ module ActiveRecord
|
|
507
668
|
# This regex will match the column name and collation type and will save
|
508
669
|
# the value in $1 and $2 respectively.
|
509
670
|
collation_hash[$1] = $2 if COLLATE_REGEX =~ column_string
|
671
|
+
auto_increments[$1] = true if PRIMARY_KEY_AUTOINCREMENT_REGEX =~ column_string
|
510
672
|
end
|
511
673
|
|
512
674
|
basic_structure.map do |column|
|
@@ -516,6 +678,10 @@ module ActiveRecord
|
|
516
678
|
column["collation"] = collation_hash[column_name]
|
517
679
|
end
|
518
680
|
|
681
|
+
if auto_increments.has_key?(column_name)
|
682
|
+
column["auto_increment"] = true
|
683
|
+
end
|
684
|
+
|
519
685
|
column
|
520
686
|
end
|
521
687
|
else
|
@@ -532,29 +698,55 @@ module ActiveRecord
|
|
532
698
|
end
|
533
699
|
|
534
700
|
def connect
|
535
|
-
@
|
536
|
-
|
537
|
-
|
538
|
-
)
|
539
|
-
configure_connection
|
701
|
+
@raw_connection = self.class.new_client(@connection_parameters)
|
702
|
+
rescue ConnectionNotEstablished => ex
|
703
|
+
raise ex.set_pool(@pool)
|
540
704
|
end
|
541
705
|
|
542
|
-
def
|
543
|
-
|
544
|
-
|
545
|
-
|
706
|
+
def reconnect
|
707
|
+
if active?
|
708
|
+
@raw_connection.rollback rescue nil
|
709
|
+
else
|
710
|
+
connect
|
711
|
+
end
|
546
712
|
end
|
547
713
|
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
714
|
+
def configure_connection
|
715
|
+
if @config[:timeout] && @config[:retries]
|
716
|
+
raise ArgumentError, "Cannot specify both timeout and retries arguments"
|
717
|
+
elsif @config[:timeout]
|
718
|
+
@raw_connection.busy_timeout(self.class.type_cast_config_to_integer(@config[:timeout]))
|
719
|
+
elsif @config[:retries]
|
720
|
+
retries = self.class.type_cast_config_to_integer(@config[:retries])
|
721
|
+
raw_connection.busy_handler do |count|
|
722
|
+
count <= retries
|
554
723
|
end
|
555
|
-
|
724
|
+
end
|
556
725
|
|
557
|
-
|
726
|
+
# Enforce foreign key constraints
|
727
|
+
# https://www.sqlite.org/pragma.html#pragma_foreign_keys
|
728
|
+
# https://www.sqlite.org/foreignkeys.html
|
729
|
+
raw_execute("PRAGMA foreign_keys = ON", "SCHEMA")
|
730
|
+
unless @memory_database
|
731
|
+
# Journal mode WAL allows for greater concurrency (many readers + one writer)
|
732
|
+
# https://www.sqlite.org/pragma.html#pragma_journal_mode
|
733
|
+
raw_execute("PRAGMA journal_mode = WAL", "SCHEMA")
|
734
|
+
# Set more relaxed level of database durability
|
735
|
+
# 2 = "FULL" (sync on every write), 1 = "NORMAL" (sync every 1000 written pages) and 0 = "NONE"
|
736
|
+
# https://www.sqlite.org/pragma.html#pragma_synchronous
|
737
|
+
raw_execute("PRAGMA synchronous = NORMAL", "SCHEMA")
|
738
|
+
# Set the global memory map so all processes can share some data
|
739
|
+
# https://www.sqlite.org/pragma.html#pragma_mmap_size
|
740
|
+
# https://www.sqlite.org/mmap.html
|
741
|
+
raw_execute("PRAGMA mmap_size = #{128.megabytes}", "SCHEMA")
|
742
|
+
end
|
743
|
+
# Impose a limit on the WAL file to prevent unlimited growth
|
744
|
+
# https://www.sqlite.org/pragma.html#pragma_journal_size_limit
|
745
|
+
raw_execute("PRAGMA journal_size_limit = #{64.megabytes}", "SCHEMA")
|
746
|
+
# Set the local connection cache to 2000 pages
|
747
|
+
# https://www.sqlite.org/pragma.html#pragma_cache_size
|
748
|
+
raw_execute("PRAGMA cache_size = 2000", "SCHEMA")
|
749
|
+
end
|
558
750
|
end
|
559
751
|
ActiveSupport.run_load_hooks(:active_record_sqlite3adapter, SQLite3Adapter)
|
560
752
|
end
|
@@ -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)
|