Add setting for enumerating column names in SELECT statements#41718
Add setting for enumerating column names in SELECT statements#41718rafaelfranca merged 1 commit intorails:mainfrom
Conversation
|
This makes sense to me. Just a small comment that we should use |
7cfeef4 to
28db742
Compare
28db742 to
b3ea8aa
Compare
b3ea8aa to
726abea
Compare
|
This is a brilliant addition to finally and cleanly deal with a real world pain, which anyone working on a highly transactional system deals with regularly. Cheers. 👍 |
|
It would be awesome if this got back ported to rails 6.1. |
|
|
||
| * `config.active_record.queues.destroy` allows specifying the Active Job queue to use for destroy jobs. When this option is `nil`, purge jobs are sent to the default Active Job queue (see `config.active_job.default_queue_name`). It defaults to `nil`. | ||
|
|
||
| * `config.active_record.enumerate_columns_in_select_statements` when truthy, will always include column names in `SELECT` statements, and avoid wildcard `SELECT * FROM ...` queries. This avoids prepared statement cache errors when adding columns to a Postgres database. Defaults to `false`. |
There was a problem hiding this comment.
Just curious, but why does it default to false? Is there any drawback to enumerating the columns instead of using *?
There was a problem hiding this comment.
As far as I know there's no drawback, but it's off by default to guarantee backwards compatibility by maintaining existing behavior.
There was a problem hiding this comment.
One small drawback is that the query logs will be bigger/more verbose when showing the SQL generated by ActiveRecord.
|
I took a look at the Rails backporting policy and would be curious to know if this feature could be backported to Rails 6 🙇🏽♂️
While this seems like a feature, I feel like this is a bug, considering that it's taken down high traffic Rails applications. For us it's shot developers in the foot when running migrations that touch a table with a query in a transaction. As a result we've had to do multiple force deploys, but that seems like a workaround as opposed to this PR. |
It's a one line change in |
Summary
Add a new configuration setting
ActiveRecord::Base.enumerate_columns_in_select_statements. When truthy, ActiveRecord will explicitly project all column names inSELECTstatements, rather than a wildcardtable_name.*.E.g.
SELECT * FROM postsbecomesSELECT id, title, body, created_at, updated_at FROM postsOther Information
When a column is added to a Postgres table, it changes the query result for any wildcard SELECTs. This causes
PreparedStatementCacheExpirederrors when the statement occurs inside a transaction. #22170 cleans up the statement cache, but the error is still raised and will fail the transaction, and probably cause a 500 error, failed background job, etc.I've seen a few different recommendations on how to handle these:
ignored_columnsThe last option above works because setting any value for
ignored_columnstriggers the code path to project all column names instead of a wildcard, and this is what we're currently using in production.However, this feels hacky, and isn't how
ignored_columnsis supposed to be used. Adding an option to enable this behavior all the time seems cleaner, and makes it easier to opt-in on a per-model, or per-environment basis.If the code looks good and is agreeable to everyone, I'll make sure to update the docs and add a changelog entry as well.