Add setting for enumerating column names in SELECT statements
This commit is contained in:
parent
9e1cdf27eb
commit
726abeaab4
@ -1,3 +1,43 @@
|
||||
* Add setting for enumerating column names in SELECT statements.
|
||||
|
||||
Adding a column to a Postgres database while the application is running can
|
||||
change the result of wildcard `SELECT *` queries, which invalidates the result
|
||||
of cached prepared statements and raises a PreparedStatementCacheExpired error.
|
||||
|
||||
When truthy, ActiveRecord will avoid wildcards and always include column names
|
||||
in `SELECT` queries, which will return consistent results and avoid prepared
|
||||
statement errors.
|
||||
|
||||
Before:
|
||||
|
||||
```ruby
|
||||
Book.limit(5)
|
||||
# SELECT * FROM books LIMIT 5
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```ruby
|
||||
# config/application.rb
|
||||
module MyApp
|
||||
class Application < Rails::Application
|
||||
config.active_record.enumerate_columns_in_select_statements = true
|
||||
end
|
||||
end
|
||||
|
||||
# or, configure per-model
|
||||
class Book < ApplicationRecord
|
||||
self.enumerate_columns_in_select_statements = true
|
||||
end
|
||||
```
|
||||
|
||||
```ruby
|
||||
Book.limit(5)
|
||||
# SELECT id, author_id, name, format, status, language, etc FROM books LIMIT 5
|
||||
```
|
||||
|
||||
*Matt Duszynski*
|
||||
|
||||
* Only update dirty attributes once for cyclic autosave callbacks.
|
||||
|
||||
Instead of calling `changes_applied` everytime `save` is called,
|
||||
|
@ -129,6 +129,14 @@ def self.configurations
|
||||
# for multiple databases.
|
||||
mattr_accessor :suppress_multiple_database_warning, instance_writer: false, default: false
|
||||
|
||||
##
|
||||
# :singleton-method:
|
||||
# Force enumeration of all columns in SELECT statements
|
||||
# e.g. `SELECT first_name, last_name FROM ...` instead of `SELECT * FROM ...`
|
||||
# This avoids PreparedStatementCacheExpired errors when a column is added
|
||||
# to a Postgres database while the app is running.
|
||||
class_attribute :enumerate_columns_in_select_statements, instance_accessor: false, default: false
|
||||
|
||||
mattr_accessor :maintain_test_schema, instance_accessor: false
|
||||
|
||||
class_attribute :belongs_to_required_by_default, instance_accessor: false
|
||||
|
@ -1390,7 +1390,7 @@ def build_joins(join_sources, aliases = nil)
|
||||
def build_select(arel)
|
||||
if select_values.any?
|
||||
arel.project(*arel_columns(select_values))
|
||||
elsif klass.ignored_columns.any?
|
||||
elsif klass.ignored_columns.any? || klass.enumerate_columns_in_select_statements
|
||||
arel.project(*klass.column_names.map { |field| table[field] })
|
||||
else
|
||||
arel.project(table[Arel.star])
|
||||
|
@ -77,5 +77,15 @@ def test_star_select_with_joins_and_includes
|
||||
tags_count indestructible_tags_count tags_with_destroy_count tags_with_nullify_count
|
||||
), posts.first.attributes.keys
|
||||
end
|
||||
|
||||
def test_enumerate_columns_in_select_statements
|
||||
original_value = Post.enumerate_columns_in_select_statements
|
||||
Post.enumerate_columns_in_select_statements = true
|
||||
sql = Post.all.to_sql
|
||||
Post.column_names.each do |column_name|
|
||||
assert_includes sql, column_name
|
||||
end
|
||||
Post.enumerate_columns_in_select_statements = original_value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -473,6 +473,8 @@ in controllers and views. This defaults to `false`.
|
||||
|
||||
* `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`.
|
||||
|
||||
The MySQL adapter adds one additional configuration option:
|
||||
|
||||
* `ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans` controls whether Active Record will consider all `tinyint(1)` columns as booleans. Defaults to `true`.
|
||||
|
Loading…
Reference in New Issue
Block a user