activerecord 7.1.5.1 → 8.0.2
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 +369 -2484
- data/README.rdoc +15 -15
- data/examples/performance.rb +2 -2
- data/lib/active_record/association_relation.rb +2 -1
- data/lib/active_record/associations/alias_tracker.rb +31 -23
- data/lib/active_record/associations/association.rb +43 -12
- data/lib/active_record/associations/belongs_to_association.rb +21 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/association.rb +7 -6
- 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 +17 -9
- data/lib/active_record/associations/collection_proxy.rb +14 -1
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +10 -3
- data/lib/active_record/associations/join_dependency/join_association.rb +1 -1
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +4 -3
- 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 +14 -3
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +92 -295
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- 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/primary_key.rb +25 -61
- data/lib/active_record/attribute_methods/read.rb +1 -13
- data/lib/active_record/attribute_methods/serialization.rb +4 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +9 -18
- data/lib/active_record/attribute_methods.rb +71 -75
- data/lib/active_record/attributes.rb +63 -49
- data/lib/active_record/autosave_association.rb +92 -57
- 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 +48 -122
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +286 -77
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +119 -55
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +197 -76
- data/lib/active_record/connection_adapters/abstract/quoting.rb +66 -92
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +12 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +48 -12
- data/lib/active_record/connection_adapters/abstract/transaction.rb +140 -67
- data/lib/active_record/connection_adapters/abstract_adapter.rb +85 -90
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +71 -52
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -57
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +56 -45
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +92 -101
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +13 -31
- data/lib/active_record/connection_adapters/pool_config.rb +14 -13
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +86 -41
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- 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/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +1 -11
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +36 -20
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +75 -28
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +73 -113
- data/lib/active_record/connection_adapters/schema_cache.rb +124 -131
- data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +81 -97
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +57 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +29 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +35 -3
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +183 -87
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +39 -69
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +19 -65
- data/lib/active_record/connection_adapters.rb +65 -0
- data/lib/active_record/connection_handling.rb +74 -37
- data/lib/active_record/core.rb +132 -51
- data/lib/active_record/counter_cache.rb +19 -10
- data/lib/active_record/database_configurations/connection_url_resolver.rb +9 -2
- data/lib/active_record/database_configurations/database_config.rb +23 -4
- data/lib/active_record/database_configurations/hash_config.rb +46 -34
- 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 +41 -17
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +7 -7
- data/lib/active_record/encryption/encrypted_attribute_type.rb +33 -4
- data/lib/active_record/encryption/encryptor.rb +28 -6
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- 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 -1
- data/lib/active_record/enum.rb +20 -16
- data/lib/active_record/errors.rb +54 -20
- data/lib/active_record/explain.rb +13 -24
- data/lib/active_record/fixtures.rb +37 -33
- data/lib/active_record/future_result.rb +21 -13
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +4 -2
- data/lib/active_record/insert_all.rb +19 -16
- 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 +5 -32
- data/lib/active_record/message_pack.rb +1 -1
- data/lib/active_record/migration/command_recorder.rb +33 -14
- data/lib/active_record/migration/compatibility.rb +8 -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 +104 -98
- data/lib/active_record/model_schema.rb +32 -70
- data/lib/active_record/nested_attributes.rb +15 -9
- data/lib/active_record/normalization.rb +3 -7
- data/lib/active_record/persistence.rb +127 -451
- data/lib/active_record/query_cache.rb +19 -8
- data/lib/active_record/query_logs.rb +104 -37
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +24 -12
- data/lib/active_record/railtie.rb +26 -68
- data/lib/active_record/railties/controller_runtime.rb +13 -4
- data/lib/active_record/railties/databases.rake +43 -61
- data/lib/active_record/reflection.rb +112 -53
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +138 -72
- data/lib/active_record/relation/calculations.rb +122 -82
- data/lib/active_record/relation/delegation.rb +30 -22
- data/lib/active_record/relation/finder_methods.rb +32 -18
- data/lib/active_record/relation/merger.rb +12 -14
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +10 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +16 -3
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +317 -101
- data/lib/active_record/relation/spawn_methods.rb +3 -19
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +561 -119
- data/lib/active_record/result.rb +95 -46
- data/lib/active_record/runtime_registry.rb +39 -0
- data/lib/active_record/sanitization.rb +31 -25
- data/lib/active_record/schema.rb +8 -6
- data/lib/active_record/schema_dumper.rb +53 -20
- data/lib/active_record/schema_migration.rb +31 -14
- data/lib/active_record/scoping/named.rb +6 -2
- data/lib/active_record/signed_id.rb +24 -4
- data/lib/active_record/statement_cache.rb +19 -19
- data/lib/active_record/store.rb +7 -3
- data/lib/active_record/table_metadata.rb +2 -13
- data/lib/active_record/tasks/database_tasks.rb +87 -58
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -3
- data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +4 -3
- data/lib/active_record/test_fixtures.rb +98 -89
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +2 -2
- 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 +72 -17
- 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 +23 -18
- data/lib/active_record/validations.rb +4 -1
- data/lib/active_record.rb +138 -57
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +4 -2
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +2 -2
- data/lib/arel/collectors/substitute_binds.rb +3 -3
- data/lib/arel/nodes/binary.rb +1 -7
- 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 +5 -4
- data/lib/arel/nodes/sql_literal.rb +8 -1
- 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/table.rb +3 -7
- data/lib/arel/tree_manager.rb +3 -2
- 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 +29 -16
- data/lib/arel.rb +7 -3
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- metadata +18 -16
- data/lib/active_record/relation/record_fetch_warning.rb +0 -49
@@ -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
|
#
|
@@ -97,7 +86,7 @@ module ActiveRecord
|
|
97
86
|
"-c #{name}=#{value.to_s.gsub(/[ \\]/, '\\\\\0')}" unless value == ":default" || value == :default
|
98
87
|
end.join(" ")
|
99
88
|
end
|
100
|
-
find_cmd_and_exec(
|
89
|
+
find_cmd_and_exec(ActiveRecord.database_cli[:postgresql], config.database)
|
101
90
|
end
|
102
91
|
end
|
103
92
|
|
@@ -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" },
|
@@ -286,12 +284,12 @@ module ActiveRecord
|
|
286
284
|
database_version >= 15_00_00 # >= 15.0
|
287
285
|
end
|
288
286
|
|
289
|
-
def
|
290
|
-
|
287
|
+
def supports_native_partitioning? # :nodoc:
|
288
|
+
database_version >= 10_00_00 # >= 10.0
|
291
289
|
end
|
292
290
|
|
293
|
-
def
|
294
|
-
|
291
|
+
def index_algorithms
|
292
|
+
{ concurrently: "CONCURRENTLY" }
|
295
293
|
end
|
296
294
|
|
297
295
|
class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
|
@@ -342,11 +340,16 @@ module ActiveRecord
|
|
342
340
|
@use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
|
343
341
|
end
|
344
342
|
|
343
|
+
def connected?
|
344
|
+
!(@raw_connection.nil? || @raw_connection.finished?)
|
345
|
+
end
|
346
|
+
|
345
347
|
# Is this connection alive and ready for queries?
|
346
348
|
def active?
|
347
349
|
@lock.synchronize do
|
348
350
|
return false unless @raw_connection
|
349
351
|
@raw_connection.query ";"
|
352
|
+
verified!
|
350
353
|
end
|
351
354
|
true
|
352
355
|
rescue PG::Error
|
@@ -407,7 +410,7 @@ module ActiveRecord
|
|
407
410
|
end
|
408
411
|
|
409
412
|
def set_standard_conforming_strings
|
410
|
-
internal_execute("SET standard_conforming_strings = on")
|
413
|
+
internal_execute("SET standard_conforming_strings = on", "SCHEMA")
|
411
414
|
end
|
412
415
|
|
413
416
|
def supports_ddl_transactions?
|
@@ -481,6 +484,7 @@ module ActiveRecord
|
|
481
484
|
# Set to +:cascade+ to drop dependent objects as well.
|
482
485
|
# Defaults to false.
|
483
486
|
def disable_extension(name, force: false)
|
487
|
+
_schema, name = name.to_s.split(".").values_at(-2, -1)
|
484
488
|
internal_exec_query("DROP EXTENSION IF EXISTS \"#{name}\"#{' CASCADE' if force == :cascade}").tap {
|
485
489
|
reload_type_map
|
486
490
|
}
|
@@ -495,7 +499,19 @@ module ActiveRecord
|
|
495
499
|
end
|
496
500
|
|
497
501
|
def extensions
|
498
|
-
|
502
|
+
query = <<~SQL
|
503
|
+
SELECT
|
504
|
+
pg_extension.extname,
|
505
|
+
n.nspname AS schema
|
506
|
+
FROM pg_extension
|
507
|
+
JOIN pg_namespace n ON pg_extension.extnamespace = n.oid
|
508
|
+
SQL
|
509
|
+
|
510
|
+
internal_exec_query(query, "SCHEMA", allow_retry: true, materialize_transactions: false).cast_values.map do |row|
|
511
|
+
name, schema = row[0], row[1]
|
512
|
+
schema = nil if schema == current_schema
|
513
|
+
[schema, name].compact.join(".")
|
514
|
+
end
|
499
515
|
end
|
500
516
|
|
501
517
|
# Returns a list of defined enum types, and their values.
|
@@ -505,7 +521,7 @@ module ActiveRecord
|
|
505
521
|
type.typname AS name,
|
506
522
|
type.OID AS oid,
|
507
523
|
n.nspname AS schema,
|
508
|
-
|
524
|
+
array_agg(enum.enumlabel ORDER BY enum.enumsortorder) AS value
|
509
525
|
FROM pg_enum AS enum
|
510
526
|
JOIN pg_type AS type ON (type.oid = enum.enumtypid)
|
511
527
|
JOIN pg_namespace n ON type.typnamespace = n.oid
|
@@ -560,30 +576,34 @@ module ActiveRecord
|
|
560
576
|
end
|
561
577
|
|
562
578
|
# Rename an existing enum type to something else.
|
563
|
-
def rename_enum(name,
|
564
|
-
|
579
|
+
def rename_enum(name, new_name = nil, **options)
|
580
|
+
new_name ||= options.fetch(:to) do
|
581
|
+
raise ArgumentError, "rename_enum requires two from/to name positional arguments."
|
582
|
+
end
|
565
583
|
|
566
|
-
exec_query("ALTER TYPE #{quote_table_name(name)} RENAME TO #{
|
584
|
+
exec_query("ALTER TYPE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}").tap { reload_type_map }
|
567
585
|
end
|
568
586
|
|
569
587
|
# Add enum value to an existing enum type.
|
570
|
-
def add_enum_value(type_name, value, options
|
588
|
+
def add_enum_value(type_name, value, **options)
|
571
589
|
before, after = options.values_at(:before, :after)
|
572
|
-
sql = +"ALTER TYPE #{quote_table_name(type_name)} ADD VALUE
|
590
|
+
sql = +"ALTER TYPE #{quote_table_name(type_name)} ADD VALUE"
|
591
|
+
sql << " IF NOT EXISTS" if options[:if_not_exists]
|
592
|
+
sql << " #{quote(value)}"
|
573
593
|
|
574
594
|
if before && after
|
575
595
|
raise ArgumentError, "Cannot have both :before and :after at the same time"
|
576
596
|
elsif before
|
577
|
-
sql << " BEFORE
|
597
|
+
sql << " BEFORE #{quote(before)}"
|
578
598
|
elsif after
|
579
|
-
sql << " AFTER
|
599
|
+
sql << " AFTER #{quote(after)}"
|
580
600
|
end
|
581
601
|
|
582
602
|
execute(sql).tap { reload_type_map }
|
583
603
|
end
|
584
604
|
|
585
605
|
# Rename enum value on an existing enum type.
|
586
|
-
def rename_enum_value(type_name, options
|
606
|
+
def rename_enum_value(type_name, **options)
|
587
607
|
unless database_version >= 10_00_00 # >= 10.0
|
588
608
|
raise ArgumentError, "Renaming enum values is only supported in PostgreSQL 10 or later"
|
589
609
|
end
|
@@ -591,7 +611,7 @@ module ActiveRecord
|
|
591
611
|
from = options.fetch(:from) { raise ArgumentError, ":from is required" }
|
592
612
|
to = options.fetch(:to) { raise ArgumentError, ":to is required" }
|
593
613
|
|
594
|
-
execute("ALTER TYPE #{quote_table_name(type_name)} RENAME VALUE
|
614
|
+
execute("ALTER TYPE #{quote_table_name(type_name)} RENAME VALUE #{quote(from)} TO #{quote(to)}").tap {
|
595
615
|
reload_type_map
|
596
616
|
}
|
597
617
|
end
|
@@ -613,7 +633,13 @@ module ActiveRecord
|
|
613
633
|
|
614
634
|
# Returns the version of the connected PostgreSQL server.
|
615
635
|
def get_database_version # :nodoc:
|
616
|
-
|
636
|
+
with_raw_connection do |conn|
|
637
|
+
version = conn.server_version
|
638
|
+
if version == 0
|
639
|
+
raise ActiveRecord::ConnectionFailed, "Could not determine PostgreSQL version"
|
640
|
+
end
|
641
|
+
version
|
642
|
+
end
|
617
643
|
end
|
618
644
|
alias :postgresql_version :database_version
|
619
645
|
|
@@ -652,8 +678,8 @@ module ActiveRecord
|
|
652
678
|
m.register_type "int4", Type::Integer.new(limit: 4)
|
653
679
|
m.register_type "int8", Type::Integer.new(limit: 8)
|
654
680
|
m.register_type "oid", OID::Oid.new
|
655
|
-
m.register_type "float4", Type::Float.new
|
656
|
-
m.
|
681
|
+
m.register_type "float4", Type::Float.new(limit: 24)
|
682
|
+
m.register_type "float8", Type::Float.new
|
657
683
|
m.register_type "text", Type::Text.new
|
658
684
|
register_class_with_limit m, "varchar", Type::String
|
659
685
|
m.alias_type "char", "varchar"
|
@@ -777,7 +803,7 @@ module ActiveRecord
|
|
777
803
|
|
778
804
|
case exception.result.try(:error_field, PG::PG_DIAG_SQLSTATE)
|
779
805
|
when nil
|
780
|
-
if exception.message.match?(/connection is closed/i)
|
806
|
+
if exception.message.match?(/connection is closed/i) || exception.message.match?(/no connection to the server/i)
|
781
807
|
ConnectionNotEstablished.new(exception, connection_pool: @pool)
|
782
808
|
elsif exception.is_a?(PG::ConnectionBad)
|
783
809
|
# libpq message style always ends with a newline; the pg gem's internal
|
@@ -841,9 +867,8 @@ module ActiveRecord
|
|
841
867
|
def load_additional_types(oids = nil)
|
842
868
|
initializer = OID::TypeMapInitializer.new(type_map)
|
843
869
|
load_types_queries(initializer, oids) do |query|
|
844
|
-
|
845
|
-
|
846
|
-
end
|
870
|
+
records = internal_execute(query, "SCHEMA", [], allow_retry: true, materialize_transactions: false)
|
871
|
+
initializer.run(records)
|
847
872
|
end
|
848
873
|
end
|
849
874
|
|
@@ -864,71 +889,6 @@ module ActiveRecord
|
|
864
889
|
|
865
890
|
FEATURE_NOT_SUPPORTED = "0A000" # :nodoc:
|
866
891
|
|
867
|
-
def execute_and_clear(sql, name, binds, prepare: false, async: false, allow_retry: false, materialize_transactions: true)
|
868
|
-
sql = transform_query(sql)
|
869
|
-
check_if_write_query(sql)
|
870
|
-
|
871
|
-
if !prepare || without_prepared_statement?(binds)
|
872
|
-
result = exec_no_cache(sql, name, binds, async: async, allow_retry: allow_retry, materialize_transactions: materialize_transactions)
|
873
|
-
else
|
874
|
-
result = exec_cache(sql, name, binds, async: async, allow_retry: allow_retry, materialize_transactions: materialize_transactions)
|
875
|
-
end
|
876
|
-
begin
|
877
|
-
ret = yield result
|
878
|
-
ensure
|
879
|
-
result.clear
|
880
|
-
end
|
881
|
-
ret
|
882
|
-
end
|
883
|
-
|
884
|
-
def exec_no_cache(sql, name, binds, async:, allow_retry:, materialize_transactions:)
|
885
|
-
mark_transaction_written_if_write(sql)
|
886
|
-
|
887
|
-
# make sure we carry over any changes to ActiveRecord.default_timezone that have been
|
888
|
-
# made since we established the connection
|
889
|
-
update_typemap_for_default_timezone
|
890
|
-
|
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|
|
894
|
-
result = conn.exec_params(sql, type_casted_binds)
|
895
|
-
verified!
|
896
|
-
result
|
897
|
-
end
|
898
|
-
end
|
899
|
-
end
|
900
|
-
|
901
|
-
def exec_cache(sql, name, binds, async:, allow_retry:, materialize_transactions:)
|
902
|
-
mark_transaction_written_if_write(sql)
|
903
|
-
|
904
|
-
update_typemap_for_default_timezone
|
905
|
-
|
906
|
-
with_raw_connection do |conn|
|
907
|
-
stmt_key = prepare_statement(sql, binds, conn)
|
908
|
-
type_casted_binds = type_casted_binds(binds)
|
909
|
-
|
910
|
-
log(sql, name, binds, type_casted_binds, stmt_key, async: async) do
|
911
|
-
result = conn.exec_prepared(stmt_key, type_casted_binds)
|
912
|
-
verified!
|
913
|
-
result
|
914
|
-
end
|
915
|
-
end
|
916
|
-
rescue ActiveRecord::StatementInvalid => e
|
917
|
-
raise unless is_cached_plan_failure?(e)
|
918
|
-
|
919
|
-
# Nothing we can do if we are in a transaction because all commands
|
920
|
-
# will raise InFailedSQLTransaction
|
921
|
-
if in_transaction?
|
922
|
-
raise ActiveRecord::PreparedStatementCacheExpired.new(e.cause.message)
|
923
|
-
else
|
924
|
-
@lock.synchronize do
|
925
|
-
# outside of transactions we can simply flush this query and retry
|
926
|
-
@statements.delete sql_key(sql)
|
927
|
-
end
|
928
|
-
retry
|
929
|
-
end
|
930
|
-
end
|
931
|
-
|
932
892
|
# Annoyingly, the code for prepared statements whose return value may
|
933
893
|
# have changed is FEATURE_NOT_SUPPORTED.
|
934
894
|
#
|
@@ -938,8 +898,7 @@ module ActiveRecord
|
|
938
898
|
#
|
939
899
|
# Check here for more details:
|
940
900
|
# https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
|
941
|
-
def is_cached_plan_failure?(
|
942
|
-
pgerror = e.cause
|
901
|
+
def is_cached_plan_failure?(pgerror)
|
943
902
|
pgerror.result.result_error_field(PG::PG_DIAG_SQLSTATE) == FEATURE_NOT_SUPPORTED &&
|
944
903
|
pgerror.result.result_error_field(PG::PG_DIAG_SOURCE_FUNCTION) == "RevalidateCachedQuery"
|
945
904
|
rescue
|
@@ -995,6 +954,8 @@ module ActiveRecord
|
|
995
954
|
# Configures the encoding, verbosity, schema search path, and time zone of the connection.
|
996
955
|
# This is called by #connect and should not be called manually.
|
997
956
|
def configure_connection
|
957
|
+
super
|
958
|
+
|
998
959
|
if @config[:encoding]
|
999
960
|
@raw_connection.set_client_encoding(@config[:encoding])
|
1000
961
|
end
|
@@ -1016,16 +977,16 @@ module ActiveRecord
|
|
1016
977
|
variables = @config.fetch(:variables, {}).stringify_keys
|
1017
978
|
|
1018
979
|
# Set interval output format to ISO 8601 for ease of parsing by ActiveSupport::Duration.parse
|
1019
|
-
internal_execute("SET intervalstyle = iso_8601")
|
980
|
+
internal_execute("SET intervalstyle = iso_8601", "SCHEMA")
|
1020
981
|
|
1021
982
|
# SET statements from :variables config hash
|
1022
983
|
# https://www.postgresql.org/docs/current/static/sql-set.html
|
1023
984
|
variables.map do |k, v|
|
1024
985
|
if v == ":default" || v == :default
|
1025
986
|
# Sets the value to the global or compile default
|
1026
|
-
internal_execute("SET SESSION #{k} TO DEFAULT")
|
987
|
+
internal_execute("SET SESSION #{k} TO DEFAULT", "SCHEMA")
|
1027
988
|
elsif !v.nil?
|
1028
|
-
internal_execute("SET SESSION #{k} TO #{quote(v)}")
|
989
|
+
internal_execute("SET SESSION #{k} TO #{quote(v)}", "SCHEMA")
|
1029
990
|
end
|
1030
991
|
end
|
1031
992
|
|
@@ -1046,9 +1007,9 @@ module ActiveRecord
|
|
1046
1007
|
# If using Active Record's time zone support configure the connection
|
1047
1008
|
# to return TIMESTAMP WITH ZONE types in UTC.
|
1048
1009
|
if default_timezone == :utc
|
1049
|
-
|
1010
|
+
raw_execute("SET SESSION timezone TO 'UTC'", "SCHEMA")
|
1050
1011
|
else
|
1051
|
-
|
1012
|
+
raw_execute("SET SESSION timezone TO DEFAULT", "SCHEMA")
|
1052
1013
|
end
|
1053
1014
|
end
|
1054
1015
|
|
@@ -1115,9 +1076,8 @@ module ActiveRecord
|
|
1115
1076
|
AND castsource = #{quote column.sql_type}::regtype
|
1116
1077
|
)
|
1117
1078
|
SQL
|
1118
|
-
|
1119
|
-
|
1120
|
-
end
|
1079
|
+
result = internal_execute(sql, "SCHEMA", [], allow_retry: true, materialize_transactions: false)
|
1080
|
+
result.getvalue(0, 0)
|
1121
1081
|
end
|
1122
1082
|
end
|
1123
1083
|
end
|
@@ -1165,6 +1125,7 @@ module ActiveRecord
|
|
1165
1125
|
"timestamp" => PG::TextDecoder::TimestampUtc,
|
1166
1126
|
"timestamptz" => PG::TextDecoder::TimestampWithTimeZone,
|
1167
1127
|
}
|
1128
|
+
coders_by_name["date"] = PG::TextDecoder::Date if decode_dates
|
1168
1129
|
|
1169
1130
|
known_coder_types = coders_by_name.keys.map { |n| quote(n) }
|
1170
1131
|
query = <<~SQL % known_coder_types.join(", ")
|
@@ -1172,9 +1133,8 @@ module ActiveRecord
|
|
1172
1133
|
FROM pg_type as t
|
1173
1134
|
WHERE t.typname IN (%s)
|
1174
1135
|
SQL
|
1175
|
-
|
1176
|
-
|
1177
|
-
end
|
1136
|
+
result = internal_execute(query, "SCHEMA", [], allow_retry: true, materialize_transactions: false)
|
1137
|
+
coders = result.filter_map { |row| construct_coder(row, coders_by_name[row["typname"]]) }
|
1178
1138
|
|
1179
1139
|
map = PG::TypeMapByOid.new
|
1180
1140
|
coders.each { |coder| map.add_coder(coder) }
|