Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve postgres interval overflow protection
> Sometimes, operations on Times returns just float numbers of seconds, so, we need to handle that. > Example: Time.current - (Time.current + 1.hour) # => -3600.000001776 (Float) When this happens, it's possible to endup with a pretty large number of seconds, making the ISO 8601 formatted duration to trigger an `interval field value out range error`. PostgreSQL 15 has already improved overflow detection when casting values to interval However, to further reduce the likelihood of such issues and ensure better-formatted duration types, it now implements the construction of `ActiveSupport::Duration` during the serialization step. How to reproduce (at least in versions prior to PG 15+): ``` ruby require "bundler/inline" gemfile(true) do source "https://rubygems.org" git_source(:github) { |repo| "https://github.com/#{repo}.git" } gem "rails", github: "rails/rails", branch: "main" gem "pg" end require "active_record" require "minitest/autorun" require "logger" ActiveRecord::Base.establish_connection( adapter: 'postgresql', database: 'postgres', username: 'postgres', host: 'localhost' ) ActiveRecord::Base.logger = Logger.new(STDOUT) ActiveRecord::Schema.define do create_table :projects, force: true do |t| t.interval :duration end end class Project < ActiveRecord::Base; end class IntervalBugTest < Minitest::Test def test_duration project = Project.create(duration: 70.years) assert_equal 70.years, project.duration end def test_duration_error duration = 70.years.ago - Time.now() assert_raises ActiveRecord::StatementInvalid do Project.create(duration: duration) end end end ```
- Loading branch information