pg-hstore 1.1.6 → 1.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/pg_hstore.rb +69 -26
- metadata +5 -3
data/lib/pg_hstore.rb
CHANGED
@@ -1,19 +1,25 @@
|
|
1
1
|
module PgHstore
|
2
2
|
SINGLE_QUOTE = "'"
|
3
|
+
E_SINGLE_QUOTE = "E'"
|
3
4
|
DOUBLE_QUOTE = '"'
|
4
|
-
DOLLAR_QUOTE = '$$' # TODO not infallible
|
5
5
|
HASHROCKET = '=>'
|
6
6
|
COMMA = ','
|
7
|
+
SLASH = '\\'
|
8
|
+
|
9
|
+
ESCAPED_CHAR = /\\(.)/
|
10
|
+
ESCAPED_SINGLE_QUOTE = '\\\''
|
11
|
+
ESCAPED_DOUBLE_QUOTE = '\\"'
|
12
|
+
ESCAPED_SLASH = '\\\\'
|
7
13
|
|
8
14
|
QUOTED_LITERAL = /"[^"\\]*(?:\\.[^"\\]*)*"/
|
9
15
|
UNQUOTED_LITERAL = /[^\s=,][^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
|
10
16
|
LITERAL = /(#{QUOTED_LITERAL}|#{UNQUOTED_LITERAL})/
|
11
17
|
PAIR = /#{LITERAL}\s*=>\s*#{LITERAL}/
|
12
18
|
NULL = /\ANULL\z/i
|
19
|
+
|
13
20
|
# set symbolize_keys = false if you want string keys
|
14
21
|
# thanks to https://github.com/engageis/activerecord-postgres-hstore for regexps!
|
15
22
|
def PgHstore.load(hstore, symbolize_keys = true)
|
16
|
-
hstore = unquote hstore, DOLLAR_QUOTE
|
17
23
|
hstore.scan(PAIR).inject({}) do |memo, (k, v)|
|
18
24
|
k = unescape unquote(k, DOUBLE_QUOTE)
|
19
25
|
k = k.to_sym if symbolize_keys
|
@@ -23,22 +29,28 @@ module PgHstore
|
|
23
29
|
end
|
24
30
|
end
|
25
31
|
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
32
|
+
# Serialize a hash to be sent to PostgreSQL as an hstore value.
|
33
|
+
#
|
34
|
+
# By default, returns a (Postgre)SQL string constant suitable for
|
35
|
+
# interpolating directly into a query. With raw_string = true,
|
36
|
+
# returns the plain string value suitable for use as a bind variable.
|
37
|
+
def PgHstore.dump(hash, raw_string = false)
|
38
|
+
# Per http://www.postgresql.org/docs/9.2/static/hstore.html :
|
39
|
+
#
|
40
|
+
# The text representation of an hstore, used for input and
|
41
|
+
# output, includes zero or more 'key => value' pairs separated
|
42
|
+
# by commas. [...] Whitespace between pairs or around the =>
|
43
|
+
# sign is ignored. Double-quote keys and values [... see
|
44
|
+
# escape_nonnull_for_hstore ...]
|
45
|
+
#
|
46
|
+
# A value (but not a key) can be an SQL NULL. Double-quote the
|
47
|
+
# NULL to treat it as the ordinary string "NULL".
|
48
|
+
hstore = hash.map do |k, v|
|
49
|
+
hstore_k = escape_nonnull_for_hstore(k)
|
50
|
+
hstore_v = (v.nil?) ? "NULL" : escape_nonnull_for_hstore(v)
|
51
|
+
[hstore_k, hstore_v].join(HASHROCKET)
|
52
|
+
end.join(COMMA)
|
53
|
+
raw_string ? hstore : as_postgresql_string_constant(hstore)
|
42
54
|
end
|
43
55
|
|
44
56
|
class << self
|
@@ -57,16 +69,47 @@ module PgHstore
|
|
57
69
|
end
|
58
70
|
end
|
59
71
|
|
60
|
-
ESCAPED_CHAR = /\\(.)/
|
61
72
|
def PgHstore.unescape(literal)
|
62
73
|
literal.gsub ESCAPED_CHAR, '\1'
|
63
74
|
end
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
75
|
+
|
76
|
+
# Escape a value as a string to use as an hstore key or value.
|
77
|
+
#
|
78
|
+
# Per http://www.postgresql.org/docs/9.2/static/hstore.html :
|
79
|
+
#
|
80
|
+
# Double-quote keys and values that include [stuff]. To include a
|
81
|
+
# double quote or a backslash in a key or value, escape it with a
|
82
|
+
# backslash.
|
83
|
+
#
|
84
|
+
# You got it, boss.
|
85
|
+
def PgHstore.escape_nonnull_for_hstore(string)
|
86
|
+
interior = string.to_s.dup
|
87
|
+
interior.gsub!(SLASH) {ESCAPED_SLASH}
|
88
|
+
interior.gsub!(DOUBLE_QUOTE, ESCAPED_DOUBLE_QUOTE)
|
89
|
+
DOUBLE_QUOTE + interior + DOUBLE_QUOTE
|
70
90
|
end
|
71
|
-
end
|
72
91
|
|
92
|
+
# Escape a string as a string constant to be used in a SQL query
|
93
|
+
# to PostgreSQL.
|
94
|
+
#
|
95
|
+
# Ideally we would use plain SQL string constants, which are very simple:
|
96
|
+
# http://www.postgresql.org/docs/9.2/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS
|
97
|
+
# Unfortunately PostgreSQL treats these differently depending on the
|
98
|
+
# variable standard_conforming_strings, which defaulted to off until 9.1.
|
99
|
+
# It doesn't seem possible to generate them correctly for both cases at
|
100
|
+
# once, and trying to know the value of that variable and dispatch on it
|
101
|
+
# would be awful.
|
102
|
+
#
|
103
|
+
# Instead, use the slightly more cumbersome "escape" string constants:
|
104
|
+
# http://www.postgresql.org/docs/9.2/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE
|
105
|
+
# They're a little uglier and they're PostgreSQL-specific, but nobody has
|
106
|
+
# to see them and this whole module is PostgreSQL-specific. And, crucially,
|
107
|
+
# their behavior doesn't vary. Not allowing injection attacks: priceless.
|
108
|
+
# We don't use any of the fancy escapes, just neuter any backslashes and quotes.
|
109
|
+
def PgHstore.as_postgresql_string_constant(string)
|
110
|
+
interior = string.to_s.dup
|
111
|
+
interior.gsub!(SLASH) {ESCAPED_SLASH}
|
112
|
+
interior.gsub!(SINGLE_QUOTE) {ESCAPED_SINGLE_QUOTE}
|
113
|
+
E_SINGLE_QUOTE + interior + SINGLE_QUOTE
|
114
|
+
end
|
115
|
+
end
|
metadata
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg-hstore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Peter van Hardenberg
|
9
9
|
- Seamus Abshere
|
10
|
+
- Greg Price
|
10
11
|
autorequire:
|
11
12
|
bindir: bin
|
12
13
|
cert_chain: []
|
13
|
-
date: 2013-02-
|
14
|
+
date: 2013-02-20 00:00:00.000000000 Z
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
17
|
name: rspec
|
@@ -77,6 +78,7 @@ rubyforge_project:
|
|
77
78
|
rubygems_version: 1.8.25
|
78
79
|
signing_key:
|
79
80
|
specification_version: 3
|
80
|
-
summary:
|
81
|
+
summary: postgresql hstore parser/deparser - provides PgHstore.dump and PgHstore.load
|
82
|
+
(aka parse)
|
81
83
|
test_files: []
|
82
84
|
has_rdoc:
|