diff --git a/lib/active_record/type/oracle_enhanced/raw.rb b/lib/active_record/type/oracle_enhanced/raw.rb index 947947ae1..34e30f83a 100644 --- a/lib/active_record/type/oracle_enhanced/raw.rb +++ b/lib/active_record/type/oracle_enhanced/raw.rb @@ -10,14 +10,31 @@ def type :raw end + def deserialize(value) + value.is_a?(HEXData) ? value.raw_binary_string : super + end + def serialize(value) # Encode a string or byte array as string of hex codes if value.nil? super else - value = value.unpack("C*") - value.map { |x| "%02X" % x }.join + HEXData.from_binary_string(value) + end + end + + class HEXData < ::String + def self.from_binary_string(str) + new(str.unpack1("H*")) + end + + def raw_binary_string + (0..length - 2).step(2).reduce(::String.new(capacity: length/2, encoding: Encoding::BINARY)) do |data, i| + data << self[i, 2].hex + end end + + OCI8::BindType::Mapping[self] = OCI8::BindType::String end end end diff --git a/spec/active_record/oracle_enhanced/type/raw_spec.rb b/spec/active_record/oracle_enhanced/type/raw_spec.rb index 4cd4d6812..061e876a4 100644 --- a/spec/active_record/oracle_enhanced/type/raw_spec.rb +++ b/spec/active_record/oracle_enhanced/type/raw_spec.rb @@ -38,6 +38,7 @@ class ::TestEmployee < ActiveRecord::Base last_name: "Last", binary_data: @binary_data ) + expect(@employee.binary_data).to eq(@binary_data) @employee.reload expect(@employee.binary_data).to eq(@binary_data) end @@ -51,6 +52,7 @@ class ::TestEmployee < ActiveRecord::Base expect(@employee.binary_data).to be_nil @employee.binary_data = @binary_data @employee.save! + expect(@employee.binary_data).to eq(@binary_data) @employee.reload expect(@employee.binary_data).to eq(@binary_data) end @@ -77,6 +79,7 @@ class ::TestEmployee < ActiveRecord::Base @employee.reload @employee.binary_data = @binary_data2 @employee.save! + expect(@employee.binary_data).to eq(@binary_data2) @employee.reload expect(@employee.binary_data).to eq(@binary_data2) end @@ -116,13 +119,14 @@ class ::TestEmployee < ActiveRecord::Base @employee.reload @employee.binary_data = @binary_data @employee.save! + expect(@employee.binary_data).to eq(@binary_data) @employee.reload expect(@employee.binary_data).to eq(@binary_data) end it "should allow equality on select" do TestEmployee.delete_all - TestEmployee.create!( + employee = TestEmployee.create!( first_name: "First", last_name: "Last", binary_data: @binary_data, @@ -132,6 +136,20 @@ class ::TestEmployee < ActiveRecord::Base last_name: "Last1", binary_data: @binary_data2, ) - expect(TestEmployee.where(binary_data: @binary_data)).to have_attributes(count: 1) + expect(TestEmployee.where(binary_data: @binary_data).to_a).to eq([employee]) + end + + it "should allow equality on select with NULL value" do + TestEmployee.delete_all + employee = TestEmployee.create!( + first_name: "First", + last_name: "Last", + ) + TestEmployee.create!( + first_name: "First1", + last_name: "Last1", + binary_data: @binary_data2, + ) + expect(TestEmployee.where(binary_data: nil).to_a).to eq([employee]) end end