Skip to content

Commit

Permalink
Simplify encoding support.
Browse files Browse the repository at this point in the history
  • Loading branch information
metaskills committed Oct 22, 2010
1 parent 4743909 commit 8cbdac4
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 49 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG
@@ -1,7 +1,10 @@
* master * * master *


* Simplify encoding support. [Ken Collins]

* Add binary timestamp datatype handling. [Erik Bryn] * Add binary timestamp datatype handling. [Erik Bryn]



* 3.0.3 * 3.0.3


* Add TinyTDS/dblib connection mode. [Ken Collins] * Add TinyTDS/dblib connection mode. [Ken Collins]
Expand Down
12 changes: 2 additions & 10 deletions lib/active_record/connection_adapters/sqlserver/quoting.rb
Expand Up @@ -10,8 +10,8 @@ def quote(value, column = nil)
when String, ActiveSupport::Multibyte::Chars when String, ActiveSupport::Multibyte::Chars
if column && column.type == :binary if column && column.type == :binary
column.class.string_to_binary(value) column.class.string_to_binary(value)
elsif quote_value_as_utf8?(value) || column && column.respond_to?(:is_utf8?) && column.is_utf8? elsif value.is_utf8? || (column && column.type == :string)
quoted_utf8_value(value) "N'#{quote_string(value)}'"
else else
super super
end end
Expand Down Expand Up @@ -48,14 +48,6 @@ def quoted_date(value)
super super
end end
end end

def quoted_utf8_value(value)
"N'#{quote_string(value)}'"
end

def quote_value_as_utf8?(value)
value.is_utf8? || enable_default_unicode_types
end


end end
end end
Expand Down
22 changes: 0 additions & 22 deletions lib/active_record/connection_adapters/sqlserver_adapter.rb
Expand Up @@ -68,38 +68,16 @@ def initialize(name, default, sql_type = nil, null = true, sqlserver_options = {


class << self class << self


def string_to_utf8_encoding(value)
value.force_encoding('UTF-8') rescue value
end

def string_to_binary(value) def string_to_binary(value)
value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding)
"0x#{value.unpack("H*")[0]}" "0x#{value.unpack("H*")[0]}"
end end


def binary_to_string(value) def binary_to_string(value)
value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding)
value =~ /[^[:xdigit:]]/ ? value : [value].pack('H*') value =~ /[^[:xdigit:]]/ ? value : [value].pack('H*')
end end


end end


def type_cast(value)
if value && type == :string && is_utf8?
self.class.string_to_utf8_encoding(value)
else
super
end
end

def type_cast_code(var_name)
if type == :string && is_utf8?
"#{self.class.name}.string_to_utf8_encoding(#{var_name})"
else
super
end
end

def is_identity? def is_identity?
@sqlserver_options[:is_identity] @sqlserver_options[:is_identity]
end end
Expand Down
8 changes: 2 additions & 6 deletions test/cases/finder_test_sqlserver.rb
Expand Up @@ -11,12 +11,8 @@ class FinderTest < ActiveRecord::TestCase
include SqlserverCoercedTest include SqlserverCoercedTest


def test_coerced_string_sanitation def test_coerced_string_sanitation
assert_not_equal "'something ' 1=1'", ActiveRecord::Base.sanitize("something ' 1=1") assert_not_equal "N'something ' 1=1'", ActiveRecord::Base.sanitize("something ' 1=1")
if quote_values_as_utf8? assert_equal "N'something; select table'", ActiveRecord::Base.sanitize("something; select table")
assert_equal "N'something; select table'", ActiveRecord::Base.sanitize("something; select table")
else
assert_equal "'something; select table'", ActiveRecord::Base.sanitize("something; select table")
end
end end


end end
Expand Down
4 changes: 2 additions & 2 deletions test/cases/sqlserver_helper.rb
Expand Up @@ -95,10 +95,10 @@ class TestCase < ActiveSupport::TestCase
class << self class << self
def connection_mode_dblib? ; ActiveRecord::Base.connection.instance_variable_get(:@connection_options)[:mode] == :dblib ; end def connection_mode_dblib? ; ActiveRecord::Base.connection.instance_variable_get(:@connection_options)[:mode] == :dblib ; end
def connection_mode_odbc? ; ActiveRecord::Base.connection.instance_variable_get(:@connection_options)[:mode] == :odbc ; end def connection_mode_odbc? ; ActiveRecord::Base.connection.instance_variable_get(:@connection_options)[:mode] == :odbc ; end
def connection_mode_adonet? ; ActiveRecord::Base.connection.instance_variable_get(:@connection_options)[:mode] == :adonet ; end
def sqlserver_2005? ; ActiveRecord::Base.connection.sqlserver_2005? ; end def sqlserver_2005? ; ActiveRecord::Base.connection.sqlserver_2005? ; end
def sqlserver_2008? ; ActiveRecord::Base.connection.sqlserver_2008? ; end def sqlserver_2008? ; ActiveRecord::Base.connection.sqlserver_2008? ; end
def ruby_19? ; RUBY_VERSION >= '1.9' ; end def ruby_19? ; RUBY_VERSION >= '1.9' ; end
def quote_values_as_utf8? ; ActiveRecord::Base.connection.quote_value_as_utf8?('') ; end
end end
def assert_sql(*patterns_to_match) def assert_sql(*patterns_to_match)
$queries_executed = [] $queries_executed = []
Expand All @@ -112,10 +112,10 @@ def assert_sql(*patterns_to_match)
end end
def connection_mode_dblib? ; self.class.connection_mode_dblib? ; end def connection_mode_dblib? ; self.class.connection_mode_dblib? ; end
def connection_mode_odbc? ; self.class.connection_mode_odbc? ; end def connection_mode_odbc? ; self.class.connection_mode_odbc? ; end
def connection_mode_adonet? ; self.class.connection_mode_adonet? ; end
def sqlserver_2005? ; self.class.sqlserver_2005? ; end def sqlserver_2005? ; self.class.sqlserver_2005? ; end
def sqlserver_2008? ; self.class.sqlserver_2008? ; end def sqlserver_2008? ; self.class.sqlserver_2008? ; end
def ruby_19? ; self.class.ruby_19? ; end def ruby_19? ; self.class.ruby_19? ; end
def quote_values_as_utf8? ; self.class.quote_values_as_utf8? ; end
def with_enable_default_unicode_types? def with_enable_default_unicode_types?
ActiveRecord::ConnectionAdapters::SQLServerAdapter.enable_default_unicode_types.is_a?(TrueClass) ActiveRecord::ConnectionAdapters::SQLServerAdapter.enable_default_unicode_types.is_a?(TrueClass)
end end
Expand Down
22 changes: 13 additions & 9 deletions test/cases/unicode_test_sqlserver.rb
@@ -1,3 +1,4 @@
# encoding: UTF-8
require 'cases/sqlserver_helper' require 'cases/sqlserver_helper'


class UnicodeTestSqlserver < ActiveRecord::TestCase class UnicodeTestSqlserver < ActiveRecord::TestCase
Expand Down Expand Up @@ -29,19 +30,22 @@ class UnicodeTestSqlserver < ActiveRecord::TestCase
context 'Testing unicode data' do context 'Testing unicode data' do


setup do setup do
@unicode_data = "\344\270\200\344\272\21434\344\272\224\345\205\255" @unicode_data = "\344\270\200\344\272\21434\344\272\224\345\205\255" # "一二34五六"
@encoded_unicode_data = "\344\270\200\344\272\21434\344\272\224\345\205\255".force_encoding('UTF-8') if ruby_19?
end end


should 'insert into nvarchar field' do should 'insert and retrieve unicode data' do
assert data = SqlServerUnicode.create!(:nvarchar => @unicode_data) assert data = SqlServerUnicode.create!(:nvarchar => @unicode_data)
assert_equal @unicode_data, data.reload.nvarchar if connection_mode_dblib?
assert_equal "一二34五六", data.reload.nvarchar
elsif connection_mode_odbc?
assert_equal "一二34五六", data.reload.nvarchar, 'perhaps you are not using the utf8 odbc that does this legwork'
elsif connection_mode_adonet?
assert_equal "一二34五六", data.reload.nvarchar
else
raise 'need to add a case for this'
end
assert_equal Encoding.find('UTF-8'), data.nvarchar.encoding if ruby_19?
end end

should 're-encode data on DB reads' do
assert data = SqlServerUnicode.create!(:nvarchar => @unicode_data)
assert_equal @encoded_unicode_data, data.reload.nvarchar
end if ruby_19?


end end


Expand Down

0 comments on commit 8cbdac4

Please sign in to comment.