Skip to content

Commit 3369fee

Browse files
committed
Merge branch 'master' of git://github.com/jeremydurham/rails-sqlserver-adapter
Although Jeremy didn't comment it, he also changed over to using SCOPE_IDENTITY instead of @@IDENTITY, which is a Good Thing when you have triggers, etc.
2 parents 89447a2 + 0a453f2 commit 3369fee

File tree

1 file changed

+39
-2
lines changed

1 file changed

+39
-2
lines changed

lib/active_record/connection_adapters/sqlserver_adapter.rb

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)