activerecord 7.0.8 → 7.1.3.4
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 +1554 -1452
- data/MIT-LICENSE +1 -1
- data/README.rdoc +16 -16
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/association.rb +20 -4
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +14 -6
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +21 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +15 -9
- data/lib/active_record/associations/collection_proxy.rb +15 -10
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +20 -13
- data/lib/active_record/associations/has_many_through_association.rb +10 -6
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency.rb +10 -8
- data/lib/active_record/associations/preloader/association.rb +31 -7
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +313 -217
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/dirty.rb +52 -34
- data/lib/active_record/attribute_methods/primary_key.rb +76 -24
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +18 -5
- data/lib/active_record/attribute_methods/serialization.rb +150 -31
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +105 -21
- data/lib/active_record/attributes.rb +3 -3
- data/lib/active_record/autosave_association.rb +55 -9
- data/lib/active_record/base.rb +7 -2
- data/lib/active_record/callbacks.rb +10 -24
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +163 -88
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +74 -51
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +129 -31
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +62 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +41 -6
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +289 -124
- data/lib/active_record/connection_adapters/abstract/transaction.rb +287 -58
- data/lib/active_record/connection_adapters/abstract_adapter.rb +511 -91
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +207 -108
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +22 -143
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +18 -13
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
- data/lib/active_record/connection_adapters/pool_config.rb +14 -5
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +14 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +74 -40
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +10 -6
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +361 -60
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +353 -192
- data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +52 -39
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +4 -3
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +26 -7
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +209 -79
- 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 +262 -0
- data/lib/active_record/connection_adapters.rb +3 -1
- data/lib/active_record/connection_handling.rb +72 -95
- data/lib/active_record/core.rb +175 -153
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/database_config.rb +9 -3
- data/lib/active_record/database_configurations/hash_config.rb +22 -12
- data/lib/active_record/database_configurations/url_config.rb +17 -11
- data/lib/active_record/database_configurations.rb +86 -33
- data/lib/active_record/delegated_type.rb +9 -4
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +2 -0
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +42 -18
- data/lib/active_record/encryption/encrypted_attribute_type.rb +21 -6
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -69
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/message_serializer.rb +2 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/scheme.rb +19 -22
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +112 -28
- data/lib/active_record/errors.rb +112 -18
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +29 -8
- data/lib/active_record/fixtures.rb +135 -71
- data/lib/active_record/future_result.rb +31 -5
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +30 -16
- data/lib/active_record/insert_all.rb +57 -10
- data/lib/active_record/integration.rb +8 -8
- data/lib/active_record/internal_metadata.rb +120 -30
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +29 -12
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +6 -8
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +104 -5
- data/lib/active_record/migration/compatibility.rb +139 -5
- 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/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +219 -111
- data/lib/active_record/model_schema.rb +64 -44
- data/lib/active_record/nested_attributes.rb +24 -6
- data/lib/active_record/normalization.rb +167 -0
- data/lib/active_record/persistence.rb +188 -37
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +77 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +15 -2
- data/lib/active_record/railtie.rb +109 -47
- data/lib/active_record/railties/controller_runtime.rb +12 -6
- data/lib/active_record/railties/databases.rake +142 -148
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +174 -44
- data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
- data/lib/active_record/relation/batches.rb +190 -61
- data/lib/active_record/relation/calculations.rb +187 -63
- data/lib/active_record/relation/delegation.rb +23 -9
- data/lib/active_record/relation/finder_methods.rb +77 -16
- data/lib/active_record/relation/merger.rb +2 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +26 -14
- data/lib/active_record/relation/query_attribute.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +352 -63
- data/lib/active_record/relation/spawn_methods.rb +18 -1
- data/lib/active_record/relation.rb +91 -35
- data/lib/active_record/result.rb +19 -5
- data/lib/active_record/runtime_registry.rb +24 -1
- data/lib/active_record/sanitization.rb +51 -11
- data/lib/active_record/schema.rb +2 -3
- data/lib/active_record/schema_dumper.rb +46 -7
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +2 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +7 -5
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +10 -1
- data/lib/active_record/tasks/database_tasks.rb +127 -105
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_fixtures.rb +113 -96
- data/lib/active_record/timestamp.rb +27 -15
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +36 -10
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/validations/absence.rb +1 -1
- 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 +47 -2
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +121 -16
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.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/cte.rb +36 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +4 -0
- data/lib/arel/predications.rb +2 -0
- data/lib/arel/table.rb +9 -5
- data/lib/arel/visitors/mysql.rb +8 -1
- data/lib/arel/visitors/to_sql.rb +81 -17
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +16 -2
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- metadata +48 -12
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
@@ -15,14 +15,14 @@ module ActiveRecord
|
|
15
15
|
|
16
16
|
# Escapes binary strings for bytea input to the database.
|
17
17
|
def escape_bytea(value)
|
18
|
-
|
18
|
+
valid_raw_connection.escape_bytea(value) if value
|
19
19
|
end
|
20
20
|
|
21
21
|
# Unescapes bytea output from a database to the binary string it represents.
|
22
22
|
# NOTE: This is NOT an inverse of escape_bytea! This is only to be used
|
23
23
|
# on escaped binary output from database drive.
|
24
24
|
def unescape_bytea(value)
|
25
|
-
|
25
|
+
valid_raw_connection.unescape_bytea(value) if value
|
26
26
|
end
|
27
27
|
|
28
28
|
def check_int_in_range(value)
|
@@ -72,7 +72,9 @@ module ActiveRecord
|
|
72
72
|
|
73
73
|
# Quotes strings for use in SQL input.
|
74
74
|
def quote_string(s) # :nodoc:
|
75
|
-
|
75
|
+
with_raw_connection(allow_retry: true, materialize_transactions: false) do |connection|
|
76
|
+
connection.escape(s)
|
77
|
+
end
|
76
78
|
end
|
77
79
|
|
78
80
|
# Checks the following cases:
|
@@ -118,7 +120,7 @@ module ActiveRecord
|
|
118
120
|
def quote_default_expression(value, column) # :nodoc:
|
119
121
|
if value.is_a?(Proc)
|
120
122
|
value.call
|
121
|
-
elsif column.type == :uuid && value.is_a?(String) &&
|
123
|
+
elsif column.type == :uuid && value.is_a?(String) && value.include?("()")
|
122
124
|
value # Does not quote function default values for UUID columns
|
123
125
|
elsif column.respond_to?(:array?)
|
124
126
|
type = lookup_cast_type_from_column(column)
|
@@ -147,6 +149,7 @@ module ActiveRecord
|
|
147
149
|
end
|
148
150
|
|
149
151
|
def lookup_cast_type_from_column(column) # :nodoc:
|
152
|
+
verify! if type_map.nil?
|
150
153
|
type_map.lookup(column.oid, column.fmod, column.sql_type)
|
151
154
|
end
|
152
155
|
|
@@ -163,7 +166,7 @@ module ActiveRecord
|
|
163
166
|
(
|
164
167
|
(?:
|
165
168
|
# "schema_name"."table_name"."column_name"::type_name | function(one or no argument)::type_name
|
166
|
-
((?:\w+\.|"\w+"\.){,2}(?:\w+|"\w+")(?:::\w+)?
|
169
|
+
((?:\w+\.|"\w+"\.){,2}(?:\w+|"\w+")(?:::\w+)? | \w+\((?:|\g<2>)\)(?:::\w+)?)
|
167
170
|
)
|
168
171
|
(?:(?:\s+AS)?\s+(?:\w+|"\w+"))?
|
169
172
|
)
|
@@ -176,8 +179,9 @@ module ActiveRecord
|
|
176
179
|
(
|
177
180
|
(?:
|
178
181
|
# "schema_name"."table_name"."column_name"::type_name | function(one or no argument)::type_name
|
179
|
-
((?:\w+\.|"\w+"\.){,2}(?:\w+|"\w+")(?:::\w+)?
|
182
|
+
((?:\w+\.|"\w+"\.){,2}(?:\w+|"\w+")(?:::\w+)? | \w+\((?:|\g<2>)\)(?:::\w+)?)
|
180
183
|
)
|
184
|
+
(?:\s+COLLATE\s+"\w+")?
|
181
185
|
(?:\s+ASC|\s+DESC)?
|
182
186
|
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
183
187
|
)
|
@@ -38,7 +38,7 @@ Rails needs superuser privileges to disable referential integrity.
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
def
|
41
|
+
def check_all_foreign_keys_valid! # :nodoc:
|
42
42
|
sql = <<~SQL
|
43
43
|
do $$
|
44
44
|
declare r record;
|
@@ -61,14 +61,8 @@ Rails needs superuser privileges to disable referential integrity.
|
|
61
61
|
$$;
|
62
62
|
SQL
|
63
63
|
|
64
|
-
|
65
|
-
|
66
|
-
execute(sql)
|
67
|
-
end
|
68
|
-
|
69
|
-
true
|
70
|
-
rescue ActiveRecord::StatementInvalid
|
71
|
-
false
|
64
|
+
transaction(requires_new: true) do
|
65
|
+
execute(sql)
|
72
66
|
end
|
73
67
|
end
|
74
68
|
end
|
@@ -5,21 +5,30 @@ module ActiveRecord
|
|
5
5
|
module PostgreSQL
|
6
6
|
class SchemaCreation < SchemaCreation # :nodoc:
|
7
7
|
private
|
8
|
+
delegate :quoted_include_columns_for_index, to: :@conn
|
9
|
+
|
8
10
|
def visit_AlterTable(o)
|
9
|
-
|
11
|
+
sql = super
|
12
|
+
sql << o.constraint_validations.map { |fk| visit_ValidateConstraint fk }.join(" ")
|
13
|
+
sql << o.exclusion_constraint_adds.map { |con| visit_AddExclusionConstraint con }.join(" ")
|
14
|
+
sql << o.exclusion_constraint_drops.map { |con| visit_DropExclusionConstraint con }.join(" ")
|
15
|
+
sql << o.unique_constraint_adds.map { |con| visit_AddUniqueConstraint con }.join(" ")
|
16
|
+
sql << o.unique_constraint_drops.map { |con| visit_DropUniqueConstraint con }.join(" ")
|
10
17
|
end
|
11
18
|
|
12
19
|
def visit_AddForeignKey(o)
|
13
20
|
super.dup.tap do |sql|
|
14
|
-
if o.deferrable
|
15
|
-
sql << " DEFERRABLE"
|
16
|
-
sql << " INITIALLY #{o.deferrable.to_s.upcase}" unless o.deferrable == true
|
17
|
-
end
|
18
|
-
|
21
|
+
sql << " DEFERRABLE INITIALLY #{o.options[:deferrable].to_s.upcase}" if o.deferrable
|
19
22
|
sql << " NOT VALID" unless o.validate?
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
26
|
+
def visit_ForeignKeyDefinition(o)
|
27
|
+
super.dup.tap do |sql|
|
28
|
+
sql << " DEFERRABLE INITIALLY #{o.deferrable.to_s.upcase}" if o.deferrable
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
23
32
|
def visit_CheckConstraintDefinition(o)
|
24
33
|
super.dup.tap { |sql| sql << " NOT VALID" unless o.validate? }
|
25
34
|
end
|
@@ -28,6 +37,54 @@ module ActiveRecord
|
|
28
37
|
"VALIDATE CONSTRAINT #{quote_column_name(name)}"
|
29
38
|
end
|
30
39
|
|
40
|
+
def visit_ExclusionConstraintDefinition(o)
|
41
|
+
sql = ["CONSTRAINT"]
|
42
|
+
sql << quote_column_name(o.name)
|
43
|
+
sql << "EXCLUDE"
|
44
|
+
sql << "USING #{o.using}" if o.using
|
45
|
+
sql << "(#{o.expression})"
|
46
|
+
sql << "WHERE (#{o.where})" if o.where
|
47
|
+
sql << "DEFERRABLE INITIALLY #{o.deferrable.to_s.upcase}" if o.deferrable
|
48
|
+
|
49
|
+
sql.join(" ")
|
50
|
+
end
|
51
|
+
|
52
|
+
def visit_UniqueConstraintDefinition(o)
|
53
|
+
column_name = Array(o.column).map { |column| quote_column_name(column) }.join(", ")
|
54
|
+
|
55
|
+
sql = ["CONSTRAINT"]
|
56
|
+
sql << quote_column_name(o.name)
|
57
|
+
sql << "UNIQUE"
|
58
|
+
|
59
|
+
if o.using_index
|
60
|
+
sql << "USING INDEX #{quote_column_name(o.using_index)}"
|
61
|
+
else
|
62
|
+
sql << "(#{column_name})"
|
63
|
+
end
|
64
|
+
|
65
|
+
if o.deferrable
|
66
|
+
sql << "DEFERRABLE INITIALLY #{o.deferrable.to_s.upcase}"
|
67
|
+
end
|
68
|
+
|
69
|
+
sql.join(" ")
|
70
|
+
end
|
71
|
+
|
72
|
+
def visit_AddExclusionConstraint(o)
|
73
|
+
"ADD #{accept(o)}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def visit_DropExclusionConstraint(name)
|
77
|
+
"DROP CONSTRAINT #{quote_column_name(name)}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def visit_AddUniqueConstraint(o)
|
81
|
+
"ADD #{accept(o)}"
|
82
|
+
end
|
83
|
+
|
84
|
+
def visit_DropUniqueConstraint(name)
|
85
|
+
"DROP CONSTRAINT #{quote_column_name(name)}"
|
86
|
+
end
|
87
|
+
|
31
88
|
def visit_ChangeColumnDefinition(o)
|
32
89
|
column = o.column
|
33
90
|
column.sql_type = type_to_sql(column.type, **column.options)
|
@@ -64,6 +121,15 @@ module ActiveRecord
|
|
64
121
|
change_column_sql
|
65
122
|
end
|
66
123
|
|
124
|
+
def visit_ChangeColumnDefaultDefinition(o)
|
125
|
+
sql = +"ALTER COLUMN #{quote_column_name(o.column.name)} "
|
126
|
+
if o.default.nil?
|
127
|
+
sql << "DROP DEFAULT"
|
128
|
+
else
|
129
|
+
sql << "SET DEFAULT #{quote_default_expression(o.default, o.column)}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
67
133
|
def add_column_options!(sql, options)
|
68
134
|
if options[:collation]
|
69
135
|
sql << " COLLATE \"#{options[:collation]}\""
|
@@ -84,6 +150,10 @@ module ActiveRecord
|
|
84
150
|
super
|
85
151
|
end
|
86
152
|
|
153
|
+
def quoted_include_columns(o)
|
154
|
+
String === o ? o : quoted_include_columns_for_index(o)
|
155
|
+
end
|
156
|
+
|
87
157
|
# Returns any SQL string to go between CREATE and TABLE. May be nil.
|
88
158
|
def table_modifier_in_create(o)
|
89
159
|
# A table cannot be both TEMPORARY and UNLOGGED, since all TEMPORARY
|
@@ -189,16 +189,83 @@ module ActiveRecord
|
|
189
189
|
end
|
190
190
|
end
|
191
191
|
|
192
|
+
ExclusionConstraintDefinition = Struct.new(:table_name, :expression, :options) do
|
193
|
+
def name
|
194
|
+
options[:name]
|
195
|
+
end
|
196
|
+
|
197
|
+
def using
|
198
|
+
options[:using]
|
199
|
+
end
|
200
|
+
|
201
|
+
def where
|
202
|
+
options[:where]
|
203
|
+
end
|
204
|
+
|
205
|
+
def deferrable
|
206
|
+
options[:deferrable]
|
207
|
+
end
|
208
|
+
|
209
|
+
def export_name_on_schema_dump?
|
210
|
+
!ActiveRecord::SchemaDumper.excl_ignore_pattern.match?(name) if name
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
UniqueConstraintDefinition = Struct.new(:table_name, :column, :options) do
|
215
|
+
def name
|
216
|
+
options[:name]
|
217
|
+
end
|
218
|
+
|
219
|
+
def deferrable
|
220
|
+
options[:deferrable]
|
221
|
+
end
|
222
|
+
|
223
|
+
def using_index
|
224
|
+
options[:using_index]
|
225
|
+
end
|
226
|
+
|
227
|
+
def export_name_on_schema_dump?
|
228
|
+
!ActiveRecord::SchemaDumper.unique_ignore_pattern.match?(name) if name
|
229
|
+
end
|
230
|
+
|
231
|
+
def defined_for?(name: nil, column: nil, **options)
|
232
|
+
(name.nil? || self.name == name.to_s) &&
|
233
|
+
(column.nil? || Array(self.column) == Array(column).map(&:to_s)) &&
|
234
|
+
options.all? { |k, v| self.options[k].to_s == v.to_s }
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# = Active Record PostgreSQL Adapter \Table Definition
|
192
239
|
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
193
240
|
include ColumnMethods
|
194
241
|
|
195
|
-
attr_reader :unlogged
|
242
|
+
attr_reader :exclusion_constraints, :unique_constraints, :unlogged
|
196
243
|
|
197
244
|
def initialize(*, **)
|
198
245
|
super
|
246
|
+
@exclusion_constraints = []
|
247
|
+
@unique_constraints = []
|
199
248
|
@unlogged = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.create_unlogged_tables
|
200
249
|
end
|
201
250
|
|
251
|
+
def exclusion_constraint(expression, **options)
|
252
|
+
exclusion_constraints << new_exclusion_constraint_definition(expression, options)
|
253
|
+
end
|
254
|
+
|
255
|
+
def unique_constraint(column_name, **options)
|
256
|
+
unique_constraints << new_unique_constraint_definition(column_name, options)
|
257
|
+
end
|
258
|
+
|
259
|
+
def new_exclusion_constraint_definition(expression, options) # :nodoc:
|
260
|
+
options = @conn.exclusion_constraint_options(name, expression, options)
|
261
|
+
ExclusionConstraintDefinition.new(name, expression, options)
|
262
|
+
end
|
263
|
+
|
264
|
+
def new_unique_constraint_definition(column_name, options) # :nodoc:
|
265
|
+
options = @conn.unique_constraint_options(name, column_name, options)
|
266
|
+
UniqueConstraintDefinition.new(name, column_name, options)
|
267
|
+
end
|
268
|
+
|
202
269
|
def new_column_definition(name, type, **options) # :nodoc:
|
203
270
|
case type
|
204
271
|
when :virtual
|
@@ -209,6 +276,10 @@ module ActiveRecord
|
|
209
276
|
end
|
210
277
|
|
211
278
|
private
|
279
|
+
def valid_column_definition_options
|
280
|
+
super + [:array, :using, :cast_as, :as, :type, :enum_type, :stored]
|
281
|
+
end
|
282
|
+
|
212
283
|
def aliased_types(name, fallback)
|
213
284
|
fallback
|
214
285
|
end
|
@@ -222,21 +293,79 @@ module ActiveRecord
|
|
222
293
|
end
|
223
294
|
end
|
224
295
|
|
296
|
+
# = Active Record PostgreSQL Adapter \Table
|
225
297
|
class Table < ActiveRecord::ConnectionAdapters::Table
|
226
298
|
include ColumnMethods
|
299
|
+
|
300
|
+
# Adds an exclusion constraint.
|
301
|
+
#
|
302
|
+
# t.exclusion_constraint("price WITH =, availability_range WITH &&", using: :gist, name: "price_check")
|
303
|
+
#
|
304
|
+
# See {connection.add_exclusion_constraint}[rdoc-ref:SchemaStatements#add_exclusion_constraint]
|
305
|
+
def exclusion_constraint(*args)
|
306
|
+
@base.add_exclusion_constraint(name, *args)
|
307
|
+
end
|
308
|
+
|
309
|
+
# Removes the given exclusion constraint from the table.
|
310
|
+
#
|
311
|
+
# t.remove_exclusion_constraint(name: "price_check")
|
312
|
+
#
|
313
|
+
# See {connection.remove_exclusion_constraint}[rdoc-ref:SchemaStatements#remove_exclusion_constraint]
|
314
|
+
def remove_exclusion_constraint(*args)
|
315
|
+
@base.remove_exclusion_constraint(name, *args)
|
316
|
+
end
|
317
|
+
|
318
|
+
# Adds a unique constraint.
|
319
|
+
#
|
320
|
+
# t.unique_constraint(:position, name: 'unique_position', deferrable: :deferred)
|
321
|
+
#
|
322
|
+
# See {connection.add_unique_constraint}[rdoc-ref:SchemaStatements#add_unique_constraint]
|
323
|
+
def unique_constraint(*args)
|
324
|
+
@base.add_unique_constraint(name, *args)
|
325
|
+
end
|
326
|
+
|
327
|
+
# Removes the given unique constraint from the table.
|
328
|
+
#
|
329
|
+
# t.remove_unique_constraint(name: "unique_position")
|
330
|
+
#
|
331
|
+
# See {connection.remove_unique_constraint}[rdoc-ref:SchemaStatements#remove_unique_constraint]
|
332
|
+
def remove_unique_constraint(*args)
|
333
|
+
@base.remove_unique_constraint(name, *args)
|
334
|
+
end
|
227
335
|
end
|
228
336
|
|
337
|
+
# = Active Record PostgreSQL Adapter Alter \Table
|
229
338
|
class AlterTable < ActiveRecord::ConnectionAdapters::AlterTable
|
230
|
-
attr_reader :constraint_validations
|
339
|
+
attr_reader :constraint_validations, :exclusion_constraint_adds, :exclusion_constraint_drops, :unique_constraint_adds, :unique_constraint_drops
|
231
340
|
|
232
341
|
def initialize(td)
|
233
342
|
super
|
234
343
|
@constraint_validations = []
|
344
|
+
@exclusion_constraint_adds = []
|
345
|
+
@exclusion_constraint_drops = []
|
346
|
+
@unique_constraint_adds = []
|
347
|
+
@unique_constraint_drops = []
|
235
348
|
end
|
236
349
|
|
237
350
|
def validate_constraint(name)
|
238
351
|
@constraint_validations << name
|
239
352
|
end
|
353
|
+
|
354
|
+
def add_exclusion_constraint(expression, options)
|
355
|
+
@exclusion_constraint_adds << @td.new_exclusion_constraint_definition(expression, options)
|
356
|
+
end
|
357
|
+
|
358
|
+
def drop_exclusion_constraint(constraint_name)
|
359
|
+
@exclusion_constraint_drops << constraint_name
|
360
|
+
end
|
361
|
+
|
362
|
+
def add_unique_constraint(column_name, options)
|
363
|
+
@unique_constraint_adds << @td.new_unique_constraint_definition(column_name, options)
|
364
|
+
end
|
365
|
+
|
366
|
+
def drop_unique_constraint(unique_constraint_name)
|
367
|
+
@unique_constraint_drops << unique_constraint_name
|
368
|
+
end
|
240
369
|
end
|
241
370
|
end
|
242
371
|
end
|
@@ -28,6 +28,59 @@ module ActiveRecord
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
def schemas(stream)
|
32
|
+
schema_names = @connection.schema_names - ["public"]
|
33
|
+
|
34
|
+
if schema_names.any?
|
35
|
+
schema_names.sort.each do |name|
|
36
|
+
stream.puts " create_schema #{name.inspect}"
|
37
|
+
end
|
38
|
+
stream.puts
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def exclusion_constraints_in_create(table, stream)
|
43
|
+
if (exclusion_constraints = @connection.exclusion_constraints(table)).any?
|
44
|
+
add_exclusion_constraint_statements = exclusion_constraints.map do |exclusion_constraint|
|
45
|
+
parts = [
|
46
|
+
"t.exclusion_constraint #{exclusion_constraint.expression.inspect}"
|
47
|
+
]
|
48
|
+
|
49
|
+
parts << "where: #{exclusion_constraint.where.inspect}" if exclusion_constraint.where
|
50
|
+
parts << "using: #{exclusion_constraint.using.inspect}" if exclusion_constraint.using
|
51
|
+
parts << "deferrable: #{exclusion_constraint.deferrable.inspect}" if exclusion_constraint.deferrable
|
52
|
+
|
53
|
+
if exclusion_constraint.export_name_on_schema_dump?
|
54
|
+
parts << "name: #{exclusion_constraint.name.inspect}"
|
55
|
+
end
|
56
|
+
|
57
|
+
" #{parts.join(', ')}"
|
58
|
+
end
|
59
|
+
|
60
|
+
stream.puts add_exclusion_constraint_statements.sort.join("\n")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def unique_constraints_in_create(table, stream)
|
65
|
+
if (unique_constraints = @connection.unique_constraints(table)).any?
|
66
|
+
add_unique_constraint_statements = unique_constraints.map do |unique_constraint|
|
67
|
+
parts = [
|
68
|
+
"t.unique_constraint #{unique_constraint.column.inspect}"
|
69
|
+
]
|
70
|
+
|
71
|
+
parts << "deferrable: #{unique_constraint.deferrable.inspect}" if unique_constraint.deferrable
|
72
|
+
|
73
|
+
if unique_constraint.export_name_on_schema_dump?
|
74
|
+
parts << "name: #{unique_constraint.name.inspect}"
|
75
|
+
end
|
76
|
+
|
77
|
+
" #{parts.join(', ')}"
|
78
|
+
end
|
79
|
+
|
80
|
+
stream.puts add_unique_constraint_statements.sort.join("\n")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
31
84
|
def prepare_column_options(column)
|
32
85
|
spec = super
|
33
86
|
spec[:array] = "true" if column.array?
|