pg_query 0.10.0 → 0.11.0
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 +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +1 -1
- data/lib/pg_query/deparse.rb +3 -0
- data/lib/pg_query/parse.rb +32 -11
- data/lib/pg_query/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80111a507d64911a62b77017e55feb80a4dad56b
|
4
|
+
data.tar.gz: 06887ee5734b6290a5763b942ba1dde1b21fc1b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb42f31b99f44ccf66df76cb43d9e82f40a2cd87f5dce4d41d392d4920d00ba4c5d240cb25f7550988e1715e2ccd91dcedc5be8787d0cbc305a3412bd7d9a1c9
|
7
|
+
data.tar.gz: bd6c058613222acb36071f847d04afbaba2dbee6c685d52aa914fba1c12e0e86561ea226c75890f16193134426f3ee484d2a984a6fa1a3f9f9183b1db17134de
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.11.0 2016-06-22
|
4
|
+
|
5
|
+
* Improved table name analysis (#tables method)
|
6
|
+
* Don't include CTE names, make them accessible as #cte_names instead [#52](https://github.com/lfittl/pg_query/issues/52)
|
7
|
+
* Include table names in target list sub selects [#38](https://github.com/lfittl/pg_query/issues/38)
|
8
|
+
* Add support for ORDER/GROUP BY, HAVING, and booleans in WHERE [#53](https://github.com/lfittl/pg_query/pull/53) [@jcoleman](https://github.com/jcoleman)
|
9
|
+
* Fix parsing of DROP TYPE statements
|
10
|
+
|
11
|
+
|
3
12
|
## 0.10.0 2016-05-31
|
4
13
|
|
5
14
|
* Based on PostgreSQL 9.5.3
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@ This Ruby extension uses the actual PostgreSQL server source to parse SQL querie
|
|
4
4
|
|
5
5
|
In addition the extension allows you to normalize queries (replacing constant values with ?) and parse these normalized queries into a parsetree again.
|
6
6
|
|
7
|
-
When you build this extension, it
|
7
|
+
When you build this extension, it builds parts of the PostgreSQL server source (see [libpg_query](https://github.com/lfittl/libpg_query)), and then statically links it into this extension.
|
8
8
|
|
9
9
|
This is slightly crazy, but is the only reliable way of parsing all valid PostgreSQL queries.
|
10
10
|
|
data/lib/pg_query/deparse.rb
CHANGED
@@ -526,6 +526,9 @@ class PgQuery
|
|
526
526
|
output << expression
|
527
527
|
end
|
528
528
|
output << '(' + deparse_item_list(node['keys']).join(', ') + ')' if node['keys']
|
529
|
+
output << '(' + deparse_item_list(node['fk_attrs']).join(', ') + ')' if node['fk_attrs']
|
530
|
+
output << 'REFERENCES ' + deparse_item(node['pktable']) + ' (' + deparse_item_list(node['pk_attrs']).join(', ') + ')' if node['pktable']
|
531
|
+
output << 'NOT VALID' if node['skip_validation']
|
529
532
|
output << "USING INDEX #{node['indexname']}" if node['indexname']
|
530
533
|
output.join(' ')
|
531
534
|
end
|
data/lib/pg_query/parse.rb
CHANGED
@@ -34,6 +34,11 @@ class PgQuery
|
|
34
34
|
@tables
|
35
35
|
end
|
36
36
|
|
37
|
+
def cte_names
|
38
|
+
load_tables_and_aliases! if @cte_names.nil?
|
39
|
+
@cte_names
|
40
|
+
end
|
41
|
+
|
37
42
|
def aliases
|
38
43
|
load_tables_and_aliases! if @aliases.nil?
|
39
44
|
@aliases
|
@@ -43,11 +48,12 @@ class PgQuery
|
|
43
48
|
|
44
49
|
def load_tables_and_aliases! # rubocop:disable Metrics/CyclomaticComplexity
|
45
50
|
@tables = []
|
51
|
+
@cte_names = []
|
46
52
|
@aliases = {}
|
47
53
|
|
48
54
|
statements = @tree.dup
|
49
55
|
from_clause_items = []
|
50
|
-
|
56
|
+
subselect_items = []
|
51
57
|
|
52
58
|
loop do
|
53
59
|
statement = statements.shift
|
@@ -64,9 +70,12 @@ class PgQuery
|
|
64
70
|
end
|
65
71
|
|
66
72
|
# CTEs
|
67
|
-
|
68
|
-
|
69
|
-
|
73
|
+
with_clause = statement[SELECT_STMT]['withClause']
|
74
|
+
if with_clause
|
75
|
+
with_clause[WITH_CLAUSE]['ctes'].each do |item|
|
76
|
+
next unless item[COMMON_TABLE_EXPR]
|
77
|
+
@cte_names << item[COMMON_TABLE_EXPR]['ctename']
|
78
|
+
statements << item[COMMON_TABLE_EXPR]['ctequery']
|
70
79
|
end
|
71
80
|
end
|
72
81
|
elsif statement[SELECT_STMT]['op'] == 1
|
@@ -99,7 +108,7 @@ class PgQuery
|
|
99
108
|
# FIXME
|
100
109
|
end
|
101
110
|
when DROP_STMT
|
102
|
-
objects = statement[DROP_STMT]['objects'].map { |list| list.map { |obj| obj['String']['str'] } }
|
111
|
+
objects = statement[DROP_STMT]['objects'].map { |list| list.map { |obj| obj['String'] && obj['String']['str'] } }
|
103
112
|
case statement[DROP_STMT]['removeType']
|
104
113
|
when OBJECT_TYPE_TABLE
|
105
114
|
@tables += objects.map { |r| r.join('.') }
|
@@ -108,11 +117,17 @@ class PgQuery
|
|
108
117
|
end
|
109
118
|
end
|
110
119
|
|
111
|
-
|
120
|
+
statement_value = statement.values[0]
|
121
|
+
unless statement.empty?
|
122
|
+
subselect_items.concat(statement_value['targetList']) if statement_value['targetList']
|
123
|
+
subselect_items << statement_value['whereClause'] if statement_value['whereClause']
|
124
|
+
subselect_items.concat(statement_value['sortClause'].collect { |h| h[SORT_BY]['node'] }) if statement_value['sortClause']
|
125
|
+
subselect_items.concat(statement_value['groupClause']) if statement_value['groupClause']
|
126
|
+
subselect_items << statement_value['havingClause'] if statement_value['havingClause']
|
127
|
+
end
|
112
128
|
end
|
113
129
|
|
114
|
-
|
115
|
-
next_item = where_clause_items.shift
|
130
|
+
next_item = subselect_items.shift
|
116
131
|
if next_item
|
117
132
|
case next_item.keys[0]
|
118
133
|
when A_EXPR
|
@@ -120,17 +135,21 @@ class PgQuery
|
|
120
135
|
elem = next_item.values[0][side]
|
121
136
|
next unless elem
|
122
137
|
if elem.is_a?(Array)
|
123
|
-
|
138
|
+
subselect_items += elem
|
124
139
|
else
|
125
|
-
|
140
|
+
subselect_items << elem
|
126
141
|
end
|
127
142
|
end
|
143
|
+
when BOOL_EXPR
|
144
|
+
subselect_items.concat(next_item.values[0]['args'])
|
145
|
+
when RES_TARGET
|
146
|
+
subselect_items << next_item[RES_TARGET]['val']
|
128
147
|
when SUB_LINK
|
129
148
|
statements << next_item[SUB_LINK]['subselect']
|
130
149
|
end
|
131
150
|
end
|
132
151
|
|
133
|
-
break if
|
152
|
+
break if subselect_items.empty? && statements.empty?
|
134
153
|
end
|
135
154
|
|
136
155
|
loop do
|
@@ -146,6 +165,8 @@ class PgQuery
|
|
146
165
|
from_clause_items += next_item[ROW_EXPR]['args']
|
147
166
|
when RANGE_VAR
|
148
167
|
rangevar = next_item[RANGE_VAR]
|
168
|
+
next if !rangevar['schemaname'] && @cte_names.include?(rangevar['relname'])
|
169
|
+
|
149
170
|
table = [rangevar['schemaname'], rangevar['relname']].compact.join('.')
|
150
171
|
@tables << table
|
151
172
|
@aliases[rangevar['alias'][ALIAS]['aliasname']] = table if rangevar['alias']
|
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.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lukas Fittl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-06-
|
11
|
+
date: 2016-06-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -136,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
136
|
version: '0'
|
137
137
|
requirements: []
|
138
138
|
rubyforge_project:
|
139
|
-
rubygems_version: 2.5.1
|
139
|
+
rubygems_version: 2.4.5.1
|
140
140
|
signing_key:
|
141
141
|
specification_version: 4
|
142
142
|
summary: PostgreSQL query parsing and normalization library
|