Repository navigation
PostgreSQL: fix ActiveRecord.default_timezone runtime switching being ignored - #1237
Open
ryudoawaru wants to merge 2 commits into
Open
ryudoawaru wants to merge 2 commits into
ryudoawaru wants to merge 2 commits into
Conversation
… ignored Changing ActiveRecord.default_timezone (or the process zone while :local) at runtime never updated the PostgreSQL session time zone, so the JDBC driver kept returning timestamps in the zone set at connect time. * update_typemap_for_default_timezone was only called from exec_no_cache/exec_cache, which the ORM query path never reaches (it goes through internal_exec_query), and it was guarded by @timestamp_decoder, which is always nil under JDBC. Hook internal_exec_query and drop the dead PG::TextDecoder branch. * local_tz memoized the first session zone; read Java's default TimeZone live instead. * Track the resolved zone name as well as the :utc/:local symbol so a switch between two local zones is detected. * Record the state in #configure_connection before it issues SQL, to avoid re-entrant recursion and a redundant first reconfigure. Use @configured_default_timezone rather than @default_timezone: Rails treats the latter as a per-connection override, and pinning it breaks quoting with PREPARED_STATEMENTS=false. * setTimestampParameter now passes getDefaultTimeZone(context) instead of null, like the sibling date/time parsers. Adds test/db/postgresql/default_timezone_test.rb. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
With prepared statements disabled the SQL is sent without binds, so the `?` placeholder in test_bound_timestamp_keeps_instant_when_local reaches PostgreSQL verbatim and raises a syntax error. The test also passed with or without the setTimestampParameter change, so it did not verify it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
ryudoawaru
marked this pull request as draft
October 28, 2026 07:35
ryudoawaru
marked this pull request as ready for review
October 28, 2026 07:36
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On
master, changingActiveRecord.default_timezone(or the process zone while:local) at runtime never changes the PostgreSQL session time zone, so the JDBC driver keeps returning timestamps in the zone set at connect time.Reproduction (
:utc->:local+ Asia/Tokyo ->:local+ America/New_York ->:utc),SHOW TIME ZONE::utc:local+ Asia/Tokyo:local+ America/New_York:utcCauses and changes
update_typemap_for_default_timezonewas only called fromexec_no_cache/exec_cache, which the ORM path never reaches (it usesinternal_exec_query), and was guarded by@timestamp_decoder, which is always nil under JDBC. Now hooked intointernal_exec_query; the deadPG::TextDecoderbranch is removed.local_tzmemoized the first session zone. It now reads Java's defaultTimeZonelive.:utc/:local, so switching between two local zones was missed. It now also compares the resolved zone name.configure_connection(it issues SQL that re-entersinternal_exec_query, so this avoids recursion and a redundant first reconfigure). It uses@configured_default_timezone, not@default_timezone: Rails treats the latter as a per-connection override, and pinning it breaks quoting withPREPARED_STATEMENTS=false.setTimestampParameterpassesgetDefaultTimeZone(context)instead ofnull, like the sibling date/time parsers. I do not have a test showing this line matters (a bind-parameter test I tried passed with or without it, and cannot run withPREPARED_STATEMENTS=false, so I dropped it). Happy to drop the line if you prefer.New test:
test/db/postgresql/default_timezone_test.rb(fails onmaster, passes here).Testing
Local PostgreSQL, JRuby 10.0.0.1, Java 21. Compared against unmodified
master:rake test_postgresql, default andPREPARED_STATEMENTS=false: no new failures. The 21 existing errors (PostgresSchemaDumpTest, uninitialized constantPG) are identical onmaster, which is also why the ARJDBC Postgres CI jobs are red onmaster(run for Remove special cases for 8.0 support #1226).rake rails:test_postgresqlagainst Rails 8-1-stable, time-related files only (12 files, 489 tests): no new failures in either mode; two Rails tests that failed onmasternow pass (FinderTest#test_condition_local_time_interpolation_with_default_timezone_utc,FinderTest#test_condition_utc_time_interpolation_with_default_timezone_local).Not run: the full Rails activerecord suite, MySQL/SQLite3.
🤖 Generated with Claude Code