Skip to content

Commit 7f9a4cf

Browse files
committed
Added support for storing hex strings in binary columns.
This resembles how the Mysql and Postgres adapters store binary data.
1 parent 7977a7a commit 7f9a4cf

File tree

1 file changed

+19
-4
lines changed

1 file changed

+19
-4
lines changed

lib/active_record/connection_adapters/sqlserver_adapter.rb

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,14 +200,20 @@ def string_to_time(value)
200200
end
201201
end
202202

203-
# These methods will only allow the adapter to insert binary data with a length of 7K or less
204-
# because of a SQL Server statement length policy.
203+
# To insert into a SQL server binary column, the value must be
204+
# converted to hex characters and prepended with 0x
205+
# Example: INSERT into varbinarytable values (0x0)
206+
# See the output of the stored procedure: 'exec sp_datatype_info'
207+
# and note the literal prefix value of 0x for binary types
205208
def string_to_binary(value)
206-
Base64.encode64(value)
209+
"0x#{value.unpack("H*")[0]}"
207210
end
208211

209212
def binary_to_string(value)
210-
Base64.decode64(value)
213+
# Check if the value actually is hex output from the database
214+
# or an Active Record attribute that was just written. If hex, pack the hex
215+
# characters into a string, otherwise return the value
216+
value =~ /[^[:xdigit:]]/ ? value : [value].pack('H*')
211217
end
212218

213219
protected
@@ -278,6 +284,8 @@ def initialize(connection, logger, connection_options=nil)
278284
def native_database_types
279285
# support for varchar(max) and varbinary(max) for text and binary cols if our version is 9 (2005)
280286
txt = @database_version_major >= 9 ? "varchar(max)" : "text"
287+
288+
# TODO: Need to verify image column works correctly with 2000 if string_to_binary stores a hex string
281289
bin = @database_version_major >= 9 ? "varbinary(max)" : "image"
282290
{
283291
:primary_key => "int NOT NULL IDENTITY(1, 1) PRIMARY KEY",
@@ -491,6 +499,13 @@ def quote(value, column = nil)
491499
case value
492500
when TrueClass then '1'
493501
when FalseClass then '0'
502+
503+
when String, ActiveSupport::Multibyte::Chars
504+
value = value.to_s
505+
506+
# for binary columns, don't quote the result of the string to binary
507+
return column.class.string_to_binary(value) if column && column.type == :binary && column.class.respond_to?(:string_to_binary)
508+
super
494509
else
495510
if value.acts_like?(:time)
496511
"'#{value.strftime("%Y%m%d %H:%M:%S")}'"

0 commit comments

Comments
 (0)