activerecord 7.1.3.4 → 7.2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +652 -2032
- data/README.rdoc +15 -15
- data/examples/performance.rb +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +15 -8
- data/lib/active_record/associations/belongs_to_association.rb +18 -11
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/belongs_to.rb +1 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/collection_association.rb +11 -5
- data/lib/active_record/associations/collection_proxy.rb +14 -1
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/has_many_association.rb +3 -3
- data/lib/active_record/associations/has_many_through_association.rb +7 -1
- data/lib/active_record/associations/has_one_association.rb +2 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
- data/lib/active_record/associations/join_dependency.rb +10 -12
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +2 -1
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +62 -289
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +2 -2
- data/lib/active_record/attribute_methods/primary_key.rb +23 -55
- data/lib/active_record/attribute_methods/read.rb +4 -16
- data/lib/active_record/attribute_methods/serialization.rb +4 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -6
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +89 -58
- data/lib/active_record/attributes.rb +61 -47
- data/lib/active_record/autosave_association.rb +17 -31
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +24 -107
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +270 -58
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +35 -18
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +190 -75
- data/lib/active_record/connection_adapters/abstract/quoting.rb +65 -91
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +23 -10
- data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -62
- data/lib/active_record/connection_adapters/abstract_adapter.rb +38 -59
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +73 -19
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +43 -48
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +8 -1
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +16 -15
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +20 -32
- data/lib/active_record/connection_adapters/pool_config.rb +7 -6
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +27 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +58 -58
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +18 -12
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +29 -24
- data/lib/active_record/connection_adapters/schema_cache.rb +123 -128
- data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +10 -6
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +44 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +25 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +127 -77
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +15 -15
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +32 -65
- data/lib/active_record/connection_adapters.rb +121 -0
- data/lib/active_record/connection_handling.rb +56 -41
- data/lib/active_record/core.rb +93 -40
- data/lib/active_record/counter_cache.rb +23 -10
- data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -3
- data/lib/active_record/database_configurations/database_config.rb +19 -4
- data/lib/active_record/database_configurations/hash_config.rb +44 -36
- data/lib/active_record/database_configurations/url_config.rb +20 -1
- data/lib/active_record/database_configurations.rb +1 -1
- data/lib/active_record/delegated_type.rb +30 -6
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/encryptable_record.rb +3 -3
- data/lib/active_record/encryption/encrypted_attribute_type.rb +26 -6
- data/lib/active_record/encryption/encryptor.rb +18 -3
- data/lib/active_record/encryption/key_provider.rb +1 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +4 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +8 -4
- data/lib/active_record/encryption.rb +2 -0
- data/lib/active_record/enum.rb +19 -2
- data/lib/active_record/errors.rb +46 -20
- data/lib/active_record/explain.rb +13 -24
- data/lib/active_record/fixtures.rb +37 -31
- data/lib/active_record/future_result.rb +17 -4
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +4 -2
- data/lib/active_record/insert_all.rb +18 -15
- data/lib/active_record/integration.rb +4 -1
- data/lib/active_record/internal_metadata.rb +48 -34
- data/lib/active_record/locking/optimistic.rb +8 -7
- data/lib/active_record/log_subscriber.rb +0 -21
- data/lib/active_record/marshalling.rb +4 -1
- data/lib/active_record/message_pack.rb +2 -2
- data/lib/active_record/migration/command_recorder.rb +2 -3
- data/lib/active_record/migration/compatibility.rb +11 -3
- data/lib/active_record/migration/default_strategy.rb +4 -5
- data/lib/active_record/migration/pending_migration_connection.rb +2 -2
- data/lib/active_record/migration.rb +85 -76
- data/lib/active_record/model_schema.rb +38 -70
- data/lib/active_record/nested_attributes.rb +24 -5
- data/lib/active_record/normalization.rb +3 -7
- data/lib/active_record/persistence.rb +32 -354
- data/lib/active_record/query_cache.rb +19 -8
- data/lib/active_record/query_logs.rb +15 -0
- data/lib/active_record/query_logs_formatter.rb +1 -1
- data/lib/active_record/querying.rb +21 -9
- data/lib/active_record/railtie.rb +50 -68
- data/lib/active_record/railties/controller_runtime.rb +13 -4
- data/lib/active_record/railties/databases.rake +42 -45
- data/lib/active_record/reflection.rb +106 -38
- data/lib/active_record/relation/batches/batch_enumerator.rb +15 -2
- data/lib/active_record/relation/batches.rb +14 -8
- data/lib/active_record/relation/calculations.rb +96 -63
- data/lib/active_record/relation/delegation.rb +8 -11
- data/lib/active_record/relation/finder_methods.rb +16 -2
- data/lib/active_record/relation/merger.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +6 -1
- data/lib/active_record/relation/predicate_builder.rb +3 -3
- data/lib/active_record/relation/query_methods.rb +245 -65
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -18
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +500 -66
- data/lib/active_record/result.rb +32 -45
- data/lib/active_record/runtime_registry.rb +39 -0
- data/lib/active_record/sanitization.rb +24 -19
- data/lib/active_record/schema.rb +8 -6
- data/lib/active_record/schema_dumper.rb +19 -9
- data/lib/active_record/schema_migration.rb +30 -14
- data/lib/active_record/scoping/named.rb +1 -0
- data/lib/active_record/signed_id.rb +20 -1
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/table_metadata.rb +1 -10
- data/lib/active_record/tasks/database_tasks.rb +98 -48
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -1
- data/lib/active_record/test_fixtures.rb +87 -89
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +5 -3
- data/lib/active_record/token_for.rb +22 -12
- data/lib/active_record/touch_later.rb +1 -1
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +70 -14
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/associated.rb +9 -3
- data/lib/active_record/validations/uniqueness.rb +15 -10
- data/lib/active_record/validations.rb +4 -1
- data/lib/active_record.rb +150 -41
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/nodes/binary.rb +0 -6
- data/lib/arel/nodes/bound_sql_literal.rb +9 -5
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +4 -3
- data/lib/arel/nodes/sql_literal.rb +7 -0
- data/lib/arel/nodes.rb +2 -2
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/tree_manager.rb +8 -3
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +9 -4
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/sqlite.rb +25 -0
- data/lib/arel/visitors/to_sql.rb +31 -17
- data/lib/arel.rb +7 -3
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- metadata +21 -15
@@ -6,6 +6,7 @@ module ActiveRecord
|
|
6
6
|
module OID # :nodoc:
|
7
7
|
class Uuid < Type::Value # :nodoc:
|
8
8
|
ACCEPTABLE_UUID = %r{\A(\{)?([a-fA-F0-9]{4}-?){8}(?(1)\}|)\z}
|
9
|
+
CANONICAL_UUID = %r{\A[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}\z}
|
9
10
|
|
10
11
|
alias :serialize :deserialize
|
11
12
|
|
@@ -15,18 +16,27 @@ module ActiveRecord
|
|
15
16
|
|
16
17
|
def changed?(old_value, new_value, _new_value_before_type_cast)
|
17
18
|
old_value.class != new_value.class ||
|
18
|
-
new_value
|
19
|
+
new_value != old_value
|
19
20
|
end
|
20
21
|
|
21
22
|
def changed_in_place?(raw_old_value, new_value)
|
22
23
|
raw_old_value.class != new_value.class ||
|
23
|
-
new_value
|
24
|
+
new_value != raw_old_value
|
24
25
|
end
|
25
26
|
|
26
27
|
private
|
27
28
|
def cast_value(value)
|
28
|
-
|
29
|
-
|
29
|
+
value = value.to_s
|
30
|
+
format_uuid(value) if value.match?(ACCEPTABLE_UUID)
|
31
|
+
end
|
32
|
+
|
33
|
+
def format_uuid(uuid)
|
34
|
+
if uuid.match?(CANONICAL_UUID)
|
35
|
+
uuid
|
36
|
+
else
|
37
|
+
uuid = uuid.delete("{}-").downcase
|
38
|
+
"#{uuid[..7]}-#{uuid[8..11]}-#{uuid[12..15]}-#{uuid[16..19]}-#{uuid[20..]}"
|
39
|
+
end
|
30
40
|
end
|
31
41
|
end
|
32
42
|
end
|
@@ -4,9 +4,62 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
5
5
|
module PostgreSQL
|
6
6
|
module Quoting
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
7
9
|
QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
|
8
10
|
QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
|
9
11
|
|
12
|
+
module ClassMethods # :nodoc:
|
13
|
+
def column_name_matcher
|
14
|
+
/
|
15
|
+
\A
|
16
|
+
(
|
17
|
+
(?:
|
18
|
+
# "schema_name"."table_name"."column_name"::type_name | function(one or no argument)::type_name
|
19
|
+
((?:\w+\.|"\w+"\.){,2}(?:\w+|"\w+")(?:::\w+)? | \w+\((?:|\g<2>)\)(?:::\w+)?)
|
20
|
+
)
|
21
|
+
(?:(?:\s+AS)?\s+(?:\w+|"\w+"))?
|
22
|
+
)
|
23
|
+
(?:\s*,\s*\g<1>)*
|
24
|
+
\z
|
25
|
+
/ix
|
26
|
+
end
|
27
|
+
|
28
|
+
def column_name_with_order_matcher
|
29
|
+
/
|
30
|
+
\A
|
31
|
+
(
|
32
|
+
(?:
|
33
|
+
# "schema_name"."table_name"."column_name"::type_name | function(one or no argument)::type_name
|
34
|
+
((?:\w+\.|"\w+"\.){,2}(?:\w+|"\w+")(?:::\w+)? | \w+\((?:|\g<2>)\)(?:::\w+)?)
|
35
|
+
)
|
36
|
+
(?:\s+COLLATE\s+"\w+")?
|
37
|
+
(?:\s+ASC|\s+DESC)?
|
38
|
+
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
39
|
+
)
|
40
|
+
(?:\s*,\s*\g<1>)*
|
41
|
+
\z
|
42
|
+
/ix
|
43
|
+
end
|
44
|
+
|
45
|
+
# Quotes column names for use in SQL queries.
|
46
|
+
def quote_column_name(name) # :nodoc:
|
47
|
+
QUOTED_COLUMN_NAMES[name] ||= PG::Connection.quote_ident(name.to_s).freeze
|
48
|
+
end
|
49
|
+
|
50
|
+
# Checks the following cases:
|
51
|
+
#
|
52
|
+
# - table_name
|
53
|
+
# - "table.name"
|
54
|
+
# - schema_name.table_name
|
55
|
+
# - schema_name."table.name"
|
56
|
+
# - "schema.name".table_name
|
57
|
+
# - "schema.name"."table.name"
|
58
|
+
def quote_table_name(name) # :nodoc:
|
59
|
+
QUOTED_TABLE_NAMES[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted.freeze
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
10
63
|
class IntegerOutOf64BitRange < StandardError
|
11
64
|
def initialize(msg)
|
12
65
|
super(msg)
|
@@ -77,30 +130,13 @@ module ActiveRecord
|
|
77
130
|
end
|
78
131
|
end
|
79
132
|
|
80
|
-
# Checks the following cases:
|
81
|
-
#
|
82
|
-
# - table_name
|
83
|
-
# - "table.name"
|
84
|
-
# - schema_name.table_name
|
85
|
-
# - schema_name."table.name"
|
86
|
-
# - "schema.name".table_name
|
87
|
-
# - "schema.name"."table.name"
|
88
|
-
def quote_table_name(name) # :nodoc:
|
89
|
-
QUOTED_TABLE_NAMES[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted.freeze
|
90
|
-
end
|
91
|
-
|
92
|
-
# Quotes schema names for use in SQL queries.
|
93
|
-
def quote_schema_name(name)
|
94
|
-
PG::Connection.quote_ident(name)
|
95
|
-
end
|
96
|
-
|
97
133
|
def quote_table_name_for_assignment(table, attr)
|
98
134
|
quote_column_name(attr)
|
99
135
|
end
|
100
136
|
|
101
|
-
# Quotes
|
102
|
-
def
|
103
|
-
|
137
|
+
# Quotes schema names for use in SQL queries.
|
138
|
+
def quote_schema_name(schema_name)
|
139
|
+
quote_column_name(schema_name)
|
104
140
|
end
|
105
141
|
|
106
142
|
# Quote date/time values for use in SQL input.
|
@@ -143,6 +179,8 @@ module ActiveRecord
|
|
143
179
|
encode_array(value)
|
144
180
|
when Range
|
145
181
|
encode_range(value)
|
182
|
+
when Rational
|
183
|
+
value.to_f
|
146
184
|
else
|
147
185
|
super
|
148
186
|
end
|
@@ -153,44 +191,6 @@ module ActiveRecord
|
|
153
191
|
type_map.lookup(column.oid, column.fmod, column.sql_type)
|
154
192
|
end
|
155
193
|
|
156
|
-
def column_name_matcher
|
157
|
-
COLUMN_NAME
|
158
|
-
end
|
159
|
-
|
160
|
-
def column_name_with_order_matcher
|
161
|
-
COLUMN_NAME_WITH_ORDER
|
162
|
-
end
|
163
|
-
|
164
|
-
COLUMN_NAME = /
|
165
|
-
\A
|
166
|
-
(
|
167
|
-
(?:
|
168
|
-
# "schema_name"."table_name"."column_name"::type_name | function(one or no argument)::type_name
|
169
|
-
((?:\w+\.|"\w+"\.){,2}(?:\w+|"\w+")(?:::\w+)? | \w+\((?:|\g<2>)\)(?:::\w+)?)
|
170
|
-
)
|
171
|
-
(?:(?:\s+AS)?\s+(?:\w+|"\w+"))?
|
172
|
-
)
|
173
|
-
(?:\s*,\s*\g<1>)*
|
174
|
-
\z
|
175
|
-
/ix
|
176
|
-
|
177
|
-
COLUMN_NAME_WITH_ORDER = /
|
178
|
-
\A
|
179
|
-
(
|
180
|
-
(?:
|
181
|
-
# "schema_name"."table_name"."column_name"::type_name | function(one or no argument)::type_name
|
182
|
-
((?:\w+\.|"\w+"\.){,2}(?:\w+|"\w+")(?:::\w+)? | \w+\((?:|\g<2>)\)(?:::\w+)?)
|
183
|
-
)
|
184
|
-
(?:\s+COLLATE\s+"\w+")?
|
185
|
-
(?:\s+ASC|\s+DESC)?
|
186
|
-
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
187
|
-
)
|
188
|
-
(?:\s*,\s*\g<1>)*
|
189
|
-
\z
|
190
|
-
/ix
|
191
|
-
|
192
|
-
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
193
|
-
|
194
194
|
private
|
195
195
|
def lookup_cast_type(sql_type)
|
196
196
|
super(query_value("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").to_i)
|
@@ -332,6 +332,26 @@ module ActiveRecord
|
|
332
332
|
def remove_unique_constraint(*args)
|
333
333
|
@base.remove_unique_constraint(name, *args)
|
334
334
|
end
|
335
|
+
|
336
|
+
# Validates the given constraint on the table.
|
337
|
+
#
|
338
|
+
# t.check_constraint("price > 0", name: "price_check", validate: false)
|
339
|
+
# t.validate_constraint "price_check"
|
340
|
+
#
|
341
|
+
# See {connection.validate_constraint}[rdoc-ref:SchemaStatements#validate_constraint]
|
342
|
+
def validate_constraint(*args)
|
343
|
+
@base.validate_constraint(name, *args)
|
344
|
+
end
|
345
|
+
|
346
|
+
# Validates the given check constraint on the table
|
347
|
+
#
|
348
|
+
# t.check_constraint("price > 0", name: "price_check", validate: false)
|
349
|
+
# t.validate_check_constraint name: "price_check"
|
350
|
+
#
|
351
|
+
# See {connection.validate_check_constraint}[rdoc-ref:SchemaStatements#validate_check_constraint]
|
352
|
+
def validate_check_constraint(*args)
|
353
|
+
@base.validate_check_constraint(name, *args)
|
354
|
+
end
|
335
355
|
end
|
336
356
|
|
337
357
|
# = Active Record PostgreSQL Adapter Alter \Table
|
@@ -112,7 +112,7 @@ module ActiveRecord
|
|
112
112
|
|
113
113
|
orders = {}
|
114
114
|
opclasses = {}
|
115
|
-
include_columns = include ? include.split(",").map(
|
115
|
+
include_columns = include ? include.split(",").map { |c| Utils.unquote_identifier(c.strip.gsub('""', '"')) } : []
|
116
116
|
|
117
117
|
if indkey.include?(0)
|
118
118
|
columns = expressions
|
@@ -209,8 +209,16 @@ module ActiveRecord
|
|
209
209
|
end
|
210
210
|
|
211
211
|
# Creates a schema for the given schema name.
|
212
|
-
def create_schema(schema_name)
|
213
|
-
|
212
|
+
def create_schema(schema_name, force: nil, if_not_exists: nil)
|
213
|
+
if force && if_not_exists
|
214
|
+
raise ArgumentError, "Options `:force` and `:if_not_exists` cannot be used simultaneously."
|
215
|
+
end
|
216
|
+
|
217
|
+
if force
|
218
|
+
drop_schema(schema_name, if_exists: true)
|
219
|
+
end
|
220
|
+
|
221
|
+
execute("CREATE SCHEMA#{' IF NOT EXISTS' if if_not_exists} #{quote_schema_name(schema_name)}")
|
214
222
|
end
|
215
223
|
|
216
224
|
# Drops the schema for the given schema name.
|
@@ -247,6 +255,8 @@ module ActiveRecord
|
|
247
255
|
|
248
256
|
# Returns the sequence name for a table's primary key or some other specified key.
|
249
257
|
def default_sequence_name(table_name, pk = "id") # :nodoc:
|
258
|
+
return nil if pk.is_a?(Array)
|
259
|
+
|
250
260
|
result = serial_sequence(table_name, pk)
|
251
261
|
return nil unless result
|
252
262
|
Utils.extract_schema_qualified_name(result).to_s
|
@@ -400,7 +410,7 @@ module ActiveRecord
|
|
400
410
|
execute "ALTER TABLE #{seq.quoted} RENAME TO #{quote_table_name(new_seq)}"
|
401
411
|
end
|
402
412
|
end
|
403
|
-
rename_table_indexes(table_name, new_name)
|
413
|
+
rename_table_indexes(table_name, new_name, **options)
|
404
414
|
end
|
405
415
|
|
406
416
|
def add_column(table_name, column_name, type, **options) # :nodoc:
|
@@ -522,14 +532,6 @@ module ActiveRecord
|
|
522
532
|
end
|
523
533
|
|
524
534
|
def add_foreign_key(from_table, to_table, **options)
|
525
|
-
if options[:deferrable] == true
|
526
|
-
ActiveRecord.deprecator.warn(<<~MSG)
|
527
|
-
`deferrable: true` is deprecated in favor of `deferrable: :immediate`, and will be removed in Rails 7.2.
|
528
|
-
MSG
|
529
|
-
|
530
|
-
options[:deferrable] = :immediate
|
531
|
-
end
|
532
|
-
|
533
535
|
assert_valid_deferrable(options[:deferrable])
|
534
536
|
|
535
537
|
super
|
@@ -690,6 +692,10 @@ module ActiveRecord
|
|
690
692
|
# The constraint name. Defaults to <tt>excl_rails_<identifier></tt>.
|
691
693
|
# [<tt>:deferrable</tt>]
|
692
694
|
# Specify whether or not the exclusion constraint should be deferrable. Valid values are +false+ or +:immediate+ or +:deferred+ to specify the default behavior. Defaults to +false+.
|
695
|
+
# [<tt>:using</tt>]
|
696
|
+
# Specify which index method to use when creating this exclusion constraint (e.g. +:btree+, +:gist+ etc).
|
697
|
+
# [<tt>:where</tt>]
|
698
|
+
# Specify an exclusion constraint on a subset of the table (internally PostgreSQL creates a partial index for this).
|
693
699
|
def add_exclusion_constraint(table_name, expression, **options)
|
694
700
|
options = exclusion_constraint_options(table_name, expression, options)
|
695
701
|
at = create_alter_table(table_name)
|
@@ -20,17 +20,6 @@ require "active_record/connection_adapters/postgresql/type_metadata"
|
|
20
20
|
require "active_record/connection_adapters/postgresql/utils"
|
21
21
|
|
22
22
|
module ActiveRecord
|
23
|
-
module ConnectionHandling # :nodoc:
|
24
|
-
def postgresql_adapter_class
|
25
|
-
ConnectionAdapters::PostgreSQLAdapter
|
26
|
-
end
|
27
|
-
|
28
|
-
# Establishes a connection to the database that's used by all Active Record objects
|
29
|
-
def postgresql_connection(config)
|
30
|
-
postgresql_adapter_class.new(config)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
23
|
module ConnectionAdapters
|
35
24
|
# = Active Record PostgreSQL Adapter
|
36
25
|
#
|
@@ -133,6 +122,15 @@ module ActiveRecord
|
|
133
122
|
# setting, you should immediately run <tt>bin/rails db:migrate</tt> to update the types in your schema.rb.
|
134
123
|
class_attribute :datetime_type, default: :timestamp
|
135
124
|
|
125
|
+
##
|
126
|
+
# :singleton-method:
|
127
|
+
# Toggles automatic decoding of date columns.
|
128
|
+
#
|
129
|
+
# ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.select_value("select '2024-01-01'::date").class #=> String
|
130
|
+
# ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.decode_dates = true
|
131
|
+
# ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.select_value("select '2024-01-01'::date").class #=> Date
|
132
|
+
class_attribute :decode_dates, default: false
|
133
|
+
|
136
134
|
NATIVE_DATABASE_TYPES = {
|
137
135
|
primary_key: "bigserial primary key",
|
138
136
|
string: { name: "character varying" },
|
@@ -290,10 +288,6 @@ module ActiveRecord
|
|
290
288
|
{ concurrently: "CONCURRENTLY" }
|
291
289
|
end
|
292
290
|
|
293
|
-
def return_value_after_insert?(column) # :nodoc:
|
294
|
-
column.auto_populated?
|
295
|
-
end
|
296
|
-
|
297
291
|
class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
|
298
292
|
def initialize(connection, max)
|
299
293
|
super(max)
|
@@ -342,6 +336,10 @@ module ActiveRecord
|
|
342
336
|
@use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
|
343
337
|
end
|
344
338
|
|
339
|
+
def connected?
|
340
|
+
!(@raw_connection.nil? || @raw_connection.finished?)
|
341
|
+
end
|
342
|
+
|
345
343
|
# Is this connection alive and ready for queries?
|
346
344
|
def active?
|
347
345
|
@lock.synchronize do
|
@@ -613,7 +611,9 @@ module ActiveRecord
|
|
613
611
|
|
614
612
|
# Returns the version of the connected PostgreSQL server.
|
615
613
|
def get_database_version # :nodoc:
|
616
|
-
|
614
|
+
with_raw_connection do |conn|
|
615
|
+
conn.server_version
|
616
|
+
end
|
617
617
|
end
|
618
618
|
alias :postgresql_version :database_version
|
619
619
|
|
@@ -652,8 +652,8 @@ module ActiveRecord
|
|
652
652
|
m.register_type "int4", Type::Integer.new(limit: 4)
|
653
653
|
m.register_type "int8", Type::Integer.new(limit: 8)
|
654
654
|
m.register_type "oid", OID::Oid.new
|
655
|
-
m.register_type "float4", Type::Float.new
|
656
|
-
m.
|
655
|
+
m.register_type "float4", Type::Float.new(limit: 24)
|
656
|
+
m.register_type "float8", Type::Float.new
|
657
657
|
m.register_type "text", Type::Text.new
|
658
658
|
register_class_with_limit m, "varchar", Type::String
|
659
659
|
m.alias_type "char", "varchar"
|
@@ -777,7 +777,7 @@ module ActiveRecord
|
|
777
777
|
|
778
778
|
case exception.result.try(:error_field, PG::PG_DIAG_SQLSTATE)
|
779
779
|
when nil
|
780
|
-
if exception.message.match?(/connection is closed/i)
|
780
|
+
if exception.message.match?(/connection is closed/i) || exception.message.match?(/no connection to the server/i)
|
781
781
|
ConnectionNotEstablished.new(exception, connection_pool: @pool)
|
782
782
|
elsif exception.is_a?(PG::ConnectionBad)
|
783
783
|
# libpq message style always ends with a newline; the pg gem's internal
|
@@ -889,10 +889,11 @@ module ActiveRecord
|
|
889
889
|
update_typemap_for_default_timezone
|
890
890
|
|
891
891
|
type_casted_binds = type_casted_binds(binds)
|
892
|
-
log(sql, name, binds, type_casted_binds, async: async) do
|
893
|
-
with_raw_connection do |conn|
|
892
|
+
log(sql, name, binds, type_casted_binds, async: async) do |notification_payload|
|
893
|
+
with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
|
894
894
|
result = conn.exec_params(sql, type_casted_binds)
|
895
895
|
verified!
|
896
|
+
notification_payload[:row_count] = result.count
|
896
897
|
result
|
897
898
|
end
|
898
899
|
end
|
@@ -903,13 +904,14 @@ module ActiveRecord
|
|
903
904
|
|
904
905
|
update_typemap_for_default_timezone
|
905
906
|
|
906
|
-
with_raw_connection do |conn|
|
907
|
+
with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
|
907
908
|
stmt_key = prepare_statement(sql, binds, conn)
|
908
909
|
type_casted_binds = type_casted_binds(binds)
|
909
910
|
|
910
|
-
log(sql, name, binds, type_casted_binds, stmt_key, async: async) do
|
911
|
+
log(sql, name, binds, type_casted_binds, stmt_key, async: async) do |notification_payload|
|
911
912
|
result = conn.exec_prepared(stmt_key, type_casted_binds)
|
912
913
|
verified!
|
914
|
+
notification_payload[:row_count] = result.count
|
913
915
|
result
|
914
916
|
end
|
915
917
|
end
|
@@ -919,7 +921,7 @@ module ActiveRecord
|
|
919
921
|
# Nothing we can do if we are in a transaction because all commands
|
920
922
|
# will raise InFailedSQLTransaction
|
921
923
|
if in_transaction?
|
922
|
-
raise ActiveRecord::PreparedStatementCacheExpired.new(e.cause.message)
|
924
|
+
raise ActiveRecord::PreparedStatementCacheExpired.new(e.cause.message, connection_pool: @pool)
|
923
925
|
else
|
924
926
|
@lock.synchronize do
|
925
927
|
# outside of transactions we can simply flush this query and retry
|
@@ -995,6 +997,8 @@ module ActiveRecord
|
|
995
997
|
# Configures the encoding, verbosity, schema search path, and time zone of the connection.
|
996
998
|
# This is called by #connect and should not be called manually.
|
997
999
|
def configure_connection
|
1000
|
+
super
|
1001
|
+
|
998
1002
|
if @config[:encoding]
|
999
1003
|
@raw_connection.set_client_encoding(@config[:encoding])
|
1000
1004
|
end
|
@@ -1165,6 +1169,7 @@ module ActiveRecord
|
|
1165
1169
|
"timestamp" => PG::TextDecoder::TimestampUtc,
|
1166
1170
|
"timestamptz" => PG::TextDecoder::TimestampWithTimeZone,
|
1167
1171
|
}
|
1172
|
+
coders_by_name["date"] = PG::TextDecoder::Date if decode_dates
|
1168
1173
|
|
1169
1174
|
known_coder_types = coders_by_name.keys.map { |n| quote(n) }
|
1170
1175
|
query = <<~SQL % known_coder_types.join(", ")
|