mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #29699 from lugray/represent_boolean_as_integer
Change sqlite3 boolean serialization to use 1 and 0
This commit is contained in:
commit
58f10a31b3
12 changed files with 148 additions and 8 deletions
|
@ -1,3 +1,14 @@
|
|||
* Change sqlite3 boolean serialization to use 1 and 0
|
||||
|
||||
SQLite natively recognizes 1 and 0 as true and false, but does not natively
|
||||
recognize 't' and 'f' as was previously serialized.
|
||||
|
||||
This change in serialization requires a migration of stored boolean data
|
||||
for SQLite databases, so it's implemented behind a configuration flag
|
||||
whose default false value is deprecated.
|
||||
|
||||
*Lisa Ugray*
|
||||
|
||||
* Skip query caching when working with batches of records (`find_each`, `find_in_batches`,
|
||||
`in_batches`).
|
||||
|
||||
|
|
|
@ -106,19 +106,19 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def quoted_true
|
||||
"'t'".freeze
|
||||
"TRUE".freeze
|
||||
end
|
||||
|
||||
def unquoted_true
|
||||
"t".freeze
|
||||
true
|
||||
end
|
||||
|
||||
def quoted_false
|
||||
"'f'".freeze
|
||||
"FALSE".freeze
|
||||
end
|
||||
|
||||
def unquoted_false
|
||||
"f".freeze
|
||||
false
|
||||
end
|
||||
|
||||
# Quote date/time values for use in SQL input. Includes microseconds
|
||||
|
|
|
@ -22,6 +22,22 @@ module ActiveRecord
|
|||
"x'#{value.hex}'"
|
||||
end
|
||||
|
||||
def quoted_true
|
||||
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? "1".freeze : "'t'".freeze
|
||||
end
|
||||
|
||||
def unquoted_true
|
||||
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? 1 : "t".freeze
|
||||
end
|
||||
|
||||
def quoted_false
|
||||
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? "0".freeze : "'f'".freeze
|
||||
end
|
||||
|
||||
def unquoted_false
|
||||
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? 0 : "f".freeze
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _type_cast(value)
|
||||
|
|
|
@ -72,6 +72,23 @@ module ActiveRecord
|
|||
boolean: { name: "boolean" }
|
||||
}
|
||||
|
||||
##
|
||||
# :singleton-method:
|
||||
# Indicates whether boolean values are stored in sqlite3 databases as 1
|
||||
# and 0 or 't' and 'f'. Leaving `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
|
||||
# set to false is deprecated. SQLite databases have used 't' and 'f' to
|
||||
# serialize boolean values and must have old data converted to 1 and 0
|
||||
# (its native boolean serialization) before setting this flag to true.
|
||||
# Conversion can be accomplished by setting up a rake task which runs
|
||||
#
|
||||
# ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
|
||||
# ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 0)
|
||||
# for all models and all boolean columns, after which the flag must be set
|
||||
# to true by adding the following to your application.rb file:
|
||||
#
|
||||
# ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true
|
||||
class_attribute :represent_boolean_as_integer, default: false
|
||||
|
||||
class StatementPool < ConnectionAdapters::StatementPool
|
||||
private
|
||||
|
||||
|
@ -512,5 +529,6 @@ module ActiveRecord
|
|||
execute("PRAGMA foreign_keys = ON", "SCHEMA")
|
||||
end
|
||||
end
|
||||
ActiveSupport.run_load_hooks(:active_record_sqlite3adapter, SQLite3Adapter)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -174,5 +174,29 @@ end_warning
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
initializer "active_record.check_represent_sqlite3_boolean_as_integer" do
|
||||
config.after_initialize do
|
||||
ActiveSupport.on_load(:active_record_sqlite3adapter) do
|
||||
unless ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
|
||||
ActiveSupport::Deprecation.warn <<-MSG
|
||||
Leaving `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
|
||||
set to false is deprecated. SQLite databases have used 't' and 'f' to serialize
|
||||
boolean values and must have old data converted to 1 and 0 (its native boolean
|
||||
serialization) before setting this flag to true. Conversion can be accomplished
|
||||
by setting up a rake task which runs
|
||||
|
||||
ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
|
||||
ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 0)
|
||||
|
||||
for all models and all boolean columns, after which the flag must be set to
|
||||
true by adding the following to your application.rb file:
|
||||
|
||||
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true
|
||||
MSG
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,11 +9,11 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def test_type_cast_true
|
||||
assert_equal "t", @conn.type_cast(true)
|
||||
assert_equal true, @conn.type_cast(true)
|
||||
end
|
||||
|
||||
def test_type_cast_false
|
||||
assert_equal "f", @conn.type_cast(false)
|
||||
assert_equal false, @conn.type_cast(false)
|
||||
end
|
||||
|
||||
def test_quote_float_nan
|
||||
|
|
|
@ -5,6 +5,11 @@ require "securerandom"
|
|||
class SQLite3QuotingTest < ActiveRecord::SQLite3TestCase
|
||||
def setup
|
||||
@conn = ActiveRecord::Base.connection
|
||||
@initial_represent_boolean_as_integer = ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
|
||||
end
|
||||
|
||||
def teardown
|
||||
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = @initial_represent_boolean_as_integer
|
||||
end
|
||||
|
||||
def test_type_cast_binary_encoding_without_logger
|
||||
|
@ -15,11 +20,19 @@ class SQLite3QuotingTest < ActiveRecord::SQLite3TestCase
|
|||
end
|
||||
|
||||
def test_type_cast_true
|
||||
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = false
|
||||
assert_equal "t", @conn.type_cast(true)
|
||||
|
||||
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true
|
||||
assert_equal 1, @conn.type_cast(true)
|
||||
end
|
||||
|
||||
def test_type_cast_false
|
||||
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = false
|
||||
assert_equal "f", @conn.type_cast(false)
|
||||
|
||||
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true
|
||||
assert_equal 0, @conn.type_cast(false)
|
||||
end
|
||||
|
||||
def test_type_cast_bigdecimal
|
||||
|
|
|
@ -8,11 +8,11 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def test_quoted_true
|
||||
assert_equal "'t'", @quoter.quoted_true
|
||||
assert_equal "TRUE", @quoter.quoted_true
|
||||
end
|
||||
|
||||
def test_quoted_false
|
||||
assert_equal "'f'", @quoter.quoted_false
|
||||
assert_equal "FALSE", @quoter.quoted_false
|
||||
end
|
||||
|
||||
def test_quote_column_name
|
||||
|
|
|
@ -375,6 +375,28 @@ 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`.
|
||||
|
||||
The SQLite3Adapter adapter adds one additional configuration option:
|
||||
|
||||
* `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
|
||||
indicates whether boolean values are stored in sqlite3 databases as 1 and 0 or
|
||||
't' and 'f'. Leaving `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
|
||||
set to false is deprecated. SQLite databases have used 't' and 'f' to serialize
|
||||
boolean values and must have old data converted to 1 and 0 (its native boolean
|
||||
serialization) before setting this flag to true. Conversion can be accomplished
|
||||
by setting up a rake task which runs
|
||||
|
||||
```ruby
|
||||
ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
|
||||
ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 0)
|
||||
```
|
||||
|
||||
for all models and all boolean columns, after which the flag must be set to true
|
||||
by adding the following to your application.rb file:
|
||||
|
||||
```ruby
|
||||
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true
|
||||
```
|
||||
|
||||
The schema dumper adds one additional configuration option:
|
||||
|
||||
* `ActiveRecord::SchemaDumper.ignore_tables` accepts an array of tables that should _not_ be included in any generated schema file. This setting is ignored unless `config.active_record.schema_format == :ruby`.
|
||||
|
|
|
@ -86,6 +86,10 @@ module Rails
|
|||
|
||||
if respond_to?(:active_record)
|
||||
active_record.cache_versioning = true
|
||||
# Remove the temporary load hook from SQLite3Adapter when this is removed
|
||||
ActiveSupport.on_load(:active_record_sqlite3adapter) do
|
||||
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true
|
||||
end
|
||||
end
|
||||
|
||||
if respond_to?(:action_dispatch)
|
||||
|
|
|
@ -21,3 +21,7 @@
|
|||
# Add default protection from forgery to ActionController::Base instead of in
|
||||
# ApplicationController.
|
||||
# Rails.application.config.action_controller.default_protect_from_forgery = true
|
||||
|
||||
# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and
|
||||
# 'f' after migrating old data.
|
||||
# ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true
|
||||
|
|
|
@ -1585,6 +1585,34 @@ module ApplicationTests
|
|||
assert_equal({}, Rails.application.config.my_custom_config)
|
||||
end
|
||||
|
||||
test "default SQLite3Adapter.represent_boolean_as_integer for 5.1 is false" do
|
||||
remove_from_config '.*config\.load_defaults.*\n'
|
||||
add_to_top_of_config <<-RUBY
|
||||
config.load_defaults 5.1
|
||||
RUBY
|
||||
app_file "app/models/post.rb", <<-RUBY
|
||||
class Post < ActiveRecord::Base
|
||||
end
|
||||
RUBY
|
||||
|
||||
app "development"
|
||||
Post.object_id # force lazy load hooks to run
|
||||
|
||||
assert_not ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
|
||||
end
|
||||
|
||||
test "default SQLite3Adapter.represent_boolean_as_integer for new installs is true" do
|
||||
app_file "app/models/post.rb", <<-RUBY
|
||||
class Post < ActiveRecord::Base
|
||||
end
|
||||
RUBY
|
||||
|
||||
app "development"
|
||||
Post.object_id # force lazy load hooks to run
|
||||
|
||||
assert ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
|
||||
end
|
||||
|
||||
test "config_for containing ERB tags should evaluate" do
|
||||
app_file "config/custom.yml", <<-RUBY
|
||||
development:
|
||||
|
|
Loading…
Reference in a new issue