activerecord 6.0.0 → 6.1.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1178 -600
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/lib/active_record/aggregations.rb +5 -6
- data/lib/active_record/association_relation.rb +30 -10
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +55 -29
- data/lib/active_record/associations/association_scope.rb +19 -15
- data/lib/active_record/associations/belongs_to_association.rb +23 -10
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
- data/lib/active_record/associations/builder/association.rb +32 -5
- data/lib/active_record/associations/builder/belongs_to.rb +10 -7
- data/lib/active_record/associations/builder/collection_association.rb +5 -4
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -3
- data/lib/active_record/associations/builder/has_many.rb +6 -2
- data/lib/active_record/associations/builder/has_one.rb +11 -14
- data/lib/active_record/associations/builder/singular_association.rb +1 -1
- data/lib/active_record/associations/collection_association.rb +25 -8
- data/lib/active_record/associations/collection_proxy.rb +14 -7
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +24 -3
- data/lib/active_record/associations/has_many_through_association.rb +10 -4
- data/lib/active_record/associations/has_one_association.rb +15 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -16
- data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
- data/lib/active_record/associations/join_dependency.rb +77 -42
- data/lib/active_record/associations/preloader/association.rb +51 -25
- data/lib/active_record/associations/preloader/through_association.rb +2 -2
- data/lib/active_record/associations/preloader.rb +13 -8
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +120 -13
- data/lib/active_record/attribute_assignment.rb +10 -9
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
- data/lib/active_record/attribute_methods/dirty.rb +3 -13
- data/lib/active_record/attribute_methods/primary_key.rb +6 -4
- data/lib/active_record/attribute_methods/query.rb +3 -6
- data/lib/active_record/attribute_methods/read.rb +8 -12
- data/lib/active_record/attribute_methods/serialization.rb +11 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +12 -21
- data/lib/active_record/attribute_methods.rb +64 -54
- data/lib/active_record/attributes.rb +33 -9
- data/lib/active_record/autosave_association.rb +63 -44
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +153 -24
- data/lib/active_record/coders/yaml_column.rb +12 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +202 -138
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +87 -38
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +5 -10
- data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +141 -52
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +267 -105
- data/lib/active_record/connection_adapters/abstract/transaction.rb +94 -36
- data/lib/active_record/connection_adapters/abstract_adapter.rb +76 -79
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -115
- data/lib/active_record/connection_adapters/column.rb +15 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +30 -36
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +18 -3
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -13
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -56
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -65
- data/lib/active_record/connection_adapters/schema_cache.rb +106 -15
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +38 -12
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -57
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +219 -81
- data/lib/active_record/core.rb +268 -71
- data/lib/active_record/counter_cache.rb +4 -1
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +52 -9
- data/lib/active_record/database_configurations/hash_config.rb +54 -8
- data/lib/active_record/database_configurations/url_config.rb +15 -41
- data/lib/active_record/database_configurations.rb +124 -85
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +2 -3
- data/lib/active_record/enum.rb +80 -38
- data/lib/active_record/errors.rb +47 -12
- data/lib/active_record/explain.rb +9 -5
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +1 -2
- data/lib/active_record/fixture_set/render_context.rb +1 -1
- data/lib/active_record/fixture_set/table_row.rb +2 -3
- data/lib/active_record/fixture_set/table_rows.rb +0 -1
- data/lib/active_record/fixtures.rb +58 -12
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +40 -21
- data/lib/active_record/insert_all.rb +43 -10
- data/lib/active_record/integration.rb +3 -5
- data/lib/active_record/internal_metadata.rb +16 -7
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +33 -18
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +28 -9
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +14 -14
- data/lib/active_record/middleware/database_selector.rb +4 -2
- data/lib/active_record/migration/command_recorder.rb +53 -45
- data/lib/active_record/migration/compatibility.rb +71 -20
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +115 -85
- data/lib/active_record/model_schema.rb +120 -15
- data/lib/active_record/nested_attributes.rb +2 -5
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +50 -46
- data/lib/active_record/query_cache.rb +15 -5
- data/lib/active_record/querying.rb +12 -7
- data/lib/active_record/railtie.rb +65 -45
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/databases.rake +280 -99
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +77 -63
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +38 -32
- data/lib/active_record/relation/calculations.rb +106 -45
- data/lib/active_record/relation/delegation.rb +9 -7
- data/lib/active_record/relation/finder_methods.rb +55 -17
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +27 -26
- data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +59 -40
- data/lib/active_record/relation/query_methods.rb +344 -181
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -8
- data/lib/active_record/relation/where_clause.rb +111 -62
- data/lib/active_record/relation.rb +116 -82
- data/lib/active_record/result.rb +41 -34
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +6 -17
- data/lib/active_record/schema_dumper.rb +34 -4
- data/lib/active_record/schema_migration.rb +2 -8
- data/lib/active_record/scoping/default.rb +1 -4
- data/lib/active_record/scoping/named.rb +7 -18
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +20 -4
- data/lib/active_record/store.rb +3 -3
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +42 -36
- data/lib/active_record/tasks/database_tasks.rb +140 -113
- data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
- data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
- data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +79 -16
- data/lib/active_record/timestamp.rb +4 -7
- data/lib/active_record/touch_later.rb +20 -21
- data/lib/active_record/transactions.rb +26 -73
- data/lib/active_record/type/adapter_specific_registry.rb +2 -5
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +8 -2
- data/lib/active_record/type_caster/connection.rb +0 -1
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record.rb +7 -13
- data/lib/arel/attributes/attribute.rb +4 -0
- data/lib/arel/collectors/bind.rb +5 -0
- data/lib/arel/collectors/composite.rb +8 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/nodes/binary.rb +82 -8
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/casted.rb +21 -9
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/node.rb +7 -6
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/sql_literal.rb +3 -0
- data/lib/arel/nodes/table_alias.rb +7 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes.rb +3 -1
- data/lib/arel/predications.rb +17 -24
- data/lib/arel/select_manager.rb +1 -2
- data/lib/arel/table.rb +13 -5
- data/lib/arel/visitors/dot.rb +14 -3
- data/lib/arel/visitors/mysql.rb +11 -1
- data/lib/arel/visitors/postgresql.rb +15 -5
- data/lib/arel/visitors/sqlite.rb +0 -1
- data/lib/arel/visitors/to_sql.rb +89 -79
- data/lib/arel/visitors/visitor.rb +0 -1
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel.rb +15 -12
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
- data/lib/rails/generators/active_record/migration.rb +6 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- metadata +27 -24
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -204
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -157
- data/lib/arel/visitors/oracle.rb +0 -159
- data/lib/arel/visitors/oracle12.rb +0 -66
- data/lib/arel/visitors/where_sql.rb +0 -23
@@ -1,8 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/file/atomic"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module ConnectionAdapters
|
5
7
|
class SchemaCache
|
8
|
+
def self.load_from(filename)
|
9
|
+
return unless File.file?(filename)
|
10
|
+
|
11
|
+
read(filename) do |file|
|
12
|
+
if filename.include?(".dump")
|
13
|
+
Marshal.load(file)
|
14
|
+
else
|
15
|
+
if YAML.respond_to?(:unsafe_load)
|
16
|
+
YAML.unsafe_load(file)
|
17
|
+
else
|
18
|
+
YAML.load(file)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.read(filename, &block)
|
25
|
+
if File.extname(filename) == ".gz"
|
26
|
+
Zlib::GzipReader.open(filename) { |gz|
|
27
|
+
yield gz.read
|
28
|
+
}
|
29
|
+
else
|
30
|
+
yield File.read(filename)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
private_class_method :read
|
34
|
+
|
6
35
|
attr_reader :version
|
7
36
|
attr_accessor :connection
|
8
37
|
|
@@ -26,27 +55,33 @@ module ActiveRecord
|
|
26
55
|
end
|
27
56
|
|
28
57
|
def encode_with(coder)
|
58
|
+
reset_version!
|
59
|
+
|
29
60
|
coder["columns"] = @columns
|
30
|
-
coder["columns_hash"] = @columns_hash
|
31
61
|
coder["primary_keys"] = @primary_keys
|
32
62
|
coder["data_sources"] = @data_sources
|
33
63
|
coder["indexes"] = @indexes
|
34
|
-
coder["version"] =
|
64
|
+
coder["version"] = @version
|
35
65
|
coder["database_version"] = database_version
|
36
66
|
end
|
37
67
|
|
38
68
|
def init_with(coder)
|
39
69
|
@columns = coder["columns"]
|
40
|
-
@columns_hash = coder["columns_hash"]
|
41
70
|
@primary_keys = coder["primary_keys"]
|
42
71
|
@data_sources = coder["data_sources"]
|
43
72
|
@indexes = coder["indexes"] || {}
|
44
73
|
@version = coder["version"]
|
45
74
|
@database_version = coder["database_version"]
|
75
|
+
|
76
|
+
derive_columns_hash_and_deduplicate_values
|
46
77
|
end
|
47
78
|
|
48
79
|
def primary_keys(table_name)
|
49
|
-
@primary_keys
|
80
|
+
@primary_keys.fetch(table_name) do
|
81
|
+
if data_source_exists?(table_name)
|
82
|
+
@primary_keys[deep_deduplicate(table_name)] = deep_deduplicate(connection.primary_key(table_name))
|
83
|
+
end
|
84
|
+
end
|
50
85
|
end
|
51
86
|
|
52
87
|
# A cached lookup for table existence.
|
@@ -54,7 +89,7 @@ module ActiveRecord
|
|
54
89
|
prepare_data_sources if @data_sources.empty?
|
55
90
|
return @data_sources[name] if @data_sources.key? name
|
56
91
|
|
57
|
-
@data_sources[name] = connection.data_source_exists?(name)
|
92
|
+
@data_sources[deep_deduplicate(name)] = connection.data_source_exists?(name)
|
58
93
|
end
|
59
94
|
|
60
95
|
# Add internal cache for table with +table_name+.
|
@@ -73,15 +108,17 @@ module ActiveRecord
|
|
73
108
|
|
74
109
|
# Get the columns for a table
|
75
110
|
def columns(table_name)
|
76
|
-
@columns
|
111
|
+
@columns.fetch(table_name) do
|
112
|
+
@columns[deep_deduplicate(table_name)] = deep_deduplicate(connection.columns(table_name))
|
113
|
+
end
|
77
114
|
end
|
78
115
|
|
79
116
|
# Get the columns for a table as a hash, key is the column name
|
80
117
|
# value is the column object.
|
81
118
|
def columns_hash(table_name)
|
82
|
-
@columns_hash
|
83
|
-
[
|
84
|
-
|
119
|
+
@columns_hash.fetch(table_name) do
|
120
|
+
@columns_hash[deep_deduplicate(table_name)] = columns(table_name).index_by(&:name).freeze
|
121
|
+
end
|
85
122
|
end
|
86
123
|
|
87
124
|
# Checks whether the columns hash is already cached for a table.
|
@@ -90,7 +127,9 @@ module ActiveRecord
|
|
90
127
|
end
|
91
128
|
|
92
129
|
def indexes(table_name)
|
93
|
-
@indexes
|
130
|
+
@indexes.fetch(table_name) do
|
131
|
+
@indexes[deep_deduplicate(table_name)] = deep_deduplicate(connection.indexes(table_name))
|
132
|
+
end
|
94
133
|
end
|
95
134
|
|
96
135
|
def database_version # :nodoc:
|
@@ -121,21 +160,73 @@ module ActiveRecord
|
|
121
160
|
@indexes.delete name
|
122
161
|
end
|
123
162
|
|
163
|
+
def dump_to(filename)
|
164
|
+
clear!
|
165
|
+
connection.data_sources.each { |table| add(table) }
|
166
|
+
open(filename) { |f|
|
167
|
+
if filename.include?(".dump")
|
168
|
+
f.write(Marshal.dump(self))
|
169
|
+
else
|
170
|
+
f.write(YAML.dump(self))
|
171
|
+
end
|
172
|
+
}
|
173
|
+
end
|
174
|
+
|
124
175
|
def marshal_dump
|
125
|
-
|
126
|
-
|
127
|
-
[@version, @columns,
|
176
|
+
reset_version!
|
177
|
+
|
178
|
+
[@version, @columns, {}, @primary_keys, @data_sources, @indexes, database_version]
|
128
179
|
end
|
129
180
|
|
130
181
|
def marshal_load(array)
|
131
|
-
@version, @columns,
|
132
|
-
@indexes
|
182
|
+
@version, @columns, _columns_hash, @primary_keys, @data_sources, @indexes, @database_version = array
|
183
|
+
@indexes ||= {}
|
184
|
+
|
185
|
+
derive_columns_hash_and_deduplicate_values
|
133
186
|
end
|
134
187
|
|
135
188
|
private
|
189
|
+
def reset_version!
|
190
|
+
@version = connection.migration_context.current_version
|
191
|
+
end
|
192
|
+
|
193
|
+
def derive_columns_hash_and_deduplicate_values
|
194
|
+
@columns = deep_deduplicate(@columns)
|
195
|
+
@columns_hash = @columns.transform_values { |columns| columns.index_by(&:name) }
|
196
|
+
@primary_keys = deep_deduplicate(@primary_keys)
|
197
|
+
@data_sources = deep_deduplicate(@data_sources)
|
198
|
+
@indexes = deep_deduplicate(@indexes)
|
199
|
+
end
|
200
|
+
|
201
|
+
def deep_deduplicate(value)
|
202
|
+
case value
|
203
|
+
when Hash
|
204
|
+
value.transform_keys { |k| deep_deduplicate(k) }.transform_values { |v| deep_deduplicate(v) }
|
205
|
+
when Array
|
206
|
+
value.map { |i| deep_deduplicate(i) }
|
207
|
+
when String, Deduplicable
|
208
|
+
-value
|
209
|
+
else
|
210
|
+
value
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
136
214
|
def prepare_data_sources
|
137
215
|
connection.data_sources.each { |source| @data_sources[source] = true }
|
138
216
|
end
|
217
|
+
|
218
|
+
def open(filename)
|
219
|
+
File.atomic_write(filename) do |file|
|
220
|
+
if File.extname(filename) == ".gz"
|
221
|
+
zipper = Zlib::GzipWriter.new file
|
222
|
+
yield zipper
|
223
|
+
zipper.flush
|
224
|
+
zipper.close
|
225
|
+
else
|
226
|
+
yield file
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
139
230
|
end
|
140
231
|
end
|
141
232
|
end
|
@@ -4,6 +4,8 @@ module ActiveRecord
|
|
4
4
|
# :stopdoc:
|
5
5
|
module ConnectionAdapters
|
6
6
|
class SqlTypeMetadata
|
7
|
+
include Deduplicable
|
8
|
+
|
7
9
|
attr_reader :sql_type, :type, :limit, :precision, :scale
|
8
10
|
|
9
11
|
def initialize(sql_type: nil, type: nil, limit: nil, precision: nil, scale: nil)
|
@@ -32,6 +34,12 @@ module ActiveRecord
|
|
32
34
|
precision.hash >> 1 ^
|
33
35
|
scale.hash >> 2
|
34
36
|
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def deduplicated
|
40
|
+
@sql_type = -sql_type
|
41
|
+
super
|
42
|
+
end
|
35
43
|
end
|
36
44
|
end
|
37
45
|
end
|
@@ -4,19 +4,27 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
5
5
|
module SQLite3
|
6
6
|
module DatabaseStatements
|
7
|
-
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
7
|
+
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
8
|
+
:pragma
|
9
|
+
) # :nodoc:
|
8
10
|
private_constant :READ_QUERY
|
9
11
|
|
10
12
|
def write_query?(sql) # :nodoc:
|
11
13
|
!READ_QUERY.match?(sql)
|
12
14
|
end
|
13
15
|
|
16
|
+
def explain(arel, binds = [])
|
17
|
+
sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
|
18
|
+
SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", []))
|
19
|
+
end
|
20
|
+
|
14
21
|
def execute(sql, name = nil) #:nodoc:
|
15
22
|
if preventing_writes? && write_query?(sql)
|
16
23
|
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
17
24
|
end
|
18
25
|
|
19
26
|
materialize_transactions
|
27
|
+
mark_transaction_written_if_write(sql)
|
20
28
|
|
21
29
|
log(sql, name) do
|
22
30
|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
@@ -31,6 +39,7 @@ module ActiveRecord
|
|
31
39
|
end
|
32
40
|
|
33
41
|
materialize_transactions
|
42
|
+
mark_transaction_written_if_write(sql)
|
34
43
|
|
35
44
|
type_casted_binds = type_casted_binds(binds)
|
36
45
|
|
@@ -56,7 +65,7 @@ module ActiveRecord
|
|
56
65
|
records = stmt.to_a
|
57
66
|
end
|
58
67
|
|
59
|
-
|
68
|
+
build_result(columns: cols, rows: records)
|
60
69
|
end
|
61
70
|
end
|
62
71
|
end
|
@@ -67,26 +76,46 @@ module ActiveRecord
|
|
67
76
|
end
|
68
77
|
alias :exec_update :exec_delete
|
69
78
|
|
79
|
+
def begin_isolated_db_transaction(isolation) #:nodoc
|
80
|
+
raise TransactionIsolationError, "SQLite3 only supports the `read_uncommitted` transaction isolation level" if isolation != :read_uncommitted
|
81
|
+
raise StandardError, "You need to enable the shared-cache mode in SQLite mode before attempting to change the transaction isolation level" unless shared_cache?
|
82
|
+
|
83
|
+
Thread.current.thread_variable_set("read_uncommitted", @connection.get_first_value("PRAGMA read_uncommitted"))
|
84
|
+
@connection.read_uncommitted = true
|
85
|
+
begin_db_transaction
|
86
|
+
end
|
87
|
+
|
70
88
|
def begin_db_transaction #:nodoc:
|
71
|
-
log("begin transaction",
|
89
|
+
log("begin transaction", "TRANSACTION") { @connection.transaction }
|
72
90
|
end
|
73
91
|
|
74
92
|
def commit_db_transaction #:nodoc:
|
75
|
-
log("commit transaction",
|
93
|
+
log("commit transaction", "TRANSACTION") { @connection.commit }
|
94
|
+
reset_read_uncommitted
|
76
95
|
end
|
77
96
|
|
78
97
|
def exec_rollback_db_transaction #:nodoc:
|
79
|
-
log("rollback transaction",
|
98
|
+
log("rollback transaction", "TRANSACTION") { @connection.rollback }
|
99
|
+
reset_read_uncommitted
|
80
100
|
end
|
81
101
|
|
82
|
-
|
83
102
|
private
|
84
|
-
def
|
103
|
+
def reset_read_uncommitted
|
104
|
+
read_uncommitted = Thread.current.thread_variable_get("read_uncommitted")
|
105
|
+
return unless read_uncommitted
|
106
|
+
|
107
|
+
@connection.read_uncommitted = read_uncommitted
|
108
|
+
end
|
109
|
+
|
110
|
+
def execute_batch(statements, name = nil)
|
111
|
+
sql = combine_multi_statements(statements)
|
112
|
+
|
85
113
|
if preventing_writes? && write_query?(sql)
|
86
114
|
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
87
115
|
end
|
88
116
|
|
89
117
|
materialize_transactions
|
118
|
+
mark_transaction_written_if_write(sql)
|
90
119
|
|
91
120
|
log(sql, name) do
|
92
121
|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
@@ -106,11 +135,8 @@ module ActiveRecord
|
|
106
135
|
end.compact
|
107
136
|
end
|
108
137
|
|
109
|
-
def
|
110
|
-
|
111
|
-
"DELETE FROM #{quote_table_name(table_name)}"
|
112
|
-
end
|
113
|
-
combine_multi_statements(truncate_tables)
|
138
|
+
def build_truncate_statement(table_name)
|
139
|
+
"DELETE FROM #{quote_table_name(table_name)}"
|
114
140
|
end
|
115
141
|
end
|
116
142
|
end
|
@@ -60,7 +60,7 @@ module ActiveRecord
|
|
60
60
|
# "table_name"."column_name" | function(one or no argument)
|
61
61
|
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")) | \w+\((?:|\g<2>)\)
|
62
62
|
)
|
63
|
-
(?:\s+AS
|
63
|
+
(?:(?:\s+AS)?\s+(?:\w+|"\w+"))?
|
64
64
|
)
|
65
65
|
(?:\s*,\s*\g<1>)*
|
66
66
|
\z
|
@@ -82,7 +82,6 @@ module ActiveRecord
|
|
82
82
|
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
83
83
|
|
84
84
|
private
|
85
|
-
|
86
85
|
def _type_cast(value)
|
87
86
|
case value
|
88
87
|
when BigDecimal
|
@@ -3,8 +3,12 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
5
5
|
module SQLite3
|
6
|
-
class SchemaCreation <
|
6
|
+
class SchemaCreation < SchemaCreation # :nodoc:
|
7
7
|
private
|
8
|
+
def supports_index_using?
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
8
12
|
def add_column_options!(sql, options)
|
9
13
|
if options[:collation]
|
10
14
|
sql << " COLLATE \"#{options[:collation]}\""
|
@@ -9,7 +9,7 @@ module ActiveRecord
|
|
9
9
|
exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", "SCHEMA").map do |row|
|
10
10
|
# Indexes SQLite creates implicitly for internal use start with "sqlite_".
|
11
11
|
# See https://www.sqlite.org/fileformat2.html#intschema
|
12
|
-
next if row["name"].
|
12
|
+
next if row["name"].start_with?("sqlite_")
|
13
13
|
|
14
14
|
index_sql = query_value(<<~SQL, "SCHEMA")
|
15
15
|
SELECT sql
|
@@ -55,13 +55,13 @@ module ActiveRecord
|
|
55
55
|
def add_foreign_key(from_table, to_table, **options)
|
56
56
|
alter_table(from_table) do |definition|
|
57
57
|
to_table = strip_table_name_prefix_and_suffix(to_table)
|
58
|
-
definition.foreign_key(to_table, options)
|
58
|
+
definition.foreign_key(to_table, **options)
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
62
|
def remove_foreign_key(from_table, to_table = nil, **options)
|
63
63
|
to_table ||= options[:to_table]
|
64
|
-
options = options.except(:name, :to_table)
|
64
|
+
options = options.except(:name, :to_table, :validate)
|
65
65
|
foreign_keys = foreign_keys(from_table)
|
66
66
|
|
67
67
|
fkey = foreign_keys.detect do |fk|
|
@@ -78,6 +78,35 @@ module ActiveRecord
|
|
78
78
|
alter_table(from_table, foreign_keys)
|
79
79
|
end
|
80
80
|
|
81
|
+
def check_constraints(table_name)
|
82
|
+
table_sql = query_value(<<-SQL, "SCHEMA")
|
83
|
+
SELECT sql
|
84
|
+
FROM sqlite_master
|
85
|
+
WHERE name = #{quote_table_name(table_name)} AND type = 'table'
|
86
|
+
UNION ALL
|
87
|
+
SELECT sql
|
88
|
+
FROM sqlite_temp_master
|
89
|
+
WHERE name = #{quote_table_name(table_name)} AND type = 'table'
|
90
|
+
SQL
|
91
|
+
|
92
|
+
table_sql.to_s.scan(/CONSTRAINT\s+(?<name>\w+)\s+CHECK\s+\((?<expression>(:?[^()]|\(\g<expression>\))+)\)/i).map do |name, expression|
|
93
|
+
CheckConstraintDefinition.new(table_name, expression, name: name)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def add_check_constraint(table_name, expression, **options)
|
98
|
+
alter_table(table_name) do |definition|
|
99
|
+
definition.check_constraint(expression, **options)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def remove_check_constraint(table_name, expression = nil, **options)
|
104
|
+
check_constraints = check_constraints(table_name)
|
105
|
+
chk_name_to_delete = check_constraint_for!(table_name, expression: expression, **options).name
|
106
|
+
check_constraints.delete_if { |chk| chk.name == chk_name_to_delete }
|
107
|
+
alter_table(table_name, foreign_keys(table_name), check_constraints)
|
108
|
+
end
|
109
|
+
|
81
110
|
def create_schema_dumper(options)
|
82
111
|
SQLite3::SchemaDumper.create(self, options)
|
83
112
|
end
|
@@ -87,8 +116,12 @@ module ActiveRecord
|
|
87
116
|
SQLite3::SchemaCreation.new(self)
|
88
117
|
end
|
89
118
|
|
90
|
-
def create_table_definition(
|
91
|
-
SQLite3::TableDefinition.new(self,
|
119
|
+
def create_table_definition(name, **options)
|
120
|
+
SQLite3::TableDefinition.new(self, name, **options)
|
121
|
+
end
|
122
|
+
|
123
|
+
def validate_index_length!(table_name, new_name, internal = false)
|
124
|
+
super unless internal
|
92
125
|
end
|
93
126
|
|
94
127
|
def new_column_from_field(table_name, field)
|