activerecord 5.0.7.2 → 5.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +389 -2252
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +28 -28
- data/examples/simple.rb +3 -3
- data/lib/active_record.rb +20 -20
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations.rb +1579 -1569
- data/lib/active_record/associations/alias_tracker.rb +1 -1
- data/lib/active_record/associations/association.rb +23 -15
- data/lib/active_record/associations/association_scope.rb +83 -81
- data/lib/active_record/associations/belongs_to_association.rb +0 -1
- data/lib/active_record/associations/builder/belongs_to.rb +16 -14
- data/lib/active_record/associations/builder/collection_association.rb +1 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
- data/lib/active_record/associations/collection_association.rb +74 -241
- data/lib/active_record/associations/collection_proxy.rb +144 -70
- data/lib/active_record/associations/has_many_association.rb +15 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -5
- data/lib/active_record/associations/has_one_association.rb +22 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency.rb +117 -115
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -13
- data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/preloader.rb +94 -94
- data/lib/active_record/associations/preloader/association.rb +87 -64
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
- data/lib/active_record/associations/preloader/collection_association.rb +6 -6
- data/lib/active_record/associations/preloader/has_many.rb +0 -2
- data/lib/active_record/associations/preloader/singular_association.rb +6 -8
- data/lib/active_record/associations/preloader/through_association.rb +34 -41
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +3 -6
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +216 -34
- data/lib/active_record/attribute_methods/primary_key.rb +78 -73
- data/lib/active_record/attribute_methods/read.rb +39 -35
- data/lib/active_record/attribute_methods/serialization.rb +7 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
- data/lib/active_record/attribute_methods/write.rb +36 -30
- data/lib/active_record/attribute_mutation_tracker.rb +53 -10
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attribute_set/builder.rb +41 -49
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attributes.rb +21 -21
- data/lib/active_record/autosave_association.rb +13 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +52 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +6 -17
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +320 -278
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -34
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -57
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +9 -19
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +78 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +99 -93
- data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +156 -128
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +424 -382
- data/lib/active_record/connection_adapters/column.rb +27 -5
- data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
- data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -43
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +49 -31
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +5 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +24 -26
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -35
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +9 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +28 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +38 -36
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +161 -170
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +179 -152
- data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -20
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +187 -130
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
- data/lib/active_record/connection_handling.rb +14 -26
- data/lib/active_record/core.rb +110 -93
- data/lib/active_record/counter_cache.rb +62 -13
- data/lib/active_record/define_callbacks.rb +20 -0
- data/lib/active_record/dynamic_matchers.rb +80 -79
- data/lib/active_record/enum.rb +8 -6
- data/lib/active_record/errors.rb +58 -15
- data/lib/active_record/explain.rb +1 -2
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +7 -4
- data/lib/active_record/fixture_set/file.rb +11 -8
- data/lib/active_record/fixtures.rb +66 -53
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +93 -79
- data/lib/active_record/integration.rb +7 -7
- data/lib/active_record/internal_metadata.rb +3 -16
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +64 -56
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +29 -29
- data/lib/active_record/migration.rb +155 -172
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +76 -37
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/model_schema.rb +85 -119
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +10 -33
- data/lib/active_record/persistence.rb +45 -38
- data/lib/active_record/query_cache.rb +4 -8
- data/lib/active_record/querying.rb +2 -3
- data/lib/active_record/railtie.rb +16 -17
- data/lib/active_record/railties/controller_runtime.rb +6 -2
- data/lib/active_record/railties/databases.rake +125 -140
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +2 -2
- data/lib/active_record/reflection.rb +79 -96
- data/lib/active_record/relation.rb +72 -115
- data/lib/active_record/relation/batches.rb +87 -58
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/calculations.rb +154 -160
- data/lib/active_record/relation/delegation.rb +30 -29
- data/lib/active_record/relation/finder_methods.rb +195 -226
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
- data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +247 -295
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +4 -5
- data/lib/active_record/relation/where_clause.rb +79 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/result.rb +29 -31
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +182 -197
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +14 -37
- data/lib/active_record/schema_migration.rb +3 -3
- data/lib/active_record/scoping.rb +9 -10
- data/lib/active_record/scoping/default.rb +87 -91
- data/lib/active_record/scoping/named.rb +16 -28
- data/lib/active_record/secure_token.rb +2 -2
- data/lib/active_record/statement_cache.rb +13 -15
- data/lib/active_record/store.rb +31 -32
- data/lib/active_record/suppressor.rb +2 -1
- data/lib/active_record/table_metadata.rb +9 -5
- data/lib/active_record/tasks/database_tasks.rb +72 -65
- data/lib/active_record/tasks/mysql_database_tasks.rb +75 -72
- data/lib/active_record/tasks/postgresql_database_tasks.rb +53 -48
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +39 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +98 -110
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +9 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/serialized.rb +8 -8
- data/lib/active_record/type/text.rb +9 -0
- data/lib/active_record/type/time.rb +0 -1
- data/lib/active_record/type/type_map.rb +11 -15
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type_caster.rb +2 -2
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.rb +4 -4
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +8 -39
- data/lib/active_record/version.rb +1 -1
- data/lib/rails/generators/active_record.rb +4 -4
- data/lib/rails/generators/active_record/migration.rb +2 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- metadata +22 -13
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -21,6 +21,22 @@ module ActiveRecord
|
|
21
21
|
@data_sources = @data_sources.dup
|
22
22
|
end
|
23
23
|
|
24
|
+
def encode_with(coder)
|
25
|
+
coder["columns"] = @columns
|
26
|
+
coder["columns_hash"] = @columns_hash
|
27
|
+
coder["primary_keys"] = @primary_keys
|
28
|
+
coder["data_sources"] = @data_sources
|
29
|
+
coder["version"] = ActiveRecord::Migrator.current_version
|
30
|
+
end
|
31
|
+
|
32
|
+
def init_with(coder)
|
33
|
+
@columns = coder["columns"]
|
34
|
+
@columns_hash = coder["columns_hash"]
|
35
|
+
@primary_keys = coder["primary_keys"]
|
36
|
+
@data_sources = coder["data_sources"]
|
37
|
+
@version = coder["version"]
|
38
|
+
end
|
39
|
+
|
24
40
|
def primary_keys(table_name)
|
25
41
|
@primary_keys[table_name] ||= data_source_exists?(table_name) ? connection.primary_key(table_name) : nil
|
26
42
|
end
|
@@ -32,9 +48,6 @@ module ActiveRecord
|
|
32
48
|
|
33
49
|
@data_sources[name] = connection.data_source_exists?(name)
|
34
50
|
end
|
35
|
-
alias table_exists? data_source_exists?
|
36
|
-
deprecate :table_exists? => "use #data_source_exists? instead"
|
37
|
-
|
38
51
|
|
39
52
|
# Add internal cache for table with +table_name+.
|
40
53
|
def add(table_name)
|
@@ -48,8 +61,6 @@ module ActiveRecord
|
|
48
61
|
def data_sources(name)
|
49
62
|
@data_sources[name]
|
50
63
|
end
|
51
|
-
alias tables data_sources
|
52
|
-
deprecate :tables => "use #data_sources instead"
|
53
64
|
|
54
65
|
# Get the columns for a table
|
55
66
|
def columns(table_name)
|
@@ -84,8 +95,6 @@ module ActiveRecord
|
|
84
95
|
@primary_keys.delete name
|
85
96
|
@data_sources.delete name
|
86
97
|
end
|
87
|
-
alias clear_table_cache! clear_data_source_cache!
|
88
|
-
deprecate :clear_table_cache! => "use #clear_data_source_cache! instead"
|
89
98
|
|
90
99
|
def marshal_dump
|
91
100
|
# if we get current version during initialization, it happens stack over flow.
|
@@ -11,37 +11,33 @@ module ActiveRecord
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def quote_column_name(name)
|
14
|
-
@quoted_column_names[name] ||= %Q("#{super.gsub('"', '""')}")
|
14
|
+
@quoted_column_names[name] ||= %Q("#{super.gsub('"', '""')}").freeze
|
15
15
|
end
|
16
16
|
|
17
17
|
def quoted_time(value)
|
18
|
-
quoted_date(value)
|
18
|
+
quoted_date(value)
|
19
19
|
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
def _quote(value)
|
24
|
-
if value.is_a?(Type::Binary::Data)
|
25
|
-
"x'#{value.hex}'"
|
26
|
-
else
|
27
|
-
super
|
28
|
-
end
|
21
|
+
def quoted_binary(value)
|
22
|
+
"x'#{value.hex}'"
|
29
23
|
end
|
30
24
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
value
|
35
|
-
|
36
|
-
|
37
|
-
|
25
|
+
private
|
26
|
+
|
27
|
+
def _type_cast(value)
|
28
|
+
case value
|
29
|
+
when BigDecimal
|
30
|
+
value.to_f
|
31
|
+
when String
|
32
|
+
if value.encoding == Encoding::ASCII_8BIT
|
33
|
+
super(value.encode(Encoding::UTF_8))
|
34
|
+
else
|
35
|
+
super
|
36
|
+
end
|
38
37
|
else
|
39
38
|
super
|
40
39
|
end
|
41
|
-
else
|
42
|
-
super
|
43
40
|
end
|
44
|
-
end
|
45
41
|
end
|
46
42
|
end
|
47
43
|
end
|
@@ -1,15 +1,8 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
3
|
module SQLite3
|
4
|
-
class SchemaCreation < AbstractAdapter::SchemaCreation
|
4
|
+
class SchemaCreation < AbstractAdapter::SchemaCreation # :nodoc:
|
5
5
|
private
|
6
|
-
|
7
|
-
def column_options(o)
|
8
|
-
options = super
|
9
|
-
options[:null] = false if o.primary_key
|
10
|
-
options
|
11
|
-
end
|
12
|
-
|
13
6
|
def add_column_options!(sql, options)
|
14
7
|
if options[:collation]
|
15
8
|
sql << " COLLATE \"#{options[:collation]}\""
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module SQLite3
|
4
|
+
module ColumnMethods
|
5
|
+
def primary_key(name, type = :primary_key, **options)
|
6
|
+
if %i(integer bigint).include?(type) && (options.delete(:auto_increment) == true || !options.key?(:default))
|
7
|
+
type = :primary_key
|
8
|
+
end
|
9
|
+
|
10
|
+
super
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
15
|
+
include ColumnMethods
|
16
|
+
|
17
|
+
def references(*args, **options)
|
18
|
+
super(*args, type: :integer, **options)
|
19
|
+
end
|
20
|
+
alias :belongs_to :references
|
21
|
+
end
|
22
|
+
|
23
|
+
class Table < ActiveRecord::ConnectionAdapters::Table
|
24
|
+
include ColumnMethods
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module SQLite3
|
4
|
+
module ColumnDumper # :nodoc:
|
5
|
+
private
|
6
|
+
|
7
|
+
def default_primary_key?(column)
|
8
|
+
schema_type(column) == :integer
|
9
|
+
end
|
10
|
+
|
11
|
+
def explicit_primary_key_default?(column)
|
12
|
+
column.bigint?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,11 +1,13 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
require "active_record/connection_adapters/abstract_adapter"
|
2
|
+
require "active_record/connection_adapters/statement_pool"
|
3
|
+
require "active_record/connection_adapters/sqlite3/explain_pretty_printer"
|
4
|
+
require "active_record/connection_adapters/sqlite3/quoting"
|
5
|
+
require "active_record/connection_adapters/sqlite3/schema_creation"
|
6
|
+
require "active_record/connection_adapters/sqlite3/schema_definitions"
|
7
|
+
require "active_record/connection_adapters/sqlite3/schema_dumper"
|
6
8
|
|
7
|
-
gem
|
8
|
-
require
|
9
|
+
gem "sqlite3", "~> 1.3.6"
|
10
|
+
require "sqlite3"
|
9
11
|
|
10
12
|
module ActiveRecord
|
11
13
|
module ConnectionHandling # :nodoc:
|
@@ -18,7 +20,7 @@ module ActiveRecord
|
|
18
20
|
# Allow database path relative to Rails.root, but only if the database
|
19
21
|
# path is not the special path that tells sqlite to build a database only
|
20
22
|
# in memory.
|
21
|
-
if
|
23
|
+
if ":memory:" != config[:database]
|
22
24
|
config[:database] = File.expand_path(config[:database], Rails.root) if defined?(Rails.root)
|
23
25
|
dirname = File.dirname(config[:database])
|
24
26
|
Dir.mkdir(dirname) unless File.directory?(dirname)
|
@@ -26,7 +28,7 @@ module ActiveRecord
|
|
26
28
|
|
27
29
|
db = SQLite3::Database.new(
|
28
30
|
config[:database].to_s,
|
29
|
-
:
|
31
|
+
results_as_hash: true
|
30
32
|
)
|
31
33
|
|
32
34
|
db.busy_timeout(ConnectionAdapters::SQLite3Adapter.type_cast_config_to_integer(config[:timeout])) if config[:timeout]
|
@@ -49,12 +51,13 @@ module ActiveRecord
|
|
49
51
|
#
|
50
52
|
# * <tt>:database</tt> - Path to the database file.
|
51
53
|
class SQLite3Adapter < AbstractAdapter
|
52
|
-
ADAPTER_NAME =
|
54
|
+
ADAPTER_NAME = "SQLite".freeze
|
53
55
|
|
54
56
|
include SQLite3::Quoting
|
57
|
+
include SQLite3::ColumnDumper
|
55
58
|
|
56
59
|
NATIVE_DATABASE_TYPES = {
|
57
|
-
primary_key:
|
60
|
+
primary_key: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL",
|
58
61
|
string: { name: "varchar" },
|
59
62
|
text: { name: "text" },
|
60
63
|
integer: { name: "integer" },
|
@@ -70,9 +73,13 @@ module ActiveRecord
|
|
70
73
|
class StatementPool < ConnectionAdapters::StatementPool
|
71
74
|
private
|
72
75
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
+
def dealloc(stmt)
|
77
|
+
stmt[:stmt].close unless stmt[:stmt].closed?
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def update_table_definition(table_name, base) # :nodoc:
|
82
|
+
SQLite3::Table.new(table_name, base)
|
76
83
|
end
|
77
84
|
|
78
85
|
def schema_creation # :nodoc:
|
@@ -88,6 +95,8 @@ module ActiveRecord
|
|
88
95
|
|
89
96
|
@active = nil
|
90
97
|
@statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
|
98
|
+
|
99
|
+
configure_connection
|
91
100
|
end
|
92
101
|
|
93
102
|
def supports_ddl_transactions?
|
@@ -99,7 +108,7 @@ module ActiveRecord
|
|
99
108
|
end
|
100
109
|
|
101
110
|
def supports_partial_index?
|
102
|
-
sqlite_version >=
|
111
|
+
sqlite_version >= "3.8.0"
|
103
112
|
end
|
104
113
|
|
105
114
|
# Returns true, since this connection adapter supports prepared statement
|
@@ -113,12 +122,12 @@ module ActiveRecord
|
|
113
122
|
true
|
114
123
|
end
|
115
124
|
|
116
|
-
def
|
125
|
+
def requires_reloading?
|
117
126
|
true
|
118
127
|
end
|
119
128
|
|
120
|
-
def
|
121
|
-
|
129
|
+
def supports_foreign_keys_in_create?
|
130
|
+
sqlite_version >= "3.6.19"
|
122
131
|
end
|
123
132
|
|
124
133
|
def supports_views?
|
@@ -130,7 +139,7 @@ module ActiveRecord
|
|
130
139
|
end
|
131
140
|
|
132
141
|
def supports_multi_insert?
|
133
|
-
sqlite_version >=
|
142
|
+
sqlite_version >= "3.7.11"
|
134
143
|
end
|
135
144
|
|
136
145
|
def active?
|
@@ -159,7 +168,7 @@ module ActiveRecord
|
|
159
168
|
end
|
160
169
|
|
161
170
|
# Returns 62. SQLite supports index names up to 64
|
162
|
-
# characters. The rest is used by
|
171
|
+
# characters. The rest is used by Rails internally to perform
|
163
172
|
# temporary rename operations
|
164
173
|
def allowed_index_name_length
|
165
174
|
index_name_length - 2
|
@@ -178,47 +187,62 @@ module ActiveRecord
|
|
178
187
|
true
|
179
188
|
end
|
180
189
|
|
190
|
+
# REFERENTIAL INTEGRITY ====================================
|
191
|
+
|
192
|
+
def disable_referential_integrity # :nodoc:
|
193
|
+
old = select_value("PRAGMA foreign_keys")
|
194
|
+
|
195
|
+
begin
|
196
|
+
execute("PRAGMA foreign_keys = OFF")
|
197
|
+
yield
|
198
|
+
ensure
|
199
|
+
execute("PRAGMA foreign_keys = #{old}")
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
181
203
|
#--
|
182
204
|
# DATABASE STATEMENTS ======================================
|
183
205
|
#++
|
184
206
|
|
185
207
|
def explain(arel, binds = [])
|
186
208
|
sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
|
187
|
-
SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql,
|
209
|
+
SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", []))
|
188
210
|
end
|
189
211
|
|
190
212
|
def exec_query(sql, name = nil, binds = [], prepare: false)
|
191
213
|
type_casted_binds = type_casted_binds(binds)
|
192
214
|
|
193
215
|
log(sql, name, binds, type_casted_binds) do
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
216
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
217
|
+
# Don't cache statements if they are not prepared
|
218
|
+
unless prepare
|
219
|
+
stmt = @connection.prepare(sql)
|
220
|
+
begin
|
221
|
+
cols = stmt.columns
|
222
|
+
unless without_prepared_statement?(binds)
|
223
|
+
stmt.bind_params(type_casted_binds)
|
224
|
+
end
|
225
|
+
records = stmt.to_a
|
226
|
+
ensure
|
227
|
+
stmt.close
|
201
228
|
end
|
229
|
+
else
|
230
|
+
cache = @statements[sql] ||= {
|
231
|
+
stmt: @connection.prepare(sql)
|
232
|
+
}
|
233
|
+
stmt = cache[:stmt]
|
234
|
+
cols = cache[:cols] ||= stmt.columns
|
235
|
+
stmt.reset!
|
236
|
+
stmt.bind_params(type_casted_binds)
|
202
237
|
records = stmt.to_a
|
203
|
-
ensure
|
204
|
-
stmt.close
|
205
238
|
end
|
206
|
-
else
|
207
|
-
cache = @statements[sql] ||= {
|
208
|
-
:stmt => @connection.prepare(sql)
|
209
|
-
}
|
210
|
-
stmt = cache[:stmt]
|
211
|
-
cols = cache[:cols] ||= stmt.columns
|
212
|
-
stmt.reset!
|
213
|
-
stmt.bind_params(type_casted_binds)
|
214
|
-
records = stmt.to_a
|
215
|
-
end
|
216
239
|
|
217
|
-
|
240
|
+
ActiveRecord::Result.new(cols, records)
|
241
|
+
end
|
218
242
|
end
|
219
243
|
end
|
220
244
|
|
221
|
-
def exec_delete(sql, name =
|
245
|
+
def exec_delete(sql, name = "SQL", binds = [])
|
222
246
|
exec_query(sql, name, binds)
|
223
247
|
@connection.changes
|
224
248
|
end
|
@@ -229,64 +253,55 @@ module ActiveRecord
|
|
229
253
|
end
|
230
254
|
|
231
255
|
def execute(sql, name = nil) #:nodoc:
|
232
|
-
log(sql, name)
|
256
|
+
log(sql, name) do
|
257
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
258
|
+
@connection.execute(sql)
|
259
|
+
end
|
260
|
+
end
|
233
261
|
end
|
234
262
|
|
235
263
|
def begin_db_transaction #:nodoc:
|
236
|
-
log(
|
264
|
+
log("begin transaction", nil) { @connection.transaction }
|
237
265
|
end
|
238
266
|
|
239
267
|
def commit_db_transaction #:nodoc:
|
240
|
-
log(
|
268
|
+
log("commit transaction", nil) { @connection.commit }
|
241
269
|
end
|
242
270
|
|
243
271
|
def exec_rollback_db_transaction #:nodoc:
|
244
|
-
log(
|
272
|
+
log("rollback transaction", nil) { @connection.rollback }
|
245
273
|
end
|
246
274
|
|
247
275
|
# SCHEMA STATEMENTS ========================================
|
248
276
|
|
249
|
-
def tables
|
250
|
-
|
251
|
-
|
252
|
-
This behavior is deprecated and will be changed with Rails 5.1 to only return tables.
|
253
|
-
Use #data_sources instead.
|
254
|
-
MSG
|
255
|
-
|
256
|
-
if name
|
257
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
258
|
-
Passing arguments to #tables is deprecated without replacement.
|
259
|
-
MSG
|
260
|
-
end
|
277
|
+
def tables # :nodoc:
|
278
|
+
select_values("SELECT name FROM sqlite_master WHERE type = 'table' AND name <> 'sqlite_sequence'", "SCHEMA")
|
279
|
+
end
|
261
280
|
|
262
|
-
|
281
|
+
def data_sources # :nodoc:
|
282
|
+
select_values("SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'", "SCHEMA")
|
263
283
|
end
|
264
284
|
|
265
|
-
def
|
266
|
-
select_values("SELECT name FROM sqlite_master WHERE type
|
285
|
+
def views # :nodoc:
|
286
|
+
select_values("SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'", "SCHEMA")
|
267
287
|
end
|
268
288
|
|
269
|
-
def table_exists?(table_name)
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
MSG
|
289
|
+
def table_exists?(table_name) # :nodoc:
|
290
|
+
return false unless table_name.present?
|
291
|
+
|
292
|
+
sql = "SELECT name FROM sqlite_master WHERE type = 'table' AND name <> 'sqlite_sequence'"
|
293
|
+
sql << " AND name = #{quote(table_name)}"
|
275
294
|
|
276
|
-
|
295
|
+
select_values(sql, "SCHEMA").any?
|
277
296
|
end
|
278
297
|
|
279
|
-
def data_source_exists?(table_name)
|
298
|
+
def data_source_exists?(table_name) # :nodoc:
|
280
299
|
return false unless table_name.present?
|
281
300
|
|
282
301
|
sql = "SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'"
|
283
302
|
sql << " AND name = #{quote(table_name)}"
|
284
303
|
|
285
|
-
select_values(sql,
|
286
|
-
end
|
287
|
-
|
288
|
-
def views # :nodoc:
|
289
|
-
select_values("SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'", 'SCHEMA')
|
304
|
+
select_values(sql, "SCHEMA").any?
|
290
305
|
end
|
291
306
|
|
292
307
|
def view_exists?(view_name) # :nodoc:
|
@@ -295,32 +310,34 @@ module ActiveRecord
|
|
295
310
|
sql = "SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'"
|
296
311
|
sql << " AND name = #{quote(view_name)}"
|
297
312
|
|
298
|
-
select_values(sql,
|
313
|
+
select_values(sql, "SCHEMA").any?
|
299
314
|
end
|
300
315
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
field["dflt_value"] = $1.gsub("''", "'")
|
310
|
-
when /^"(.*)"$/m
|
311
|
-
field["dflt_value"] = $1.gsub('""', '"')
|
312
|
-
end
|
313
|
-
|
314
|
-
collation = field['collation']
|
315
|
-
sql_type = field['type']
|
316
|
-
type_metadata = fetch_type_metadata(sql_type)
|
317
|
-
new_column(field['name'], field['dflt_value'], type_metadata, field['notnull'].to_i == 0, table_name, nil, collation)
|
316
|
+
def new_column_from_field(table_name, field) # :nondoc:
|
317
|
+
case field["dflt_value"]
|
318
|
+
when /^null$/i
|
319
|
+
field["dflt_value"] = nil
|
320
|
+
when /^'(.*)'$/m
|
321
|
+
field["dflt_value"] = $1.gsub("''", "'")
|
322
|
+
when /^"(.*)"$/m
|
323
|
+
field["dflt_value"] = $1.gsub('""', '"')
|
318
324
|
end
|
325
|
+
|
326
|
+
collation = field["collation"]
|
327
|
+
sql_type = field["type"]
|
328
|
+
type_metadata = fetch_type_metadata(sql_type)
|
329
|
+
new_column(field["name"], field["dflt_value"], type_metadata, field["notnull"].to_i == 0, table_name, nil, collation)
|
319
330
|
end
|
320
331
|
|
321
332
|
# Returns an array of indexes for the given table.
|
322
333
|
def indexes(table_name, name = nil) #:nodoc:
|
323
|
-
|
334
|
+
if name
|
335
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
336
|
+
Passing name to #indexes is deprecated without replacement.
|
337
|
+
MSG
|
338
|
+
end
|
339
|
+
|
340
|
+
exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", "SCHEMA").map do |row|
|
324
341
|
sql = <<-SQL
|
325
342
|
SELECT sql
|
326
343
|
FROM sqlite_master
|
@@ -330,22 +347,22 @@ module ActiveRecord
|
|
330
347
|
FROM sqlite_temp_master
|
331
348
|
WHERE name=#{quote(row['name'])} AND type='index'
|
332
349
|
SQL
|
333
|
-
index_sql = exec_query(sql).first[
|
350
|
+
index_sql = exec_query(sql).first["sql"]
|
334
351
|
match = /\sWHERE\s+(.+)$/i.match(index_sql)
|
335
352
|
where = match[1] if match
|
336
353
|
IndexDefinition.new(
|
337
354
|
table_name,
|
338
|
-
row[
|
339
|
-
row[
|
355
|
+
row["name"],
|
356
|
+
row["unique"] != 0,
|
340
357
|
exec_query("PRAGMA index_info('#{row['name']}')", "SCHEMA").map { |col|
|
341
|
-
col[
|
358
|
+
col["name"]
|
342
359
|
}, nil, nil, where)
|
343
360
|
end
|
344
361
|
end
|
345
362
|
|
346
363
|
def primary_keys(table_name) # :nodoc:
|
347
|
-
pks = table_structure(table_name).select { |f| f[
|
348
|
-
pks.sort_by { |f| f[
|
364
|
+
pks = table_structure(table_name).select { |f| f["pk"] > 0 }
|
365
|
+
pks.sort_by { |f| f["pk"] }.map { |f| f["name"] }
|
349
366
|
end
|
350
367
|
|
351
368
|
def remove_index(table_name, options = {}) #:nodoc:
|
@@ -410,7 +427,7 @@ module ActiveRecord
|
|
410
427
|
self.default = options[:default] if include_default
|
411
428
|
self.null = options[:null] if options.include?(:null)
|
412
429
|
self.precision = options[:precision] if options.include?(:precision)
|
413
|
-
self.scale
|
430
|
+
self.scale = options[:scale] if options.include?(:scale)
|
414
431
|
self.collation = options[:collation] if options.include?(:collation)
|
415
432
|
end
|
416
433
|
end
|
@@ -418,35 +435,54 @@ module ActiveRecord
|
|
418
435
|
|
419
436
|
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
420
437
|
column = column_for(table_name, column_name)
|
421
|
-
alter_table(table_name, rename: {column.name => new_column_name.to_s})
|
438
|
+
alter_table(table_name, rename: { column.name => new_column_name.to_s })
|
422
439
|
rename_column_indexes(table_name, column.name, new_column_name)
|
423
440
|
end
|
424
441
|
|
425
|
-
|
442
|
+
def add_reference(table_name, ref_name, **options) # :nodoc:
|
443
|
+
super(table_name, ref_name, type: :integer, **options)
|
444
|
+
end
|
445
|
+
alias :add_belongs_to :add_reference
|
446
|
+
|
447
|
+
def foreign_keys(table_name)
|
448
|
+
fk_info = select_all("PRAGMA foreign_key_list(#{quote(table_name)})", "SCHEMA")
|
449
|
+
fk_info.map do |row|
|
450
|
+
options = {
|
451
|
+
column: row["from"],
|
452
|
+
primary_key: row["to"],
|
453
|
+
on_delete: extract_foreign_key_action(row["on_delete"]),
|
454
|
+
on_update: extract_foreign_key_action(row["on_update"])
|
455
|
+
}
|
456
|
+
ForeignKeyDefinition.new(table_name, row["table"], options)
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
private
|
426
461
|
|
427
462
|
def table_structure(table_name)
|
428
|
-
structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})",
|
463
|
+
structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", "SCHEMA")
|
429
464
|
raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
|
430
465
|
table_structure_with_collation(table_name, structure)
|
431
466
|
end
|
467
|
+
alias column_definitions table_structure
|
432
468
|
|
433
|
-
def alter_table(table_name, options = {})
|
469
|
+
def alter_table(table_name, options = {})
|
434
470
|
altered_table_name = "a#{table_name}"
|
435
|
-
caller = lambda {|definition| yield definition if block_given?}
|
471
|
+
caller = lambda { |definition| yield definition if block_given? }
|
436
472
|
|
437
473
|
transaction do
|
438
474
|
move_table(table_name, altered_table_name,
|
439
|
-
options.merge(:
|
475
|
+
options.merge(temporary: true))
|
440
476
|
move_table(altered_table_name, table_name, &caller)
|
441
477
|
end
|
442
478
|
end
|
443
479
|
|
444
|
-
def move_table(from, to, options = {}, &block)
|
480
|
+
def move_table(from, to, options = {}, &block)
|
445
481
|
copy_table(from, to, options, &block)
|
446
482
|
drop_table(from)
|
447
483
|
end
|
448
484
|
|
449
|
-
def copy_table(from, to, options = {})
|
485
|
+
def copy_table(from, to, options = {})
|
450
486
|
from_primary_key = primary_key(from)
|
451
487
|
options[:id] = false
|
452
488
|
create_table(to, options) do |definition|
|
@@ -460,9 +496,9 @@ module ActiveRecord
|
|
460
496
|
next if column_name == from_primary_key
|
461
497
|
|
462
498
|
@definition.column(column_name, column.type,
|
463
|
-
:
|
464
|
-
:
|
465
|
-
:
|
499
|
+
limit: column.limit, default: column.default,
|
500
|
+
precision: column.precision, scale: column.scale,
|
501
|
+
null: column.null, collation: column.collation)
|
466
502
|
end
|
467
503
|
yield @definition if block_given?
|
468
504
|
end
|
@@ -472,7 +508,7 @@ module ActiveRecord
|
|
472
508
|
options[:rename] || {})
|
473
509
|
end
|
474
510
|
|
475
|
-
def copy_table_indexes(from, to, rename = {})
|
511
|
+
def copy_table_indexes(from, to, rename = {})
|
476
512
|
indexes(from).each do |index|
|
477
513
|
name = index.name
|
478
514
|
if to == "a#{from}"
|
@@ -482,7 +518,7 @@ module ActiveRecord
|
|
482
518
|
end
|
483
519
|
|
484
520
|
to_column_names = columns(to).map(&:name)
|
485
|
-
columns = index.columns.map {|c| rename[c] || c }.select do |column|
|
521
|
+
columns = index.columns.map { |c| rename[c] || c }.select do |column|
|
486
522
|
to_column_names.include?(column)
|
487
523
|
end
|
488
524
|
|
@@ -495,21 +531,21 @@ module ActiveRecord
|
|
495
531
|
end
|
496
532
|
end
|
497
533
|
|
498
|
-
def copy_table_contents(from, to, columns, rename = {})
|
499
|
-
column_mappings = Hash[columns.map {|name| [name, name]}]
|
534
|
+
def copy_table_contents(from, to, columns, rename = {})
|
535
|
+
column_mappings = Hash[columns.map { |name| [name, name] }]
|
500
536
|
rename.each { |a| column_mappings[a.last] = a.first }
|
501
537
|
from_columns = columns(from).collect(&:name)
|
502
|
-
columns = columns.find_all{|col| from_columns.include?(column_mappings[col])}
|
538
|
+
columns = columns.find_all { |col| from_columns.include?(column_mappings[col]) }
|
503
539
|
from_columns_to_copy = columns.map { |col| column_mappings[col] }
|
504
|
-
quoted_columns = columns.map { |col| quote_column_name(col) } *
|
505
|
-
quoted_from_columns = from_columns_to_copy.map { |col| quote_column_name(col) } *
|
540
|
+
quoted_columns = columns.map { |col| quote_column_name(col) } * ","
|
541
|
+
quoted_from_columns = from_columns_to_copy.map { |col| quote_column_name(col) } * ","
|
506
542
|
|
507
543
|
exec_query("INSERT INTO #{quote_table_name(to)} (#{quoted_columns})
|
508
544
|
SELECT #{quoted_from_columns} FROM #{quote_table_name(from)}")
|
509
545
|
end
|
510
546
|
|
511
547
|
def sqlite_version
|
512
|
-
@sqlite_version ||= SQLite3Adapter::Version.new(select_value(
|
548
|
+
@sqlite_version ||= SQLite3Adapter::Version.new(select_value("select sqlite_version(*)"))
|
513
549
|
end
|
514
550
|
|
515
551
|
def translate_exception(exception, message)
|
@@ -520,42 +556,47 @@ module ActiveRecord
|
|
520
556
|
# column *column_name* is not unique
|
521
557
|
when /column(s)? .* (is|are) not unique/, /UNIQUE constraint failed: .*/
|
522
558
|
RecordNotUnique.new(message)
|
559
|
+
when /.* may not be NULL/, /NOT NULL constraint failed: .*/
|
560
|
+
NotNullViolation.new(message)
|
561
|
+
when /FOREIGN KEY constraint failed/i
|
562
|
+
InvalidForeignKey.new(message)
|
523
563
|
else
|
524
564
|
super
|
525
565
|
end
|
526
566
|
end
|
527
567
|
|
528
|
-
private
|
529
568
|
COLLATE_REGEX = /.*\"(\w+)\".*collate\s+\"(\w+)\".*/i.freeze
|
530
569
|
|
531
570
|
def table_structure_with_collation(table_name, basic_structure)
|
532
571
|
collation_hash = {}
|
533
|
-
sql
|
534
|
-
|
535
|
-
|
536
|
-
|
572
|
+
sql = <<-SQL
|
573
|
+
SELECT sql FROM
|
574
|
+
(SELECT * FROM sqlite_master UNION ALL
|
575
|
+
SELECT * FROM sqlite_temp_master)
|
576
|
+
WHERE type = 'table' AND name = #{quote(table_name)}
|
577
|
+
SQL
|
537
578
|
|
538
579
|
# Result will have following sample string
|
539
580
|
# CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
540
581
|
# "password_digest" varchar COLLATE "NOCASE");
|
541
|
-
result = exec_query(sql,
|
582
|
+
result = exec_query(sql, "SCHEMA").first
|
542
583
|
|
543
584
|
if result
|
544
585
|
# Splitting with left parentheses and picking up last will return all
|
545
586
|
# columns separated with comma(,).
|
546
|
-
columns_string = result["sql"].split(
|
587
|
+
columns_string = result["sql"].split("(").last
|
547
588
|
|
548
|
-
columns_string.split(
|
589
|
+
columns_string.split(",").each do |column_string|
|
549
590
|
# This regex will match the column name and collation type and will save
|
550
591
|
# the value in $1 and $2 respectively.
|
551
|
-
collation_hash[$1] = $2 if
|
592
|
+
collation_hash[$1] = $2 if COLLATE_REGEX =~ column_string
|
552
593
|
end
|
553
594
|
|
554
595
|
basic_structure.map! do |column|
|
555
|
-
column_name = column[
|
596
|
+
column_name = column["name"]
|
556
597
|
|
557
598
|
if collation_hash.has_key? column_name
|
558
|
-
column[
|
599
|
+
column["collation"] = collation_hash[column_name]
|
559
600
|
end
|
560
601
|
|
561
602
|
column
|
@@ -564,6 +605,22 @@ module ActiveRecord
|
|
564
605
|
basic_structure.to_hash
|
565
606
|
end
|
566
607
|
end
|
608
|
+
|
609
|
+
def create_table_definition(*args)
|
610
|
+
SQLite3::TableDefinition.new(*args)
|
611
|
+
end
|
612
|
+
|
613
|
+
def extract_foreign_key_action(specifier)
|
614
|
+
case specifier
|
615
|
+
when "CASCADE"; :cascade
|
616
|
+
when "SET NULL"; :nullify
|
617
|
+
when "RESTRICT"; :restrict
|
618
|
+
end
|
619
|
+
end
|
620
|
+
|
621
|
+
def configure_connection
|
622
|
+
execute("PRAGMA foreign_keys = ON", "SCHEMA")
|
623
|
+
end
|
567
624
|
end
|
568
625
|
end
|
569
626
|
end
|