Skip to content

Commit

Permalink
Don't rely on the sql type to quote XML columns in PG
Browse files Browse the repository at this point in the history
  • Loading branch information
sgrif committed Jul 6, 2014
1 parent 2f71669 commit f6968bd
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
require 'active_record/connection_adapters/postgresql/oid/time'
require 'active_record/connection_adapters/postgresql/oid/uuid'
require 'active_record/connection_adapters/postgresql/oid/vector'
require 'active_record/connection_adapters/postgresql/oid/xml'

require 'active_record/connection_adapters/postgresql/oid/type_map_initializer'

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
class Xml < Type::String # :nodoc:
def type
:xml
end

def text?
false
end

def type_cast_for_database(value)
return unless value
Data.new(super)
end

class Data # :nodoc:
def initialize(value)
@value = value
end

def to_s
@value
end
end
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ def quote(value, column = nil) #:nodoc:
end
when String
case sql_type
when 'xml' then "xml '#{quote_string(value)}'"
when /^bit/
case value
when /\A[01]*\Z/ then "B'#{value}'" # Bit-string notation
Expand Down Expand Up @@ -111,19 +110,25 @@ def quote_default_value(value, column) #:nodoc:
private

def _quote(value)
if value.is_a?(Type::Binary::Data)
case value
when Type::Binary::Data
"'#{escape_bytea(value.to_s)}'"
when OID::Xml::Data
"xml '#{quote_string(value.to_s)}'"
else
super
end
end

def _type_cast(value)
if value.is_a?(Type::Binary::Data)
case value
when Type::Binary::Data
# Return a bind param hash with format as binary.
# See http://deveiate.org/code/pg/PGconn.html#method-i-exec_prepared-doc
# for more information
{ value: value.to_s, format: 1 }
when OID::Xml::Data
value.to_s
else
super
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ def initialize_type_map(m) # :nodoc:
m.register_type 'cidr', OID::Cidr.new
m.register_type 'inet', OID::Inet.new
m.register_type 'uuid', OID::Uuid.new
m.register_type 'xml', OID::SpecializedString.new(:xml)
m.register_type 'xml', OID::Xml.new
m.register_type 'tsvector', OID::SpecializedString.new(:tsvector)
m.register_type 'macaddr', OID::SpecializedString.new(:macaddr)
m.register_type 'citext', OID::SpecializedString.new(:citext)
Expand Down
15 changes: 14 additions & 1 deletion activerecord/test/cases/adapters/postgresql/xml_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def setup
begin
@connection.transaction do
@connection.create_table('xml_data_type') do |t|
t.xml 'payload', default: {}
t.xml 'payload'
end
end
rescue ActiveRecord::StatementInvalid
Expand All @@ -32,4 +32,17 @@ def test_null_xml
@connection.execute %q|insert into xml_data_type (payload) VALUES(null)|
assert_nil XmlDataType.first.payload
end

def test_round_trip
data = XmlDataType.new(payload: "<foo>bar</foo>")
assert_equal "<foo>bar</foo>", data.payload
data.save!
assert_equal "<foo>bar</foo>", data.reload.payload
end

def test_update_all
data = XmlDataType.create!
XmlDataType.update_all(payload: "<bar>baz</bar>")
assert_equal "<bar>baz</bar>", data.reload.payload
end
end

0 comments on commit f6968bd

Please sign in to comment.