New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Don't skip some columns in column_types
on Postgres
#42933
Conversation
1df9439
to
a8e51c6
Compare
a8e51c6
to
2afda52
Compare
expected = if current_adapter?(:PostgreSQLAdapter) | ||
# Postgres returns the same name for each column in the given query, so each column is named "coalesce" | ||
# As a result Rails cannot accurately type cast each value. | ||
# To work around this, you should use aliases in your select statement (see test_pluck_functions_with_alias). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit yucky, but it only happens in very specific cases: if you have select two (or more) columns that don't have an alias and use the same SQL function (eg COALESCE). This happens because of how Postgres returns column names, see #36186 (comment) for a summary.
As far as I can tell we have a few options:
- The current state, which results in this bug: ActiveRecord::Result#column_types is often missing data #41651
- This PR, which fixes ActiveRecord::Result#column_types is often missing data #41651 but introduces this inconsistency between databases.
- Implement the refactor in Avoid coercing all SELECTs with the same column name to the same value #36186, which adds a fair bit of overhead to every query for a relatively niche issue.
In my opinion this PR is the least bad option.
2afda52
to
05c7090
Compare
Fixes rails#41651, by partially reverting rails#39097 I ran the same benchmark as rails#39097 and it seems like this change does not cause a perf regression. ```ruby require "bundler/inline" gemfile(true) do source "https://rubygems.org" git_source(:github) { |repo| "https://github.com/#{repo}.git" } gem "rails", path: "/Users/alex/code/rails" # github: "rails/rails", branch: "main" gem "sqlite3" gem "benchmark-ips" end require "active_record" ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") ActiveRecord::Schema.define do create_table :active_storage_blobs do |t| t.string :key, null: false t.string :filename, null: false t.string :content_type t.text :metadata t.string :service_name, null: false t.bigint :byte_size, null: false t.string :checksum, null: false t.datetime :created_at, null: false t.index [ :key ], unique: true end end class ActiveStorageBlob < ActiveRecord::Base end Benchmark.ips do |x| x.report("find_by") { ActiveStorageBlob.find_by(id: 1) } end ``` This branch: ``` Warming up -------------------------------------- find_by 1.940k i/100ms Calculating ------------------------------------- find_by 17.928k (± 4.8%) i/s - 91.180k in 5.098301s ``` Main: ``` Warming up -------------------------------------- find_by 1.912k i/100ms Calculating ------------------------------------- find_by 17.961k (± 4.8%) i/s - 89.864k in 5.015252s ```
05c7090
to
587522e
Compare
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
Don't skip some columns in `column_types` on Postgres
Fixes #41651, by partially reverting #39097. I just reverted the line that @terracatta highlighted as problematic.
I ran the same benchmark as #39097 and it seems like this change does not cause a perf regression.
This branch:
Main:
So it's basically the same. cc @terracatta @boblail