@@ -54,10 +54,15 @@ module ConnectionAdapters
5454 class SQLServerColumn < Column # :nodoc:
5555 attr_reader :identity , :is_special
5656
57- def initialize ( name , default , sql_type = nil , identity = false , null = true ) # TODO: check ok to remove scale_value = 0
58- super ( name , default , sql_type , null )
59- @identity = identity
60- @is_special = sql_type =~ /text|ntext|image/i
57+ def initialize ( info )
58+ if info [ :type ] =~ /numeric|decimal/i
59+ type = "#{ info [ :type ] } (#{ info [ :numeric_precision ] } ,#{ info [ :numeric_scale ] } )"
60+ else
61+ type = "#{ info [ :type ] } (#{ info [ :length ] } )"
62+ end
63+ super ( info [ :name ] , info [ :default_value ] , type , info [ :is_nullable ] )
64+ @identity = info [ :is_identity ]
65+ @is_special = [ "text" , "ntext" , "image" ] . include? ( info [ :type ] )
6166 # TODO: check ok to remove @scale = scale_value
6267 # SQL Server only supports limits on *char and float types
6368 @limit = nil unless @type == :float or @type == :string
@@ -102,10 +107,9 @@ def cast_to_time(value)
102107 Time . time_with_datetime_fallback ( Base . default_timezone , *time_array ) rescue nil
103108 #Time.send(Base.default_timezone, *time_array) rescue nil
104109 end
105-
110+
106111 def cast_to_datetime ( value )
107112 return value . to_time if value . is_a? ( DBI ::Timestamp )
108-
109113 if value . is_a? ( Time )
110114 if value . year != 0 and value . month != 0 and value . day != 0
111115 return value
@@ -275,41 +279,52 @@ def select_rows(sql, name = nil)
275279
276280 def columns ( table_name , name = nil )
277281 return [ ] if table_name . blank?
278- table_name = table_name . to_s if table_name . is_a? ( Symbol )
279- table_name = table_name . split ( '.' ) [ -1 ] unless table_name . nil?
282+ table_name = table_name . to_s . split ( '.' ) [ -1 ]
280283 table_name = table_name . gsub ( /[\[ \] ]/ , '' )
281- sql = %Q {
284+ sql = %{
282285 SELECT
283- cols.COLUMN_NAME as ColName,
284- cols.COLUMN_DEFAULT as DefaultValue,
285- cols.NUMERIC_SCALE as numeric_scale,
286- cols.NUMERIC_PRECISION as numeric_precision,
287- cols.DATA_TYPE as ColType,
288- cols.IS_NULLABLE As IsNullable,
289- COL_LENGTH(cols.TABLE_NAME, cols.COLUMN_NAME) as Length,
290- COLUMNPROPERTY(OBJECT_ID(cols.TABLE_NAME), cols.COLUMN_NAME, 'IsIdentity') as IsIdentity,
291- cols.NUMERIC_SCALE as Scale
292- FROM INFORMATION_SCHEMA.COLUMNS cols
293- WHERE cols.TABLE_NAME = '#{ table_name } '
286+ columns.COLUMN_NAME as name,
287+ columns.DATA_TYPE as type,
288+ CASE
289+ WHEN columns.COLUMN_DEFAULT = '(null)' OR columns.COLUMN_DEFAULT = '(NULL)' THEN NULL
290+ ELSE columns.COLUMN_DEFAULT
291+ END default_value,
292+ columns.NUMERIC_SCALE as numeric_scale,
293+ columns.NUMERIC_PRECISION as numeric_precision,
294+ COL_LENGTH(columns.TABLE_NAME, columns.COLUMN_NAME) as length,
295+ CASE
296+ WHEN constraint_column_usage.constraint_name IS NULL THEN NULL
297+ ELSE 1
298+ END is_primary_key,
299+ CASE
300+ WHEN columns.IS_NULLABLE = 'YES' THEN 1
301+ ELSE NULL
302+ end is_nullable,
303+ CASE
304+ WHEN COLUMNPROPERTY(OBJECT_ID(columns.TABLE_NAME), columns.COLUMN_NAME, 'IsIdentity') = 0 THEN NULL
305+ ELSE 1
306+ END is_identity
307+ FROM INFORMATION_SCHEMA.COLUMNS columns
308+ LEFT OUTER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS primary_key_constraints ON (
309+ primary_key_constraints.table_name = columns.table_name
310+ AND primary_key_constraints.constraint_type = 'PRIMARY KEY'
311+ )
312+ LEFT OUTER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE constraint_column_usage ON (
313+ constraint_column_usage.table_name = primary_key_constraints.table_name
314+ AND constraint_column_usage.column_name = columns.column_name
315+ )
316+ WHERE columns.TABLE_NAME = '#{ table_name } '
317+ ORDER BY columns.ordinal_position
294318 }
295- # Comment out if you want to have the Columns select statment logged.
296- # Personally, I think it adds unnecessary bloat to the log.
297- # If you do comment it out, make sure to un-comment the "result" line that follows
298- result = log ( sql , name ) { @connection . select_all ( sql ) }
299- #result = @connection.select_all(sql)
300- columns = [ ]
301- result . each do |field |
302- default = field [ :DefaultValue ] . to_s . gsub! ( /[()\' ]/ , "" ) =~ /null/i ? nil : field [ :DefaultValue ]
303- if field [ :ColType ] =~ /numeric|decimal/i
304- type = "#{ field [ :ColType ] } (#{ field [ :numeric_precision ] } ,#{ field [ :numeric_scale ] } )"
305- else
306- type = "#{ field [ :ColType ] } (#{ field [ :Length ] } )"
307- end
308- is_identity = field [ :IsIdentity ] == 1
309- is_nullable = field [ :IsNullable ] == 'YES'
310- columns << SQLServerColumn . new ( field [ :ColName ] , default , type , is_identity , is_nullable )
319+
320+ result = select ( sql , name , true )
321+ result . collect do |column_info |
322+ # Remove brackets and outer quotes (if quoted) of default value returned by db, i.e:
323+ # "(1)" => "1", "('1')" => "1", "((-1))" => "-1", "('(-1)')" => "(-1)"
324+ column_info . symbolize_keys!
325+ column_info [ :default_value ] = column_info [ :default_value ] . match ( /\A \( +'?(.*?)'?\) +\Z / ) [ 1 ] if column_info [ :default_value ]
326+ SQLServerColumn . new ( column_info )
311327 end
312- columns
313328 end
314329
315330 def empty_insert_statement ( table_name )
@@ -552,8 +567,9 @@ def __indexes(table_name, name = nil)
552567 indexes
553568 end
554569
555- def select ( sql , name = nil )
556- repair_special_columns ( sql )
570+
571+ def select ( sql , name = nil , ignore_special_columns = false )
572+ repair_special_columns ( sql ) unless ignore_special_columns
557573
558574 result = [ ]
559575 execute ( sql ) do |handle |
0 commit comments