Permalink
Browse files

Update postgres hstore casting to handle null-terminated strings.

This is needed because ruby doesn't null terminate strings, but the PG
connection adapter does. Without this, trying to use a string containing
null in an hstore will always result in invalid SQL (Unexpected end of
 string").

I chose to truncate the string at the first \0 to be consistent with
quote_string and the native PQescapeStringConn.
  • Loading branch information...
1 parent 8efd5fe commit 04eb36cd4c958fad972d1f460c09c7ccda6b8657 @scosman committed Jan 24, 2014
View
4 activerecord/CHANGELOG.md
@@ -1,3 +1,7 @@
+* Update postgres hstore to correctly handle null-terminated strings.
+
+ *Steve Cosman*
+
* Reset the collection association when calling `reset` on it.
Before:
View
2 activerecord/lib/active_record/connection_adapters/postgresql/cast.rb
@@ -137,7 +137,7 @@ def escape_hstore(value)
if value == ""
'""'
else
- '"%s"' % value.to_s.gsub(/(["\\])/, '\\\\\1')
+ '"%s"' % value.to_s.gsub(/\0.*/, '').gsub(/(["\\])/, '\\\\\1')
end
end
end
View
18 activerecord/test/cases/adapters/postgresql/hstore_test.rb
@@ -220,6 +220,24 @@ def test_quoting_special_characters
assert_cycle('ca' => '', 'ac' => 'àc')
end
+ def test_null_char
+ input = {"a" => "b\0c", "d\0e" => "f", "g\u0000h" => "j\u0000k"}
+ expected = {}
+ input.each {|k,v| expected[Hstore.connection.quote_string(k)] = Hstore.connection.quote_string(v) }
+
+ # test creation
+ x = Hstore.create!(:tags => input)
+ x.reload
+ assert_equal(expected, x.tags)
+
+ # test updating
+ x = Hstore.create!(:tags => {})
+ x.tags = input
+ x.save!
+ x.reload
+ assert_equal(expected, x.tags)
+ end
+
def test_multiline
assert_cycle("a\nb" => "c\nd")
end

0 comments on commit 04eb36c

Please sign in to comment.