Clean up docs and code using mysql2

This PR does the following:

* Adds `trilogy` to lists of adapters where applicable
* Uses `MySQL` instead of adatper names where applicable
* Splits type information into adapters code so that the adapter is set
correctly.
* Fix tests that were using mysql2 when they should be abstract
* Add load hook for trilogy to match mysql2
This commit is contained in:
eileencodes 2023-05-08 13:17:37 -04:00
parent b8dc6cd444
commit 74898d9b54
No known key found for this signature in database
GPG Key ID: BA5C575120BBE8DF
12 changed files with 70 additions and 28 deletions

View File

@ -322,7 +322,7 @@ module ActiveRecord
# * You are joining an existing open transaction
# * You are creating a nested (savepoint) transaction
#
# The mysql2 and postgresql adapters support setting the transaction
# The mysql2, trilogy, and postgresql adapters support setting the transaction
# isolation level.
# :args: (requires_new: nil, isolation: nil, &block)
def transaction(requires_new: nil, isolation: nil, joinable: true, &block)

View File

@ -102,7 +102,7 @@ module ActiveRecord
# Override to return the quoted table name for assignment. Defaults to
# table quoting.
#
# This works for mysql2 where table.column can be used to
# This works for MySQL where table.column can be used to
# resolve ambiguity.
#
# We override this in the sqlite3 and postgresql adapters to use only

View File

@ -656,11 +656,6 @@ module ActiveRecord
def initialize_type_map(m)
super
m.register_type(%r(char)i) do |sql_type|
limit = extract_limit(sql_type)
Type.lookup(:string, adapter: :mysql2, limit: limit)
end
m.register_type %r(tinytext)i, Type::Text.new(limit: 2**8 - 1)
m.register_type %r(tinyblob)i, Type::Binary.new(limit: 2**8 - 1)
m.register_type %r(text)i, Type::Text.new(limit: 2**16 - 1)
@ -680,9 +675,6 @@ module ActiveRecord
m.alias_type %r(year)i, "integer"
m.alias_type %r(bit)i, "binary"
m.register_type %r(^enum)i, Type.lookup(:string, adapter: :mysql2)
m.register_type %r(^set)i, Type.lookup(:string, adapter: :mysql2)
end
def register_integer_type(mapping, key, **options)
@ -704,7 +696,6 @@ module ActiveRecord
end
end
TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
EXTENDED_TYPE_MAPS = Concurrent::Map.new
EMULATE_BOOLEANS_TRUE = { emulate_booleans: true }.freeze
@ -715,10 +706,6 @@ module ActiveRecord
expression
end
def text_type?(type)
TYPE_MAP.lookup(type).is_a?(Type::String) || TYPE_MAP.lookup(type).is_a?(Type::Text)
end
def extended_type_map_key
if @default_timezone
{ default_timezone: @default_timezone, emulate_booleans: emulate_booleans }
@ -975,14 +962,6 @@ module ActiveRecord
def version_string(full_version_string)
full_version_string.match(/^(?:5\.5\.5-)?(\d+\.\d+\.\d+)/)[1]
end
ActiveRecord::Type.register(:immutable_string, adapter: :mysql2) do |_, **args|
Type::ImmutableString.new(true: "1", false: "0", **args)
end
ActiveRecord::Type.register(:string, adapter: :mysql2) do |_, **args|
Type::String.new(true: "1", false: "0", **args)
end
ActiveRecord::Type.register(:unsigned_integer, Type::UnsignedInteger, adapter: :mysql2)
end
end
end

View File

@ -63,7 +63,7 @@ module ActiveRecord
end
# Override +type_cast+ we pass to mysql2 Date and Time objects instead
# of Strings since mysql2 is able to handle those classes more efficiently.
# of Strings since MySQL adapters are able to handle those classes more efficiently.
def type_cast(value) # :nodoc:
case value
when ActiveSupport::TimeWithZone

View File

@ -44,8 +44,23 @@ module ActiveRecord
raise ActiveRecord::ConnectionNotEstablished, error.message
end
end
private
def initialize_type_map(m)
super
m.register_type(%r(char)i) do |sql_type|
limit = extract_limit(sql_type)
Type.lookup(:string, adapter: :mysql2, limit: limit)
end
m.register_type %r(^enum)i, Type.lookup(:string, adapter: :mysql2)
m.register_type %r(^set)i, Type.lookup(:string, adapter: :mysql2)
end
end
TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
def initialize(...)
super
@ -134,6 +149,10 @@ module ActiveRecord
end
private
def text_type?(type)
TYPE_MAP.lookup(type).is_a?(Type::String) || TYPE_MAP.lookup(type).is_a?(Type::Text)
end
def connect
@raw_connection = self.class.new_client(@connection_parameters)
end
@ -178,7 +197,18 @@ module ActiveRecord
MSG
false
end
ActiveRecord::Type.register(:immutable_string, adapter: :mysql2) do |_, **args|
Type::ImmutableString.new(true: "1", false: "0", **args)
end
ActiveRecord::Type.register(:string, adapter: :mysql2) do |_, **args|
Type::String.new(true: "1", false: "0", **args)
end
ActiveRecord::Type.register(:unsigned_integer, Type::UnsignedInteger, adapter: :mysql2)
end
ActiveSupport.run_load_hooks(:active_record_mysql2adapter, Mysql2Adapter)
end
end

View File

@ -66,7 +66,6 @@ module ActiveRecord
return mode if mode.is_a? Integer
m = mode.to_s.upcase
# enable Mysql2 client compatibility
m = "SSL_MODE_#{m}" unless m.start_with? "SSL_MODE_"
SSL_MODES.fetch(m.to_sym, mode)
@ -86,8 +85,23 @@ module ActiveRecord
end
end
end
private
def initialize_type_map(m)
super
m.register_type(%r(char)i) do |sql_type|
limit = extract_limit(sql_type)
Type.lookup(:string, adapter: :trilogy, limit: limit)
end
m.register_type %r(^enum)i, Type.lookup(:string, adapter: :trilogy)
m.register_type %r(^set)i, Type.lookup(:string, adapter: :trilogy)
end
end
TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
def supports_json?
!mariadb? && database_version >= "5.7.8"
end
@ -143,6 +157,10 @@ module ActiveRecord
end
private
def text_type?(type)
TYPE_MAP.lookup(type).is_a?(Type::String) || TYPE_MAP.lookup(type).is_a?(Type::Text)
end
def each_hash(result)
return to_enum(:each_hash, result) unless block_given?
@ -201,6 +219,18 @@ module ActiveRecord
def default_prepared_statements
false
end
ActiveRecord::Type.register(:immutable_string, adapter: :trilogy) do |_, **args|
Type::ImmutableString.new(true: "1", false: "0", **args)
end
ActiveRecord::Type.register(:string, adapter: :trilogy) do |_, **args|
Type::String.new(true: "1", false: "0", **args)
end
ActiveRecord::Type.register(:unsigned_integer, Type::UnsignedInteger, adapter: :trilogy)
end
ActiveSupport.run_load_hooks(:active_record_trilogyadapter, TrilogyAdapter)
end
end

View File

@ -453,7 +453,7 @@ module ActiveRecord
# * You are joining an existing open transaction
# * You are creating a nested (savepoint) transaction
#
# The mysql2 and postgresql adapters support setting the transaction isolation level.
# The mysql2, trilogy, and postgresql adapters support setting the transaction isolation level.
class TransactionIsolationError < ActiveRecordError
end

View File

@ -280,6 +280,7 @@ module ActiveRecord
# The following bundled adapters throw the ActiveRecord::RecordNotUnique exception:
#
# * ActiveRecord::ConnectionAdapters::Mysql2Adapter.
# * ActiveRecord::ConnectionAdapters::TrilogyAdapter.
# * ActiveRecord::ConnectionAdapters::SQLite3Adapter.
# * ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.
def validates_uniqueness_of(*attr_names)

View File

@ -106,7 +106,7 @@ module ActiveRecord
end
end
class Mysql2AnsiQuotesTest < ActiveRecord::Mysql2TestCase
class MysqlAnsiQuotesTest < ActiveRecord::AbstractMysqlTestCase
def setup
@connection = ActiveRecord::Base.connection
@connection.execute("SET SESSION sql_mode='ANSI_QUOTES'")

View File

@ -1436,7 +1436,7 @@ Defaults to `true`. Determines whether to raise an exception or not when
the PostgreSQL adapter is provided an integer that is wider than signed
64bit representation.
#### `ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans`
#### `ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans` and `ActiveRecord::ConnectionAdapters::TrilogyAdapter.emulate_booleans`
Controls whether the Active Record MySQL adapter will consider all `tinyint(1)` columns as booleans. Defaults to `true`.

View File

@ -458,6 +458,7 @@ You can now run the tests as you did for `sqlite3`. The tasks are respectively:
```bash
$ bundle exec rake test:mysql2
$ bundle exec rake test:trilogy
$ bundle exec rake test:postgresql
```

View File

@ -1497,6 +1497,7 @@ These are the load hooks you can use in your own code. To hook into the initiali
| `ActiveRecord::TestFixtures` | `active_record_fixtures` |
| `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter` | `active_record_postgresqladapter` |
| `ActiveRecord::ConnectionAdapters::Mysql2Adapter` | `active_record_mysql2adapter` |
| `ActiveRecord::ConnectionAdapters::TrilogyAdapter` | `active_record_trilogyadapter` |
| `ActiveRecord::ConnectionAdapters::SQLite3Adapter` | `active_record_sqlite3adapter` |
| `ActiveStorage::Attachment` | `active_storage_attachment` |
| `ActiveStorage::VariantRecord` | `active_storage_variant_record` |