From cf572114608b7813cacd88076dc272ac2a2a7955 Mon Sep 17 00:00:00 2001 From: Joel Date: Sat, 4 Feb 2012 23:51:03 -0800 Subject: Additional hstore tests, supporting null values, better compliance with postgres docs --- .../connection_adapters/postgresql_adapter.rb | 38 ++++++++++------------ 1 file changed, 17 insertions(+), 21 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index ed82c4d6f6..52693e19d9 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -56,36 +56,32 @@ module ActiveRecord if Hash === object object.map { |k,v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" - }.join ', ' + }.join ',' else - kvs = object.scan(/(? '\\ ', - '\\' => '\\\\', - '"' => '\\"', - '=' => '\\=', - } - HSTORE_ESCAPE_RE = Regexp.union(HSTORE_ESCAPE.keys) - HSTORE_UNESCAPE = HSTORE_ESCAPE.invert - HSTORE_UNESCAPE_RE = Regexp.union(HSTORE_UNESCAPE.keys) + def hash_from_hstore_string(string) + Hash[string.scan(HstorePair).map { |k,v| + v = v.upcase == 'NULL' ? nil : v.gsub(/^"(.*)"$/,'\1').gsub(/\\(.)/, '\1') + k = k.gsub(/^"(.*)"$/,'\1').gsub(/\\(.)/, '\1') + [k,v] + }] + end - def unescape_hstore(value) - value.gsub(HSTORE_UNESCAPE_RE) do |match| - HSTORE_UNESCAPE[match] - end + HstorePair = begin + quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/ + unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/ + /(#{quoted_string}|#{unquoted_string})\s*=>\s*(#{quoted_string}|#{unquoted_string})/ end def escape_hstore(value) - value.gsub(HSTORE_ESCAPE_RE) do |match| - HSTORE_ESCAPE[match] - end + value.nil? ? 'NULL' + : value =~ /[=\s,>]/ ? '"%s"' % value.gsub(/(["\\])/, '\\\\\1') + : value == "" ? '""' + : value.gsub(/(["\\])/, '\\\\\1') end end # :startdoc: -- cgit v1.2.3