Skip to content

Commit cfd3f86

Browse files
committed
Remove direct support for :text in lieu of :varchar(8000). Now using #extract_limit vs. limitable? hack. The #type_to_sql method is now much more like PostgreSQL adapter.
1 parent e24750e commit cfd3f86

File tree

3 files changed

+35
-26
lines changed

3 files changed

+35
-26
lines changed

lib/active_record/connection_adapters/sqlserver_adapter.rb

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ class SQLServerColumn < Column #:nodoc:
118118
def initialize(name, default, sql_type = nil, null = true, sqlserver_options = {})
119119
super(name, default, sql_type, null)
120120
@sqlserver_options = sqlserver_options
121-
@limit = nil unless limitable?
122121
end
123122

124123
def is_identity?
@@ -205,10 +204,13 @@ def new_time(year, mon, mday, hour, min, sec, microsec = 0)
205204

206205
private
207206

208-
def limitable?
209-
# SQL Server only supports limits on *char and float types. Although for schema dumping purposes
210-
# it is useful to know what others are like bigint and smallint. So we trump #extract_limit.
211-
[:float,:string].include?(type) || (type == :integer && sql_type =~ /^(big|small)int/i)
207+
def extract_limit(sql_type)
208+
case sql_type
209+
when /^smallint/i then 2
210+
when /^int/i then 4
211+
when /^bigint/i then 8
212+
else super
213+
end
212214
end
213215

214216
def simplified_type(field_type)
@@ -271,6 +273,15 @@ class SQLServerAdapter < AbstractAdapter
271273
ADAPTER_NAME = 'SQLServer'.freeze
272274
DATABASE_VERSION_REGEXP = /Microsoft SQL Server\s+(\d{4})/
273275
SUPPORTED_VERSIONS = [2000,2005].freeze
276+
LIMITABLE_TYPES = [:string,:integer,:float].freeze
277+
278+
class << self
279+
280+
def type_limitable?(type)
281+
LIMITABLE_TYPES.include?(type.to_sym)
282+
end
283+
284+
end
274285

275286
def initialize(connection, logger, connection_options=nil)
276287
super(connection, logger)
@@ -464,20 +475,20 @@ def empty_insert_statement(table_name)
464475
# SCHEMA STATEMENTS ========================================#
465476

466477
def native_database_types
467-
txt = sqlserver_2005? ? "varchar(max)" : "text"
468-
bin = sqlserver_2005? ? "varbinary(max)" : "image"
478+
text = sqlserver_2005? ? "varchar(max)" : "varchar(8000)"
479+
binary = sqlserver_2005? ? "varbinary(max)" : "image"
469480
{
470481
:primary_key => "int NOT NULL IDENTITY(1, 1) PRIMARY KEY",
471482
:string => { :name => "varchar", :limit => 255 },
472-
:text => { :name => txt },
473-
:integer => { :name => "int" },
483+
:text => { :name => text },
484+
:integer => { :name => "int", :limit => 4 },
474485
:float => { :name => "float", :limit => 8 },
475486
:decimal => { :name => "decimal" },
476487
:datetime => { :name => "datetime" },
477488
:timestamp => { :name => "datetime" },
478489
:time => { :name => "datetime" },
479490
:date => { :name => "datetime" },
480-
:binary => { :name => bin },
491+
:binary => { :name => binary },
481492
:boolean => { :name => "bit"}
482493
}
483494
end
@@ -589,19 +600,16 @@ def add_order_by_for_association_limiting!(sql, options)
589600
end
590601

591602
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
592-
# Remove limit for data types which do not require it
593-
# Valid: ALTER TABLE sessions ALTER COLUMN [data] varchar(max)
594-
# Invalid: ALTER TABLE sessions ALTER COLUMN [data] varchar(max)(16777215)
595-
limit = nil if %w{text varchar(max) nvarchar(max) ntext varbinary(max) image}.include?(native_database_types[type.to_sym][:name])
596-
return super unless type.to_s == 'integer'
597-
if limit.nil?
598-
'integer'
599-
elsif limit > 4
600-
'bigint'
601-
elsif limit < 3
602-
'smallint'
603+
limit = nil unless self.class.type_limitable?(type)
604+
if type.to_s == 'integer'
605+
case limit
606+
when 1..2 then 'smallint'
607+
when 3..4, nil then 'integer'
608+
when 5..8 then 'bigint'
609+
else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.")
610+
end
603611
else
604-
'integer'
612+
super
605613
end
606614
end
607615

test/cases/adapter_test_sqlserver.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ def setup
196196
context 'For SchemaStatements' do
197197

198198
context 'returning from #type_to_sql' do
199-
199+
200200
should 'create integers when no limit supplied' do
201201
assert_equal 'integer', @connection.type_to_sql(:integer)
202202
end

test/cases/schema_dumper_test_sqlserver.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
require 'cases/sqlserver_helper'
22

3-
# NOTE: The existing schema_dumper_test doesn't test the limits of <4 limit things
4-
# for adapaters that aren't mysql, sqlite or postgres. We should. It also only tests
5-
# non-standard id dumping for mysql. We'll do that too.
63
class SchemaDumperTestSqlserver < ActiveRecord::TestCase
74

85
context 'In schema dump' do
@@ -15,6 +12,10 @@ class SchemaDumperTestSqlserver < ActiveRecord::TestCase
1512
assert_match %r{c_int_4.*}, output
1613
assert_no_match %r{c_int_3.*:limit}, output
1714
assert_no_match %r{c_int_4.*:limit}, output
15+
assert_match %r{c_int_5.*:limit => 8}, output
16+
assert_match %r{c_int_6.*:limit => 8}, output
17+
assert_match %r{c_int_7.*:limit => 8}, output
18+
assert_match %r{c_int_8.*:limit => 8}, output
1819
end
1920

2021
should 'honor nonstandard primary keys' do

0 commit comments

Comments
 (0)