pg_query 0.2.4 → 0.2.5
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.
- checksums.yaml +8 -8
- data/ext/pg_query/pg_query.c +1 -1
- data/lib/pg_query/parse.rb +6 -157
- data/lib/pg_query/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MDBlYTM5NmYyMDE5MjJiYTgyMjFkZmIwYWU4Y2Y5MzMwMDBkOGU0NA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NmFkMDNkNzBjM2QxZjhmZjQ0NzQwYTZjMDA2YjQ2NjRiMGQ0OTVlZQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZDg4YzUyZDZhZDYwZGViNmIzMWFjOWQ3MGRlMGI4MzhmMmNlMWI4YWVhYzFm
|
10
|
+
NjE3NWY5YTczZGMyOWQyYTI0YjJjZDczZjEwZTNjOTkzOTc5ZWE5ZTlkNTI3
|
11
|
+
MDNjZDY1YWI5ZjRiNzJhZGFjMjVjNWUwMzMwODRlNDc4ZjVhYWE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OTJkZjM1NGQzM2M5NGZjZWMyZjM3NTlhOGI2MmU4OWJkOWJiMmM4NDAxMGIw
|
14
|
+
OTQwMTVlZWJhN2EyNGM3ZjA5MmIzZjM3MmNjNjRiOWZjYjE1YWE2MGQwMWM5
|
15
|
+
YmQ0YzIyMWVlZjg2Y2Y5YWRkMGFiODI0NTM2ZTBlYWM4YzI1OTQ=
|
data/ext/pg_query/pg_query.c
CHANGED
@@ -68,7 +68,7 @@ static VALUE pg_query_raw_parse(VALUE self, VALUE input)
|
|
68
68
|
str = StringValueCStr(input);
|
69
69
|
tree = raw_parser(str);
|
70
70
|
|
71
|
-
str =
|
71
|
+
str = nodeToJSONString(tree);
|
72
72
|
|
73
73
|
// Save stderr for result
|
74
74
|
read(stderr_pipe[0], stderr_buffer, STDERR_BUFFER_LEN);
|
data/lib/pg_query/parse.rb
CHANGED
@@ -3,20 +3,19 @@ require 'json'
|
|
3
3
|
class PgQuery
|
4
4
|
def self.parse(query)
|
5
5
|
parsetree, stderr = _raw_parse(query)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
if !parsetree.nil? && !parsetree.empty?
|
10
|
-
parsetree = parsetree_to_json(parsetree)
|
6
|
+
|
7
|
+
begin
|
11
8
|
parsetree = JSON.parse(parsetree, max_nesting: 1000)
|
9
|
+
rescue JSON::ParserError => e
|
10
|
+
raise ParseError.new("Failed to parse JSON", -1)
|
12
11
|
end
|
13
|
-
|
12
|
+
|
14
13
|
warnings = []
|
15
14
|
stderr.each_line do |line|
|
16
15
|
next unless line[/^WARNING/]
|
17
16
|
warnings << line.strip
|
18
17
|
end
|
19
|
-
|
18
|
+
|
20
19
|
PgQuery.new(query, parsetree, warnings)
|
21
20
|
end
|
22
21
|
|
@@ -28,154 +27,4 @@ class PgQuery
|
|
28
27
|
@parsetree = parsetree
|
29
28
|
@warnings = warnings
|
30
29
|
end
|
31
|
-
|
32
|
-
protected
|
33
|
-
def self.parsetree_to_json(str)
|
34
|
-
str.strip!
|
35
|
-
control_chars = '(){}: '
|
36
|
-
location = nil # :hashname, :key, :value
|
37
|
-
structure_stack = [] # :hash, :array (when delimiter opens we push, when delimiter closes we pop)
|
38
|
-
open_string = false
|
39
|
-
escaped_string = false
|
40
|
-
next_char_is_escaped = false
|
41
|
-
double_hash_close_in = 0 # This is used to ask for an additional closing delimiter (added when x = 1 and we reach a closing delimiter)
|
42
|
-
out = ""
|
43
|
-
|
44
|
-
i = 0
|
45
|
-
loop do
|
46
|
-
break if i > str.size-1
|
47
|
-
|
48
|
-
c = str[i]
|
49
|
-
last_location = location
|
50
|
-
char_is_escaped = next_char_is_escaped
|
51
|
-
next_char_is_escaped = false
|
52
|
-
if control_chars.include?(c) && !char_is_escaped && (!open_string || !escaped_string)
|
53
|
-
# Space is not always a control character, skip in those cases
|
54
|
-
if c == ' ' && last_location == :hashname && str[i+1] != ':'
|
55
|
-
out += c
|
56
|
-
i += 1
|
57
|
-
next
|
58
|
-
end
|
59
|
-
|
60
|
-
# Keep empty nodes as empty hashes (e.g. nodes that can't be output)
|
61
|
-
if c == '{' && str[i+1] == '}'
|
62
|
-
out += "{}"
|
63
|
-
out += ", " if i+2 < str.size && !'})'.include?(str[i+2])
|
64
|
-
i += 2 # Skip {}
|
65
|
-
next
|
66
|
-
end
|
67
|
-
|
68
|
-
location = nil # All control characters reset location
|
69
|
-
|
70
|
-
# This should never happen, but if it does, catch it
|
71
|
-
if open_string
|
72
|
-
out += '"' unless escaped_string
|
73
|
-
open_string = false
|
74
|
-
escaped_string = false
|
75
|
-
end
|
76
|
-
|
77
|
-
# Write out JSON control characters
|
78
|
-
if last_location == :hashname
|
79
|
-
out += ': {'
|
80
|
-
elsif last_location == :key
|
81
|
-
out += ': '
|
82
|
-
end
|
83
|
-
|
84
|
-
case c
|
85
|
-
when '('
|
86
|
-
out += '['
|
87
|
-
when ')'
|
88
|
-
out += ']'
|
89
|
-
when '{'
|
90
|
-
out += '{'
|
91
|
-
when '}'
|
92
|
-
out += '}}'
|
93
|
-
when ':'
|
94
|
-
# No JSON equivalent
|
95
|
-
end
|
96
|
-
|
97
|
-
# Handle double hash closes (required for out-of-place nodes like ANY)
|
98
|
-
case c
|
99
|
-
when '{'
|
100
|
-
if double_hash_close_in > 0
|
101
|
-
double_hash_close_in += 1
|
102
|
-
end
|
103
|
-
when '}'
|
104
|
-
if double_hash_close_in == 1
|
105
|
-
out += '}}'
|
106
|
-
double_hash_close_in = 0
|
107
|
-
elsif double_hash_close_in > 1
|
108
|
-
double_hash_close_in -= 1
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
# Write out delimiter if needed
|
113
|
-
if (last_location == :value || '})'.include?(c)) && i+1 < str.size && !'})'.include?(str[i+1])
|
114
|
-
out += ', '
|
115
|
-
end
|
116
|
-
|
117
|
-
# Determine new location
|
118
|
-
case c
|
119
|
-
when '{'
|
120
|
-
structure_stack << :hash
|
121
|
-
location = :hashname
|
122
|
-
when '('
|
123
|
-
structure_stack << :array
|
124
|
-
location = :value if !control_chars.include?(str[i+1])
|
125
|
-
when '}', ')'
|
126
|
-
structure_stack.pop
|
127
|
-
when ':'
|
128
|
-
location = :key
|
129
|
-
when ' '
|
130
|
-
location = :value if [:value, :key].include?(last_location) && !control_chars.include?(str[i+1])
|
131
|
-
end
|
132
|
-
else
|
133
|
-
if char_is_escaped
|
134
|
-
case c
|
135
|
-
when '"'
|
136
|
-
out += "\\\""
|
137
|
-
when '\\'
|
138
|
-
out += "\\\\"
|
139
|
-
else
|
140
|
-
out += c
|
141
|
-
end
|
142
|
-
elsif str[i] == '<' && str[i+1] == '>' && control_chars.include?(str[i+2])
|
143
|
-
# Make <> into null values
|
144
|
-
i += 1
|
145
|
-
out += "null"
|
146
|
-
elsif c == '\\'
|
147
|
-
next_char_is_escaped = true # For next round
|
148
|
-
# Ignore all other cases
|
149
|
-
elsif c[/[A-Z]/] && !open_string && last_location != :value && last_location != :hashname && structure_stack.last == :hash
|
150
|
-
# We were not expecting a node name here, but this can happen (e.g. with ANY), try to construct into valid expression
|
151
|
-
location = :hashname
|
152
|
-
double_hash_close_in = 1
|
153
|
-
open_string = true
|
154
|
-
out += '"lexpr": {"'
|
155
|
-
out += c
|
156
|
-
elsif control_chars.include?(str[i-1]) && !open_string && !'0123456789'.include?(c)
|
157
|
-
open_string = true
|
158
|
-
escaped_string = true if c == '"'
|
159
|
-
out += '"' unless escaped_string
|
160
|
-
out += c
|
161
|
-
c = nil # To avoid close string taking care of us...
|
162
|
-
else
|
163
|
-
out += c
|
164
|
-
end
|
165
|
-
|
166
|
-
# Close string if next element is control character
|
167
|
-
if open_string && !char_is_escaped && c != '\\' &&
|
168
|
-
((last_location == :hashname && ((str[i+1] == '}') || (str[i+1] == ' ' && str[i+2] == ':') || (str[i+1] == ' ' && str[i+2] == ' ' && str[i+3] == ':'))) ||
|
169
|
-
(last_location != :hashname && !escaped_string && control_chars.include?(str[i+1])) ||
|
170
|
-
(escaped_string && c == '"'))
|
171
|
-
out += '"' unless escaped_string
|
172
|
-
open_string = false
|
173
|
-
escaped_string = false
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
i += 1
|
178
|
-
end
|
179
|
-
out
|
180
|
-
end
|
181
30
|
end
|
data/lib/pg_query/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_query
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lukas Fittl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-05-
|
11
|
+
date: 2014-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|