pg-hstore 1.1.6 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|