@@ -89,7 +89,7 @@ def self.construct_finder_sql_for_association_limiting(options, join_dependency)
8989
9090 module ConnectionAdapters
9191 class SQLServerColumn < Column # :nodoc:
92- attr_reader :identity , :is_special
92+ attr_reader :identity , :is_special , :is_utf8
9393
9494 def initialize ( info )
9595 if info [ :type ] =~ /numeric|decimal/i
@@ -100,6 +100,7 @@ def initialize(info)
100100 super ( info [ :name ] , info [ :default_value ] , type , info [ :is_nullable ] )
101101 @identity = info [ :is_identity ]
102102 @is_special = [ "text" , "ntext" , "image" ] . include? ( info [ :type ] )
103+ @is_utf8 = type =~ /nvarchar|ntext/i
103104 # TODO: check ok to remove @scale = scale_value
104105 @limit = nil unless limitable? ( type )
105106 end
@@ -386,10 +387,12 @@ def empty_insert_statement(table_name)
386387 end
387388
388389 def insert_sql ( sql , name = nil , pk = nil , id_value = nil , sequence_name = nil )
390+ set_utf8_values! ( sql )
389391 super || select_value ( "SELECT SCOPE_IDENTITY() AS Ident" )
390392 end
391393
392394 def update_sql ( sql , name = nil )
395+ set_utf8_values! ( sql )
393396 auto_commiting = @connection [ "AutoCommit" ]
394397 begin
395398 begin_db_transaction if auto_commiting
@@ -716,7 +719,7 @@ def set_identity_insert(table_name, enable = true)
716719
717720 def get_table_name ( sql )
718721 if sql =~ /^\s *insert\s +into\s +([^\( \s ]+)\s *|^\s *update\s +([^\( \s ]+)\s */i
719- $1
722+ $1 || $2
720723 elsif sql =~ /from\s +([^\( \s ]+)\s */i
721724 $1
722725 else
@@ -768,6 +771,40 @@ def repair_special_columns(sql)
768771 end
769772 sql
770773 end
774+
775+ def get_utf8_columns ( table_name )
776+ utf8 = [ ]
777+ @table_columns ||= [ ]
778+ @table_columns [ table_name ] ||= columns ( table_name )
779+ @table_columns [ table_name ] . each do |col |
780+ utf8 << col . name if col . is_utf8
781+ end
782+ utf8
783+ end
784+
785+ def set_utf8_values! ( sql )
786+ utf8_cols = get_utf8_columns ( get_table_name ( sql ) )
787+ if sql =~ /^\s *UPDATE/i
788+ utf8_cols . each do |col |
789+ sql . gsub! ( "[#{ col . to_s } ] = '" , "[#{ col . to_s } ] = N'" )
790+ end
791+ elsif sql =~ /^\s *INSERT/i
792+ # TODO This code should be simplified
793+ # Get columns and values, split them into arrays, and store the original_values for when we need to replace them
794+ columns_and_values = sql . scan ( /\( (.*?)\) / ) . flatten
795+ columns = columns_and_values . first . split ( ',' )
796+ values = columns_and_values [ 1 ] . split ( ',' )
797+ original_values = values . dup
798+ # Iterate columns that should be UTF8, and append an N to the value, if the value is not NULL
799+ utf8_cols . each do |col |
800+ columns . each_with_index do |column , idx |
801+ values [ idx ] = " N#{ values [ idx ] . gsub ( /^ / , '' ) } " if column =~ /\[ #{ col } \] / and values [ idx ] !~ /^NULL$/
802+ end
803+ end
804+ # Replace (in place) the SQL
805+ sql . gsub! ( original_values . join ( ',' ) , values . join ( ',' ) )
806+ end
807+ end
771808
772809 end #class SQLServerAdapter < AbstractAdapter
773810 end #module ConnectionAdapters
0 commit comments