-
Notifications
You must be signed in to change notification settings - Fork 22k
Description
Steps to reproduce
When dumping a PostgreSQL schema that includes a real
column (defined as float(24)
), the column is represented as float
in the generated schema dump. However, when loading this schema, the real
column is converted to double precision
.
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
gem "rails", "7.1.4"
gem "pg"
end
require "active_record"
require "minitest/autorun"
require "logger"
dbconfig = {
adapter: "postgresql",
username: "postgres",
password: "postgres",
host: "localhost",
database: "migration_test"
}
ActiveRecord::Base.establish_connection(dbconfig.merge(database: "postgres"))
ActiveRecord::Base.connection.drop_database("migration_test")
ActiveRecord::Base.connection.create_database("migration_test")
ActiveRecord::Base.establish_connection(dbconfig)
ActiveRecord::Base.logger = Logger.new(STDOUT)
class CreatePaymentWithFloatColumn < ActiveRecord::Migration::Current
def change
create_table :payments do |t|
t.float :amount, limit: 24
end
end
end
class Payment < ActiveRecord::Base
end
class BugTest < Minitest::Test
def test_migration_up
CreatePaymentWithFloatColumn.migrate(:up)
Payment.reset_column_information
assert_equal "real", Payment.columns_hash["amount"].sql_type
io = StringIO.new
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, io)
assert_includes('t.float "amount", limit: 24', io.string)
end
end
result:
Run options: --seed 55169
# Running:
== CreatePaymentWithFloatColumn: migrating ===================================
-- create_table(:payments)
D, [2024-08-29T17:34:22.146929 #38268] DEBUG -- : (2.8ms) CREATE TABLE "payments" ("id" bigserial primary key, "amount" float(24))
-> 0.0187s
== CreatePaymentWithFloatColumn: migrated (0.0187s) ==========================
F
Finished in 0.036045s, 27.7431 runs/s, 83.2293 assertions/s.
1) Failure:
BugTest#test_migration_up [migration_test.rb:50]:
Expected "t.float \"amount\", limit: 24" to include "# This file is auto-generated from the current state of the database. Instead\n# of editing this file, please use the migrations feature of Active Record to\n# incrementally modify your database, and then regenerate this schema definition.\n#\n# This file is the source Rails uses to define your schema when running `bin/rails\n# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to\n# be faster and is potentially less error prone than running all of your\n# migrations from scratch. Old migrations may fail to apply correctly if those\n# migrations use external dependencies or application code.\n#\n# It's strongly recommended that you check this file into your version control system.\n\nActiveRecord::Schema[7.2].define(version: 0) do\n # These are extensions that must be enabled in order to support this database\n enable_extension \"plpgsql\"\n\n create_table \"payments\", force: :cascade do |t|\n t.float \"amount\"\n end\nend\n".
1 runs, 3 assertions, 1 failures, 0 errors, 0 skips
Expected behavior
A real
column defined in a PostgreSQL schema should be preserved as a real
column when dumped and loaded.
see: https://www.postgresql.org/docs/14/datatype-numeric.html#DATATYPE-FLOAT
PostgreSQL also supports the SQL-standard notations float and float(p) for specifying inexact numeric types. Here, p specifies the minimum acceptable precision in binary digits. PostgreSQL accepts float(1) to float(24) as selecting the real type, while float(25) to float(53) select double precision. Values of p outside the allowed range draw an error. float with no precision specified is taken to mean double precision.
Actual behavior
The current behavior results in a conversion from real
to double precision
during the dump and load process.
System configuration
Rails version: 7.1.4
Ruby version: 3.3.4
PostgreSQL version: 14.7