Skip to content

Commit 15b1d2b

Browse files
authored
[Rails 7] Define adapter type maps statically (#968)
1 parent 91103fa commit 15b1d2b

File tree

3 files changed

+86
-77
lines changed

3 files changed

+86
-77
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#### Changed
88

9+
- [#968](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/968) Define adapter type maps statically
910
- [#983](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/983) Optimize remove_columns to use a single SQL statement
1011
- [#984](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/984) Better handle SQL queries with invalid encoding
1112
- [#988](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/988) Raise `ActiveRecord::StatementInvalid` when `columns` is called with a non-existing table (***breaking change***)

lib/active_record/connection_adapters/sqlserver_adapter.rb

Lines changed: 83 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -377,83 +377,93 @@ def get_database_version # :nodoc:
377377
version_year
378378
end
379379

380-
protected
381-
382-
# === Abstract Adapter (Misc Support) =========================== #
383-
384-
def initialize_type_map(m = type_map)
385-
m.register_type %r{.*}, SQLServer::Type::UnicodeString.new
386-
387-
# Exact Numerics
388-
register_class_with_limit m, "bigint(8)", SQLServer::Type::BigInteger
389-
m.alias_type "bigint", "bigint(8)"
390-
register_class_with_limit m, "int(4)", SQLServer::Type::Integer
391-
m.alias_type "integer", "int(4)"
392-
m.alias_type "int", "int(4)"
393-
register_class_with_limit m, "smallint(2)", SQLServer::Type::SmallInteger
394-
m.alias_type "smallint", "smallint(2)"
395-
register_class_with_limit m, "tinyint(1)", SQLServer::Type::TinyInteger
396-
m.alias_type "tinyint", "tinyint(1)"
397-
m.register_type "bit", SQLServer::Type::Boolean.new
398-
m.register_type %r{\Adecimal}i do |sql_type|
399-
scale = extract_scale(sql_type)
400-
precision = extract_precision(sql_type)
401-
if scale == 0
402-
SQLServer::Type::DecimalWithoutScale.new(precision: precision)
403-
else
404-
SQLServer::Type::Decimal.new(precision: precision, scale: scale)
380+
class << self
381+
protected
382+
383+
def initialize_type_map(m)
384+
m.register_type %r{.*}, SQLServer::Type::UnicodeString.new
385+
386+
# Exact Numerics
387+
register_class_with_limit m, "bigint(8)", SQLServer::Type::BigInteger
388+
m.alias_type "bigint", "bigint(8)"
389+
register_class_with_limit m, "int(4)", SQLServer::Type::Integer
390+
m.alias_type "integer", "int(4)"
391+
m.alias_type "int", "int(4)"
392+
register_class_with_limit m, "smallint(2)", SQLServer::Type::SmallInteger
393+
m.alias_type "smallint", "smallint(2)"
394+
register_class_with_limit m, "tinyint(1)", SQLServer::Type::TinyInteger
395+
m.alias_type "tinyint", "tinyint(1)"
396+
m.register_type "bit", SQLServer::Type::Boolean.new
397+
m.register_type %r{\Adecimal}i do |sql_type|
398+
scale = extract_scale(sql_type)
399+
precision = extract_precision(sql_type)
400+
if scale == 0
401+
SQLServer::Type::DecimalWithoutScale.new(precision: precision)
402+
else
403+
SQLServer::Type::Decimal.new(precision: precision, scale: scale)
404+
end
405405
end
406-
end
407-
m.alias_type %r{\Anumeric}i, "decimal"
408-
m.register_type "money", SQLServer::Type::Money.new
409-
m.register_type "smallmoney", SQLServer::Type::SmallMoney.new
410-
411-
# Approximate Numerics
412-
m.register_type "float", SQLServer::Type::Float.new
413-
m.register_type "real", SQLServer::Type::Real.new
414-
415-
# Date and Time
416-
m.register_type "date", SQLServer::Type::Date.new
417-
m.register_type %r{\Adatetime} do |sql_type|
418-
precision = extract_precision(sql_type)
419-
if precision
420-
SQLServer::Type::DateTime2.new precision: precision
421-
else
422-
SQLServer::Type::DateTime.new
406+
m.alias_type %r{\Anumeric}i, "decimal"
407+
m.register_type "money", SQLServer::Type::Money.new
408+
m.register_type "smallmoney", SQLServer::Type::SmallMoney.new
409+
410+
# Approximate Numerics
411+
m.register_type "float", SQLServer::Type::Float.new
412+
m.register_type "real", SQLServer::Type::Real.new
413+
414+
# Date and Time
415+
m.register_type "date", SQLServer::Type::Date.new
416+
m.register_type %r{\Adatetime} do |sql_type|
417+
precision = extract_precision(sql_type)
418+
if precision
419+
SQLServer::Type::DateTime2.new precision: precision
420+
else
421+
SQLServer::Type::DateTime.new
422+
end
423423
end
424+
m.register_type %r{\Adatetimeoffset}i do |sql_type|
425+
precision = extract_precision(sql_type)
426+
SQLServer::Type::DateTimeOffset.new precision: precision
427+
end
428+
m.register_type "smalldatetime", SQLServer::Type::SmallDateTime.new
429+
m.register_type %r{\Atime}i do |sql_type|
430+
precision = extract_precision(sql_type) || DEFAULT_TIME_PRECISION
431+
SQLServer::Type::Time.new precision: precision
432+
end
433+
434+
# Character Strings
435+
register_class_with_limit m, %r{\Achar}i, SQLServer::Type::Char
436+
register_class_with_limit m, %r{\Avarchar}i, SQLServer::Type::Varchar
437+
m.register_type "varchar(max)", SQLServer::Type::VarcharMax.new
438+
m.register_type "text", SQLServer::Type::Text.new
439+
440+
# Unicode Character Strings
441+
register_class_with_limit m, %r{\Anchar}i, SQLServer::Type::UnicodeChar
442+
register_class_with_limit m, %r{\Anvarchar}i, SQLServer::Type::UnicodeVarchar
443+
m.alias_type "string", "nvarchar(4000)"
444+
m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
445+
m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
446+
m.register_type "ntext", SQLServer::Type::UnicodeText.new
447+
448+
# Binary Strings
449+
register_class_with_limit m, %r{\Abinary}i, SQLServer::Type::Binary
450+
register_class_with_limit m, %r{\Avarbinary}i, SQLServer::Type::Varbinary
451+
m.register_type "varbinary(max)", SQLServer::Type::VarbinaryMax.new
452+
453+
# Other Data Types
454+
m.register_type "uniqueidentifier", SQLServer::Type::Uuid.new
455+
m.register_type "timestamp", SQLServer::Type::Timestamp.new
424456
end
425-
m.register_type %r{\Adatetimeoffset}i do |sql_type|
426-
precision = extract_precision(sql_type)
427-
SQLServer::Type::DateTimeOffset.new precision: precision
428-
end
429-
m.register_type "smalldatetime", SQLServer::Type::SmallDateTime.new
430-
m.register_type %r{\Atime}i do |sql_type|
431-
precision = extract_precision(sql_type) || DEFAULT_TIME_PRECISION
432-
SQLServer::Type::Time.new precision: precision
433-
end
457+
end
458+
459+
TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
460+
461+
protected
462+
463+
# === Abstract Adapter (Misc Support) =========================== #
434464

435-
# Character Strings
436-
register_class_with_limit m, %r{\Achar}i, SQLServer::Type::Char
437-
register_class_with_limit m, %r{\Avarchar}i, SQLServer::Type::Varchar
438-
m.register_type "varchar(max)", SQLServer::Type::VarcharMax.new
439-
m.register_type "text", SQLServer::Type::Text.new
440-
441-
# Unicode Character Strings
442-
register_class_with_limit m, %r{\Anchar}i, SQLServer::Type::UnicodeChar
443-
register_class_with_limit m, %r{\Anvarchar}i, SQLServer::Type::UnicodeVarchar
444-
m.alias_type "string", "nvarchar(4000)"
445-
m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
446-
m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
447-
m.register_type "ntext", SQLServer::Type::UnicodeText.new
448-
449-
# Binary Strings
450-
register_class_with_limit m, %r{\Abinary}i, SQLServer::Type::Binary
451-
register_class_with_limit m, %r{\Avarbinary}i, SQLServer::Type::Varbinary
452-
m.register_type "varbinary(max)", SQLServer::Type::VarbinaryMax.new
453-
454-
# Other Data Types
455-
m.register_type "uniqueidentifier", SQLServer::Type::Uuid.new
456-
m.register_type "timestamp", SQLServer::Type::Timestamp.new
465+
def type_map
466+
TYPE_MAP
457467
end
458468

459469
def translate_exception(e, message:, sql:, binds:)

test/cases/coerced_tests.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,7 +1161,8 @@ def test_cache_does_not_wrap_results_in_arrays_coerced
11611161
end
11621162
end
11631163

1164-
# Same as original test except that we expect one query to be performed to retrieve the table's primary key.
1164+
# Same as original test except that we expect one query to be performed to retrieve the table's primary key
1165+
# and we don't call `reload_type_map` because SQL Server adapter doesn't support it.
11651166
# When we generate the SQL for the `find` it includes ordering on the primary key. If we reset the column
11661167
# information then the primary key needs to be retrieved from the database again to generate the SQL causing the
11671168
# original test's `assert_no_queries` assertion to fail. Assert that the query was to get the primary key.
@@ -1171,9 +1172,6 @@ def test_query_cached_even_when_types_are_reset_coerced
11711172
# Warm the cache
11721173
Task.find(1)
11731174

1174-
# Preload the type cache again (so we don't have those queries issued during our assertions)
1175-
Task.connection.send(:reload_type_map)
1176-
11771175
# Clear places where type information is cached
11781176
Task.reset_column_information
11791177
Task.initialize_find_by_cache

0 commit comments

Comments
 (0)