Skip to content

Commit a82e432

Browse files
authored
Merge pull request rails#51763 from JoeDupuis/postgresql-adapter-decode-dates-config
Add `active_record.postgresql_adapter_decode_dates` config
2 parents b56ee17 + 478874a commit a82e432

File tree

7 files changed

+103
-8
lines changed

7 files changed

+103
-8
lines changed

activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,15 @@ def dbconsole(config, options = {})
122122
# setting, you should immediately run <tt>bin/rails db:migrate</tt> to update the types in your schema.rb.
123123
class_attribute :datetime_type, default: :timestamp
124124

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+
125134
NATIVE_DATABASE_TYPES = {
126135
primary_key: "bigserial primary key",
127136
string: { name: "character varying" },
@@ -1159,8 +1168,8 @@ def add_pg_decoders
11591168
"bool" => PG::TextDecoder::Boolean,
11601169
"timestamp" => PG::TextDecoder::TimestampUtc,
11611170
"timestamptz" => PG::TextDecoder::TimestampWithTimeZone,
1162-
"date" => PG::TextDecoder::Date,
11631171
}
1172+
coders_by_name["date"] = PG::TextDecoder::Date if decode_dates
11641173

11651174
known_coder_types = coders_by_name.keys.map { |n| quote(n) }
11661175
query = <<~SQL % known_coder_types.join(", ")

activerecord/lib/active_record/railtie.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,16 @@ class Railtie < Rails::Railtie # :nodoc:
217217
end
218218
end
219219

220+
initializer "active_record.postgresql_adapter_decode_dates" do
221+
config.after_initialize do
222+
if config.active_record.postgresql_adapter_decode_dates
223+
ActiveSupport.on_load(:active_record_postgresqladapter) do
224+
self.decode_dates = true
225+
end
226+
end
227+
end
228+
end
229+
220230
initializer "active_record.set_configs" do |app|
221231
configs = app.config.active_record
222232

@@ -245,7 +255,8 @@ class Railtie < Rails::Railtie # :nodoc:
245255
:cache_query_log_tags,
246256
:sqlite3_adapter_strict_strings_by_default,
247257
:check_schema_cache_dump_version,
248-
:use_schema_cache_dump
258+
:use_schema_cache_dump,
259+
:postgresql_adapter_decode_dates,
249260
)
250261

251262
configs.each do |k, v|

activerecord/test/cases/adapters/postgresql/date_test.rb

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,4 @@ def test_bc_date_year_zero
3939
topic = Topic.create!(last_read: date)
4040
assert_equal date, Topic.find(topic.id).last_read
4141
end
42-
43-
def test_date_decoder
44-
date = ActiveRecord::Base.connection.select_value("select '2024-01-01'::date")
45-
assert_equal Date.new(2024, 01, 01), date
46-
assert_equal Date, date.class
47-
end
4842
end

activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,34 @@ def test_does_not_raise_notice_level_warnings
649649
end
650650
end
651651

652+
def test_date_decoding_enabled
653+
db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
654+
connection = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new(db_config.configuration_hash)
655+
656+
with_postgresql_apdater_decode_dates do
657+
date = connection.select_value("select '2024-01-01'::date")
658+
assert_equal Date.new(2024, 01, 01), date
659+
assert_equal Date, date.class
660+
end
661+
end
662+
663+
def test_date_decoding_disabled
664+
db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
665+
connection = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new(db_config.configuration_hash)
666+
667+
date = connection.select_value("select '2024-01-01'::date")
668+
assert_equal "2024-01-01", date
669+
assert_equal String, date.class
670+
end
671+
652672
private
673+
def with_postgresql_apdater_decode_dates
674+
PostgreSQLAdapter.decode_dates = true
675+
yield
676+
ensure
677+
PostgreSQLAdapter.decode_dates = false
678+
end
679+
653680
def with_example_table(definition = "id serial primary key, number integer, data character varying(255)", &block)
654681
super(@connection, "ex", definition, &block)
655682
end

guides/source/configuring.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Below are the default values associated with each target version. In cases of co
6262

6363
- [`config.active_job.enqueue_after_transaction_commit`](#config-active-job-enqueue-after-transaction-commit): `:default`
6464
- [`config.active_record.automatically_invert_plural_associations`](#config-active-record-automatically-invert-plural-associations): `true`
65+
- [`config.active_record.postgresql_adapter_decode_dates`](#config-active-record-postgresql-adapter-decode-dates): `true`
6566
- [`config.active_record.validate_migration_timestamps`](#config-active-record-validate-migration-timestamps): `true`
6667
- [`config.active_storage.web_image_content_types`](#config-active-storage-web-image-content-types): `%w[image/png image/jpeg image/gif image/webp]`
6768

@@ -1490,6 +1491,24 @@ The default value depends on the `config.load_defaults` target version:
14901491
| (original) | `false` |
14911492
| 7.1 | `true` |
14921493

1494+
#### `config.active_record.postgresql_adapter_decode_dates`
1495+
1496+
Specifies whether the PostgresqlAdapter should decode date columns.
1497+
1498+
```ruby
1499+
ActiveRecord::Base.connection
1500+
.select_value("select '2024-01-01'::date").class #=> Date
1501+
```
1502+
1503+
1504+
The default value depends on the `config.load_defaults` target version:
1505+
1506+
| Starting with version | The default value is |
1507+
| --------------------- | -------------------- |
1508+
| (original) | `false` |
1509+
| 7.2 | `true` |
1510+
1511+
14931512
#### `config.active_record.async_query_executor`
14941513

14951514
Specifies how asynchronous queries are pooled.

railties/lib/rails/application/configuration.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ def load_defaults(target_version)
327327
end
328328

329329
if respond_to?(:active_record)
330+
active_record.postgresql_adapter_decode_dates = true
330331
active_record.validate_migration_timestamps = true
331332
active_record.automatically_invert_plural_associations = true
332333
end

railties/test/application/configuration_test.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2793,6 +2793,40 @@ def index
27932793
assert_equal false, ActiveRecord::Base.run_commit_callbacks_on_first_saved_instances_in_transaction
27942794
end
27952795

2796+
test "PostgresqlAdapter.decode_dates is true by default for new apps" do
2797+
app_file "config/initializers/active_record.rb", <<~RUBY
2798+
ActiveRecord::Base.establish_connection(adapter: "postgresql")
2799+
RUBY
2800+
2801+
app "development"
2802+
2803+
assert_equal true, ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.decode_dates
2804+
end
2805+
2806+
test "PostgresqlAdapter.decode_dates is false by default for upgraded apps" do
2807+
remove_from_config '.*config\.load_defaults.*\n'
2808+
app_file "config/initializers/active_record.rb", <<~RUBY
2809+
ActiveRecord::Base.establish_connection(adapter: "postgresql")
2810+
RUBY
2811+
2812+
app "development"
2813+
2814+
assert_equal false, ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.decode_dates
2815+
end
2816+
2817+
test "PostgresqlAdapter.decode_dates can be configured via config.active_record.postgresql_adapter_decode_dates" do
2818+
remove_from_config '.*config\.load_defaults.*\n'
2819+
add_to_config "config.active_record.postgresql_adapter_decode_dates = true"
2820+
2821+
app_file "config/initializers/active_record.rb", <<~RUBY
2822+
ActiveRecord::Base.establish_connection(adapter: "postgresql")
2823+
RUBY
2824+
2825+
app "development"
2826+
2827+
assert_equal true, ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.decode_dates
2828+
end
2829+
27962830
test "SQLite3Adapter.strict_strings_by_default is true by default for new apps" do
27972831
app_file "config/initializers/active_record.rb", <<~RUBY
27982832
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")

0 commit comments

Comments
 (0)