pg_query 0.13.5 → 1.0.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/ext/pg_query/extconf.rb +1 -1
- data/lib/pg_query/deparse.rb +7 -4
- data/lib/pg_query/filter_columns.rb +3 -1
- data/lib/pg_query/fingerprint.rb +5 -1
- data/lib/pg_query/legacy_parsetree.rb +25 -26
- data/lib/pg_query/node_types.rb +77 -26
- data/lib/pg_query/parse.rb +9 -1
- data/lib/pg_query/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b234a246e532789199b80cfdc118cc44f45f56dc
|
4
|
+
data.tar.gz: 9f1b878a7902bfbce4a86a69d96ecdc8bdd4a659
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 642d3c1c1a325d737da9252e72715a16f25dc6c2138c03ebd4503efb231604a5fd13b0265cf5637c0aa12510837560b70e8f4ad90ca94ecaf937301783bc4673
|
7
|
+
data.tar.gz: 269105c0470ee517a15f6bb613609ed0ff50a915e188b1c43510a98c02304eafee38f5c70a3ecfeefdf4bffdacbbe7331ce0c3d6d13d2336af41d8c314b746bb
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.0.0 2017-10-31
|
4
|
+
|
5
|
+
* IMPORTANT: Major version bump to indicate backwards incompatible parse tree change!
|
6
|
+
* Update to Postgres 10 parser and fingerprint version 2
|
7
|
+
- This is a backwards-incompatible change in parser output format, although it should
|
8
|
+
be relatively easy to update most programs. This can't be avoided since Postgres
|
9
|
+
does not guarantee parse trees stay the same across versions
|
10
|
+
|
11
|
+
|
3
12
|
## 0.13.5 2017-10-26
|
4
13
|
|
5
14
|
* Update to libpg_query 9.5-1.7.1
|
data/ext/pg_query/extconf.rb
CHANGED
data/lib/pg_query/deparse.rb
CHANGED
@@ -116,6 +116,8 @@ class PgQuery
|
|
116
116
|
deparse_rangesubselect(node)
|
117
117
|
when RANGE_VAR
|
118
118
|
deparse_rangevar(node)
|
119
|
+
when RAW_STMT
|
120
|
+
deparse_raw_stmt(node)
|
119
121
|
when RENAME_STMT
|
120
122
|
deparse_renamestmt(node)
|
121
123
|
when RES_TARGET
|
@@ -171,15 +173,16 @@ class PgQuery
|
|
171
173
|
|
172
174
|
def deparse_rangevar(node)
|
173
175
|
output = []
|
174
|
-
|
175
|
-
when 0
|
176
|
-
output << 'ONLY'
|
177
|
-
end
|
176
|
+
output << 'ONLY' unless node['inh']
|
178
177
|
output << '"' + node['relname'] + '"'
|
179
178
|
output << deparse_item(node['alias']) if node['alias']
|
180
179
|
output.join(' ')
|
181
180
|
end
|
182
181
|
|
182
|
+
def deparse_raw_stmt(node)
|
183
|
+
deparse_item(node[STMT_FIELD])
|
184
|
+
end
|
185
|
+
|
183
186
|
def deparse_renamestmt(node)
|
184
187
|
output = []
|
185
188
|
|
@@ -13,7 +13,9 @@ class PgQuery
|
|
13
13
|
loop do
|
14
14
|
statement = statements.shift
|
15
15
|
if statement
|
16
|
-
if statement[
|
16
|
+
if statement[RAW_STMT]
|
17
|
+
statements << statement[RAW_STMT][STMT_FIELD]
|
18
|
+
elsif statement[SELECT_STMT]
|
17
19
|
case statement[SELECT_STMT]['op']
|
18
20
|
when 0
|
19
21
|
if statement[SELECT_STMT][FROM_CLAUSE_FIELD]
|
data/lib/pg_query/fingerprint.rb
CHANGED
@@ -9,7 +9,7 @@ class PgQuery
|
|
9
9
|
|
10
10
|
private
|
11
11
|
|
12
|
-
FINGERPRINT_VERSION =
|
12
|
+
FINGERPRINT_VERSION = 2
|
13
13
|
|
14
14
|
class FingerprintSubHash
|
15
15
|
attr_reader :parts
|
@@ -76,6 +76,10 @@ class PgQuery
|
|
76
76
|
next if [DECLARE_CURSOR_STMT, FETCH_STMT, CLOSE_PORTAL_STMT].include?(node_name)
|
77
77
|
when 'relname'
|
78
78
|
next if node_name == RANGE_VAR && fields[RELPERSISTENCE_FIELD] == 't'
|
79
|
+
when 'stmt_len'
|
80
|
+
next if node_name == RAW_STMT
|
81
|
+
when 'stmt_location'
|
82
|
+
next if node_name == RAW_STMT
|
79
83
|
end
|
80
84
|
|
81
85
|
fingerprint_value(val, hash, node_name, field_name, true)
|
@@ -1,7 +1,9 @@
|
|
1
1
|
class PgQuery
|
2
2
|
# Legacy parsetree from 0.7 and earlier versions - migrate to "tree" format if you can
|
3
3
|
def parsetree # rubocop:disable Metrics/CyclomaticComplexity
|
4
|
-
@parsetree ||= transform_nodes!(@tree) do |
|
4
|
+
@parsetree ||= transform_nodes!(@tree) do |raw_node|
|
5
|
+
node = raw_node.keys[0] == RAW_STMT ? raw_node.delete(RAW_STMT)[STMT_FIELD] : raw_node
|
6
|
+
|
5
7
|
key = node.keys[0]
|
6
8
|
new_key = LEGACY_NODE_NAMES[key] || key.upcase
|
7
9
|
|
@@ -9,34 +11,38 @@ class PgQuery
|
|
9
11
|
when A_CONST
|
10
12
|
transform_parsetree_a_const(node)
|
11
13
|
when A_EXPR
|
12
|
-
transform_string_list(node[A_EXPR]['name'])
|
14
|
+
node[A_EXPR]['name'] = transform_string_list(node[A_EXPR]['name'])
|
13
15
|
node[key].delete('kind')
|
14
16
|
when COLUMN_REF
|
15
|
-
transform_string_list(node[COLUMN_REF]['fields'])
|
17
|
+
node[COLUMN_REF]['fields'] = transform_string_list(node[COLUMN_REF]['fields'])
|
16
18
|
when CREATE_FUNCTION_STMT
|
17
|
-
transform_string_list(node[CREATE_FUNCTION_STMT]['funcname'])
|
19
|
+
node[CREATE_FUNCTION_STMT]['funcname'] = transform_string_list(node[CREATE_FUNCTION_STMT]['funcname'])
|
18
20
|
when CREATE_TRIG_STMT
|
19
|
-
transform_string_list(node[CREATE_TRIG_STMT]['funcname'])
|
21
|
+
node[CREATE_TRIG_STMT]['funcname'] = transform_string_list(node[CREATE_TRIG_STMT]['funcname'])
|
20
22
|
when CONSTRAINT
|
21
23
|
node[CONSTRAINT]['contype'] = LEGACY_CONSTRAINT_TYPES[node[CONSTRAINT]['contype']]
|
22
|
-
transform_string_list(node[CONSTRAINT]['keys'])
|
24
|
+
node[CONSTRAINT]['keys'] = transform_string_list(node[CONSTRAINT]['keys'])
|
23
25
|
when COPY_STMT
|
24
|
-
transform_string_list(node[COPY_STMT]['attlist'])
|
26
|
+
node[COPY_STMT]['attlist'] = transform_string_list(node[COPY_STMT]['attlist'])
|
25
27
|
when DEF_ELEM
|
26
28
|
node[DEF_ELEM]['arg'] = node[DEF_ELEM]['arg'][INTEGER]['ival'] if node[DEF_ELEM]['arg'].is_a?(Hash) && node[DEF_ELEM]['arg'].keys[0] == INTEGER
|
27
29
|
node[DEF_ELEM]['arg'] = node[DEF_ELEM]['arg'][STRING]['str'] if node[DEF_ELEM]['arg'].is_a?(Hash) && node[DEF_ELEM]['arg'].keys[0] == STRING
|
28
|
-
transform_string_list(node[DEF_ELEM]['arg']) if node[DEF_ELEM]['arg'].is_a?(Array)
|
30
|
+
node[DEF_ELEM]['arg'] = transform_string_list(node[DEF_ELEM]['arg']) if node[DEF_ELEM]['arg'].is_a?(Array)
|
29
31
|
when DROP_STMT
|
30
|
-
node[DROP_STMT]['objects'].
|
32
|
+
node[DROP_STMT]['objects'].each_with_index do |obj, idx|
|
33
|
+
node[DROP_STMT]['objects'][idx] = transform_string_list(obj)
|
34
|
+
end
|
31
35
|
when FUNC_CALL
|
32
|
-
transform_string_list(node[FUNC_CALL]['funcname'])
|
36
|
+
node[FUNC_CALL]['funcname'] = transform_string_list(node[FUNC_CALL]['funcname'])
|
33
37
|
when GRANT_ROLE_STMT
|
34
|
-
transform_string_list(node[GRANT_ROLE_STMT]['grantee_roles'])
|
38
|
+
node[GRANT_ROLE_STMT]['grantee_roles'] = transform_string_list(node[GRANT_ROLE_STMT]['grantee_roles'])
|
39
|
+
when RANGE_VAR
|
40
|
+
node[RANGE_VAR]['inhOpt'] = node[RANGE_VAR].delete('inh') ? 2 : 0
|
35
41
|
when TYPE_NAME
|
36
|
-
transform_string_list(node[TYPE_NAME]['names'])
|
42
|
+
node[TYPE_NAME]['names'] = transform_string_list(node[TYPE_NAME]['names'])
|
37
43
|
end
|
38
44
|
|
39
|
-
|
45
|
+
raw_node[new_key] = node.delete(key)
|
40
46
|
end
|
41
47
|
end
|
42
48
|
|
@@ -66,18 +72,7 @@ class PgQuery
|
|
66
72
|
}.freeze
|
67
73
|
|
68
74
|
LEGACY_CONSTRAINT_TYPES = {
|
69
|
-
|
70
|
-
# CONSTR_TYPE_NOTNULL = 1
|
71
|
-
# CONSTR_TYPE_DEFAULT = 2
|
72
|
-
# CONSTR_TYPE_CHECK = 3
|
73
|
-
CONSTR_TYPE_PRIMARY => 'PRIMARY_KEY',
|
74
|
-
# CONSTR_TYPE_UNIQUE = 5
|
75
|
-
# CONSTR_TYPE_EXCLUSION = 6
|
76
|
-
# CONSTR_TYPE_FOREIGN = 7
|
77
|
-
# CONSTR_TYPE_ATTR_DEFERRABLE = 8 # attributes for previous constraint node
|
78
|
-
# CONSTR_TYPE_ATTR_NOT_DEFERRABLE = 9
|
79
|
-
# CONSTR_TYPE_ATTR_DEFERRED = 10
|
80
|
-
# CONSTR_TYPE_ATTR_IMMEDIATE = 11
|
75
|
+
CONSTR_TYPE_PRIMARY => 'PRIMARY_KEY'
|
81
76
|
}.freeze
|
82
77
|
|
83
78
|
def transform_parsetree_a_const(node)
|
@@ -105,6 +100,10 @@ class PgQuery
|
|
105
100
|
def transform_string_list(list)
|
106
101
|
return if list.nil?
|
107
102
|
|
108
|
-
list.
|
103
|
+
if list.is_a?(Array)
|
104
|
+
list.map { |node| node.keys[0] == STRING ? node[STRING]['str'] : node }
|
105
|
+
else
|
106
|
+
[list.keys[0] == STRING ? list[STRING]['str'] : list]
|
107
|
+
end
|
109
108
|
end
|
110
109
|
end
|
data/lib/pg_query/node_types.rb
CHANGED
@@ -60,6 +60,7 @@ class PgQuery
|
|
60
60
|
RANGE_FUNCTION = 'RangeFunction'.freeze
|
61
61
|
RANGE_SUBSELECT = 'RangeSubselect'.freeze
|
62
62
|
RANGE_VAR = 'RangeVar'.freeze
|
63
|
+
RAW_STMT = 'RawStmt'.freeze
|
63
64
|
REFRESH_MAT_VIEW_STMT = 'RefreshMatViewStmt'.freeze
|
64
65
|
RENAME_STMT = 'RenameStmt'.freeze
|
65
66
|
RES_TARGET = 'ResTarget'.freeze
|
@@ -89,6 +90,7 @@ class PgQuery
|
|
89
90
|
FROM_CLAUSE_FIELD = 'fromClause'.freeze
|
90
91
|
RELPERSISTENCE_FIELD = 'relpersistence'.freeze
|
91
92
|
REXPR_FIELD = 'rexpr'.freeze
|
93
|
+
STMT_FIELD = 'stmt'.freeze
|
92
94
|
TARGET_LIST_FIELD = 'targetList'.freeze
|
93
95
|
VALUES_LISTS_FIELD = 'valuesLists'.freeze
|
94
96
|
|
@@ -97,22 +99,65 @@ class PgQuery
|
|
97
99
|
CONSTR_TYPE_NULL = 0 # not standard SQL, but a lot of people expect it
|
98
100
|
CONSTR_TYPE_NOTNULL = 1
|
99
101
|
CONSTR_TYPE_DEFAULT = 2
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
102
|
+
CONSTR_TYPE_IDENTITY = 3
|
103
|
+
CONSTR_TYPE_CHECK = 4
|
104
|
+
CONSTR_TYPE_PRIMARY = 5
|
105
|
+
CONSTR_TYPE_UNIQUE = 6
|
106
|
+
CONSTR_TYPE_EXCLUSION = 7
|
107
|
+
CONSTR_TYPE_FOREIGN = 8
|
108
|
+
CONSTR_TYPE_ATTR_DEFERRABLE = 9 # attributes for previous constraint node
|
109
|
+
CONSTR_TYPE_ATTR_NOT_DEFERRABLE = 10
|
110
|
+
CONSTR_TYPE_ATTR_DEFERRED = 11
|
111
|
+
CONSTR_TYPE_ATTR_IMMEDIATE = 12
|
109
112
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
113
|
+
OBJECT_TYPE_ACCESS_METHOD = 0
|
114
|
+
OBJECT_TYPE_AGGREGATE = 1
|
115
|
+
OBJECT_TYPE_AMOP = 2
|
116
|
+
OBJECT_TYPE_AMPROC = 3
|
117
|
+
OBJECT_TYPE_ATTRIBUTE = 4
|
118
|
+
OBJECT_TYPE_CAST = 5
|
119
|
+
OBJECT_TYPE_COLUMN = 6
|
120
|
+
OBJECT_TYPE_COLLATION = 7
|
121
|
+
OBJECT_TYPE_CONVERSION = 8
|
122
|
+
OBJECT_TYPE_DATABASE = 9
|
123
|
+
OBJECT_TYPE_DEFAULT = 10
|
124
|
+
OBJECT_TYPE_DEFACL = 11
|
125
|
+
OBJECT_TYPE_DOMAIN = 12
|
126
|
+
OBJECT_TYPE_DOMCONSTRAINT = 13
|
127
|
+
OBJECT_TYPE_EVENT_TRIGGER = 14
|
128
|
+
OBJECT_TYPE_EXTENSION = 15
|
129
|
+
OBJECT_TYPE_FDW = 16
|
130
|
+
OBJECT_TYPE_FOREIGN_SERVER = 17
|
131
|
+
OBJECT_TYPE_FOREIGN_TABLE = 18
|
132
|
+
OBJECT_TYPE_FUNCTION = 19
|
133
|
+
OBJECT_TYPE_INDEX = 20
|
134
|
+
OBJECT_TYPE_LANGUAGE = 21
|
135
|
+
OBJECT_TYPE_LARGEOBJECT = 22
|
136
|
+
OBJECT_TYPE_MATVIEW = 23
|
137
|
+
OBJECT_TYPE_OPCLASS = 24
|
138
|
+
OBJECT_TYPE_OPERATOR = 25
|
139
|
+
OBJECT_TYPE_OPFAMILY = 26
|
140
|
+
OBJECT_TYPE_POLICY = 27
|
141
|
+
OBJECT_TYPE_PUBLICATION = 28
|
142
|
+
OBJECT_TYPE_PUBLICATION_REL = 29
|
143
|
+
OBJECT_TYPE_ROLE = 30
|
144
|
+
OBJECT_TYPE_RULE = 31
|
145
|
+
OBJECT_TYPE_SCHEMA = 32
|
146
|
+
OBJECT_TYPE_SEQUENCE = 33
|
147
|
+
OBJECT_TYPE_SUBSCRIPTION = 34
|
148
|
+
OBJECT_TYPE_STATISTIC_EXT = 35
|
149
|
+
OBJECT_TYPE_TABCONSTRAINT = 36
|
150
|
+
OBJECT_TYPE_TABLE = 37
|
151
|
+
OBJECT_TYPE_TABLESPACE = 38
|
152
|
+
OBJECT_TYPE_TRANSFORM = 39
|
153
|
+
OBJECT_TYPE_TRIGGER = 40
|
154
|
+
OBJECT_TYPE_TSCONFIGURATION = 41
|
155
|
+
OBJECT_TYPE_TSDICTIONARY = 42
|
156
|
+
OBJECT_TYPE_TSPARSER = 43
|
157
|
+
OBJECT_TYPE_TSTEMPLATE = 44
|
158
|
+
OBJECT_TYPE_TYPE = 45
|
159
|
+
OBJECT_TYPE_USER_MAPPING = 46
|
160
|
+
OBJECT_TYPE_VIEW = 47
|
116
161
|
|
117
162
|
BOOL_EXPR_AND = 0
|
118
163
|
BOOL_EXPR_OR = 1
|
@@ -129,17 +174,18 @@ class PgQuery
|
|
129
174
|
AEXPR_OP_ANY = 1 # scalar op ANY (array)
|
130
175
|
AEXPR_OP_ALL = 2 # scalar op ALL (array)
|
131
176
|
AEXPR_DISTINCT = 3 # IS DISTINCT FROM - name must be "="
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
177
|
+
AEXPR_NOT_DISTINCT = 4 # IS NOT DISTINCT FROM - name must be "="
|
178
|
+
AEXPR_NULLIF = 5 # NULLIF - name must be "="
|
179
|
+
AEXPR_OF = 6 # IS [NOT] OF - name must be "=" or "<>"
|
180
|
+
AEXPR_IN = 7 # [NOT] IN - name must be "=" or "<>"
|
181
|
+
AEXPR_LIKE = 8 # [NOT] LIKE - name must be "~~" or "!~~"
|
182
|
+
AEXPR_ILIKE = 9 # [NOT] ILIKE - name must be "~~*" or "!~~*"
|
183
|
+
AEXPR_SIMILAR = 10 # [NOT] SIMILAR - name must be "~" or "!~"
|
184
|
+
AEXPR_BETWEEN = 11 # name must be "BETWEEN"
|
185
|
+
AEXPR_NOT_BETWEEN = 12 # name must be "NOT BETWEEN"
|
186
|
+
AEXPR_BETWEEN_SYM = 13 # name must be "BETWEEN SYMMETRIC"
|
187
|
+
AEXPR_NOT_BETWEEN_SYM = 14 # name must be "NOT BETWEEN SYMMETRIC"
|
188
|
+
AEXPR_PAREN = 15 # nameless dummy node for parentheses
|
143
189
|
|
144
190
|
TRANS_STMT_BEGIN = 0
|
145
191
|
TRANS_STMT_START = 1 # semantically identical to BEGIN
|
@@ -228,4 +274,9 @@ class PgQuery
|
|
228
274
|
AT_ForceRowSecurity = 58 # FORCE ROW SECURITY
|
229
275
|
AT_NoForceRowSecurity = 59 # NO FORCE ROW SECURITY
|
230
276
|
AT_GenericOptions = 60 # OPTIONS (...)
|
277
|
+
AT_AttachPartition = 61 # ATTACH PARTITION
|
278
|
+
AT_DetachPartition = 62 # DETACH PARTITION
|
279
|
+
AT_AddIdentity = 63 # ADD IDENTITY
|
280
|
+
AT_SetIdentity = 64 # SET identity column options
|
281
|
+
AT_DropIdentity = 65 # DROP IDENTITY
|
231
282
|
end
|
data/lib/pg_query/parse.rb
CHANGED
@@ -78,6 +78,8 @@ class PgQuery
|
|
78
78
|
statement = statements.shift
|
79
79
|
if statement
|
80
80
|
case statement.keys[0]
|
81
|
+
when RAW_STMT
|
82
|
+
statements << statement[RAW_STMT][STMT_FIELD]
|
81
83
|
# The following statement types do not modify tables and are added to from_clause_items
|
82
84
|
# (and subsequently @tables)
|
83
85
|
when SELECT_STMT
|
@@ -127,7 +129,13 @@ class PgQuery
|
|
127
129
|
when REFRESH_MAT_VIEW_STMT
|
128
130
|
from_clause_items << { item: statement[REFRESH_MAT_VIEW_STMT]['relation'], type: :ddl }
|
129
131
|
when DROP_STMT
|
130
|
-
objects = statement[DROP_STMT]['objects'].map
|
132
|
+
objects = statement[DROP_STMT]['objects'].map do |obj|
|
133
|
+
if obj.is_a?(Array)
|
134
|
+
obj.map { |obj2| obj2['String'] && obj2['String']['str'] }
|
135
|
+
else
|
136
|
+
obj['String'] && obj['String']['str']
|
137
|
+
end
|
138
|
+
end
|
131
139
|
case statement[DROP_STMT]['removeType']
|
132
140
|
when OBJECT_TYPE_TABLE
|
133
141
|
@tables += objects.map { |r| { table: r.join('.'), type: :ddl } }
|
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: 1.0.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: 2017-10-
|
11
|
+
date: 2017-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|