pg_query 2.0.3 → 2.1.3
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 +77 -0
- data/README.md +12 -0
- data/Rakefile +5 -19
- data/ext/pg_query/extconf.rb +3 -1
- data/ext/pg_query/include/c.h +12 -0
- data/ext/pg_query/include/executor/executor.h +6 -0
- data/ext/pg_query/include/nodes/execnodes.h +9 -6
- data/ext/pg_query/include/nodes/pathnodes.h +1 -1
- data/ext/pg_query/include/optimizer/paths.h +8 -0
- data/ext/pg_query/include/pg_config.h +9 -6
- data/ext/pg_query/include/pg_config_manual.h +7 -0
- data/ext/pg_query/include/pg_query.h +2 -2
- data/ext/pg_query/include/pg_query_outfuncs_defs.c +1 -0
- data/ext/pg_query/include/pg_query_readfuncs_defs.c +1 -0
- data/ext/pg_query/include/protobuf/pg_query.pb-c.h +472 -467
- data/ext/pg_query/include/protobuf-c/protobuf-c.h +7 -3
- data/ext/pg_query/include/protobuf-c.h +7 -3
- data/ext/pg_query/include/utils/array.h +1 -0
- data/ext/pg_query/include/utils/lsyscache.h +1 -0
- data/ext/pg_query/include/utils/probes.h +57 -57
- data/ext/pg_query/pg_query.pb-c.c +502 -487
- data/ext/pg_query/pg_query_deparse.c +6 -0
- data/ext/pg_query/pg_query_fingerprint.c +119 -32
- data/ext/pg_query/pg_query_fingerprint.h +3 -1
- data/ext/pg_query/pg_query_normalize.c +222 -63
- data/ext/pg_query/pg_query_parse_plpgsql.c +21 -1
- data/ext/pg_query/pg_query_ruby.c +1 -1
- data/ext/pg_query/pg_query_ruby.sym +1 -0
- data/ext/pg_query/protobuf-c.c +34 -27
- data/ext/pg_query/src_backend_utils_mmgr_mcxt.c +36 -0
- data/ext/pg_query/src_common_hashfn.c +420 -0
- data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +1 -1
- data/lib/pg_query/filter_columns.rb +4 -4
- data/lib/pg_query/fingerprint.rb +1 -3
- data/lib/pg_query/parse.rb +111 -45
- data/lib/pg_query/pg_query_pb.rb +1385 -1383
- data/lib/pg_query/version.rb +1 -1
- data/lib/pg_query.rb +0 -1
- metadata +8 -8
- data/lib/pg_query/json_field_names.rb +0 -1402
data/lib/pg_query/parse.rb
CHANGED
@@ -29,6 +29,7 @@ module PgQuery
|
|
29
29
|
@tables = nil
|
30
30
|
@aliases = nil
|
31
31
|
@cte_names = nil
|
32
|
+
@functions = nil
|
32
33
|
end
|
33
34
|
|
34
35
|
def dup_tree
|
@@ -51,27 +52,52 @@ module PgQuery
|
|
51
52
|
tables_with_details.select { |t| t[:type] == :ddl }.map { |t| t[:name] }.uniq
|
52
53
|
end
|
53
54
|
|
55
|
+
# Returns function names, ignoring their argument types. This may be insufficient
|
56
|
+
# if you need to disambiguate two functions with the same name but different argument
|
57
|
+
# types.
|
58
|
+
def functions
|
59
|
+
functions_with_details.map { |f| f[:function] }.uniq
|
60
|
+
end
|
61
|
+
|
62
|
+
def ddl_functions
|
63
|
+
functions_with_details.select { |f| f[:type] == :ddl }.map { |f| f[:function] }.uniq
|
64
|
+
end
|
65
|
+
|
66
|
+
def call_functions
|
67
|
+
functions_with_details.select { |f| f[:type] == :call }.map { |f| f[:function] }.uniq
|
68
|
+
end
|
69
|
+
|
54
70
|
def cte_names
|
55
|
-
|
71
|
+
load_objects! if @cte_names.nil?
|
56
72
|
@cte_names
|
57
73
|
end
|
58
74
|
|
59
75
|
def aliases
|
60
|
-
|
76
|
+
load_objects! if @aliases.nil?
|
61
77
|
@aliases
|
62
78
|
end
|
63
79
|
|
64
80
|
def tables_with_details
|
65
|
-
|
81
|
+
load_objects! if @tables.nil?
|
66
82
|
@tables
|
67
83
|
end
|
68
84
|
|
85
|
+
def functions_with_details
|
86
|
+
load_objects! if @functions.nil?
|
87
|
+
@functions
|
88
|
+
end
|
89
|
+
|
69
90
|
protected
|
70
91
|
|
71
|
-
|
92
|
+
# Parses the query and finds table and function references
|
93
|
+
#
|
94
|
+
# Note we use ".to_ary" on arrays from the Protobuf library before
|
95
|
+
# passing them to concat, because of https://bugs.ruby-lang.org/issues/18140
|
96
|
+
def load_objects! # rubocop:disable Metrics/CyclomaticComplexity
|
72
97
|
@tables = [] # types: select, dml, ddl
|
73
98
|
@cte_names = []
|
74
99
|
@aliases = {}
|
100
|
+
@functions = [] # types: call, ddl
|
75
101
|
|
76
102
|
statements = @tree.stmts.dup.to_a.map(&:stmt)
|
77
103
|
from_clause_items = [] # types: select, dml, ddl
|
@@ -86,22 +112,18 @@ module PgQuery
|
|
86
112
|
# The following statement types do not modify tables and are added to from_clause_items
|
87
113
|
# (and subsequently @tables)
|
88
114
|
when :select_stmt
|
89
|
-
subselect_items.concat(statement.select_stmt.target_list)
|
115
|
+
subselect_items.concat(statement.select_stmt.target_list.to_ary)
|
90
116
|
subselect_items << statement.select_stmt.where_clause if statement.select_stmt.where_clause
|
91
117
|
subselect_items.concat(statement.select_stmt.sort_clause.collect { |h| h.sort_by.node })
|
92
|
-
subselect_items.concat(statement.select_stmt.group_clause)
|
118
|
+
subselect_items.concat(statement.select_stmt.group_clause.to_ary)
|
93
119
|
subselect_items << statement.select_stmt.having_clause if statement.select_stmt.having_clause
|
94
120
|
|
95
121
|
case statement.select_stmt.op
|
96
122
|
when :SETOP_NONE
|
97
123
|
(statement.select_stmt.from_clause || []).each do |item|
|
98
|
-
|
99
|
-
statements << item.range_subselect.subquery
|
100
|
-
else
|
101
|
-
from_clause_items << { item: item, type: :select }
|
102
|
-
end
|
124
|
+
from_clause_items << { item: item, type: :select }
|
103
125
|
end
|
104
|
-
when :SETOP_UNION
|
126
|
+
when :SETOP_UNION, :SETOP_EXCEPT, :SETOP_INTERSECT
|
105
127
|
statements << PgQuery::Node.new(select_stmt: statement.select_stmt.larg) if statement.select_stmt.larg
|
106
128
|
statements << PgQuery::Node.new(select_stmt: statement.select_stmt.rarg) if statement.select_stmt.rarg
|
107
129
|
end
|
@@ -117,10 +139,22 @@ module PgQuery
|
|
117
139
|
from_clause_items << { item: PgQuery::Node.new(range_var: value.relation), type: :dml }
|
118
140
|
statements << value.select_stmt if statement.node == :insert_stmt && value.select_stmt
|
119
141
|
|
120
|
-
|
142
|
+
if statement.node == :update_stmt
|
143
|
+
value.from_clause.each do |item|
|
144
|
+
from_clause_items << { item: item, type: :select }
|
145
|
+
end
|
146
|
+
subselect_items.concat(statement.update_stmt.target_list.to_ary)
|
147
|
+
end
|
148
|
+
|
121
149
|
subselect_items << statement.update_stmt.where_clause if statement.node == :update_stmt && statement.update_stmt.where_clause
|
122
150
|
subselect_items << statement.delete_stmt.where_clause if statement.node == :delete_stmt && statement.delete_stmt.where_clause
|
123
151
|
|
152
|
+
if statement.node == :delete_stmt
|
153
|
+
statement.delete_stmt.using_clause.each do |using_clause|
|
154
|
+
from_clause_items << { item: using_clause, type: :select }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
124
158
|
if value.with_clause
|
125
159
|
cte_statements, cte_names = statements_and_cte_names_for_with_clause(value.with_clause)
|
126
160
|
@cte_names.concat(cte_names)
|
@@ -168,6 +202,10 @@ module PgQuery
|
|
168
202
|
@tables += objects.map { |r| { name: r.join('.'), type: :ddl } }
|
169
203
|
when :OBJECT_RULE, :OBJECT_TRIGGER
|
170
204
|
@tables += objects.map { |r| { name: r[0..-2].join('.'), type: :ddl } }
|
205
|
+
when :OBJECT_FUNCTION
|
206
|
+
# Only one function can be dropped in a statement
|
207
|
+
obj = statement.drop_stmt.objects[0].object_with_args
|
208
|
+
@functions << { function: obj.objname[0].string.str, type: :ddl }
|
171
209
|
end
|
172
210
|
when :grant_stmt
|
173
211
|
objects = statement.grant_stmt.objects
|
@@ -184,12 +222,28 @@ module PgQuery
|
|
184
222
|
# The following are other statements that don't fit into query/DML/DDL
|
185
223
|
when :explain_stmt
|
186
224
|
statements << statement.explain_stmt.query
|
225
|
+
when :create_function_stmt
|
226
|
+
@functions << {
|
227
|
+
function: statement.create_function_stmt.funcname[0].string.str,
|
228
|
+
type: :ddl
|
229
|
+
}
|
230
|
+
when :rename_stmt
|
231
|
+
if statement.rename_stmt.rename_type == :OBJECT_FUNCTION
|
232
|
+
original_name = statement.rename_stmt.object.object_with_args.objname[0].string.str
|
233
|
+
new_name = statement.rename_stmt.newname
|
234
|
+
@functions += [
|
235
|
+
{ function: original_name, type: :ddl },
|
236
|
+
{ function: new_name, type: :ddl }
|
237
|
+
]
|
238
|
+
end
|
187
239
|
end
|
188
240
|
end
|
189
241
|
|
190
242
|
next_item = subselect_items.shift
|
191
243
|
if next_item
|
192
244
|
case next_item.node
|
245
|
+
when :list
|
246
|
+
subselect_items += next_item.list.items.to_ary
|
193
247
|
when :a_expr
|
194
248
|
%w[lexpr rexpr].each do |side|
|
195
249
|
elem = next_item.a_expr.public_send(side)
|
@@ -201,47 +255,59 @@ module PgQuery
|
|
201
255
|
end
|
202
256
|
end
|
203
257
|
when :bool_expr
|
204
|
-
subselect_items.concat(next_item.bool_expr.args)
|
258
|
+
subselect_items.concat(next_item.bool_expr.args.to_ary)
|
259
|
+
when :coalesce_expr
|
260
|
+
subselect_items.concat(next_item.coalesce_expr.args.to_ary)
|
261
|
+
when :min_max_expr
|
262
|
+
subselect_items.concat(next_item.min_max_expr.args.to_ary)
|
205
263
|
when :res_target
|
206
264
|
subselect_items << next_item.res_target.val
|
207
265
|
when :sub_link
|
208
266
|
statements << next_item.sub_link.subselect
|
267
|
+
when :func_call
|
268
|
+
subselect_items.concat(next_item.func_call.args.to_ary)
|
269
|
+
@functions << {
|
270
|
+
function: next_item.func_call.funcname.map { |f| f.string.str }.join('.'),
|
271
|
+
type: :call
|
272
|
+
}
|
273
|
+
when :case_expr
|
274
|
+
subselect_items.concat(next_item.case_expr.args.map { |arg| arg.case_when.expr })
|
275
|
+
subselect_items.concat(next_item.case_expr.args.map { |arg| arg.case_when.result })
|
276
|
+
subselect_items << next_item.case_expr.defresult
|
209
277
|
end
|
210
278
|
end
|
211
279
|
|
212
|
-
break if subselect_items.empty? && statements.empty?
|
213
|
-
end
|
214
|
-
|
215
|
-
loop do
|
216
280
|
next_item = from_clause_items.shift
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
281
|
+
if next_item && next_item[:item]
|
282
|
+
case next_item[:item].node
|
283
|
+
when :join_expr
|
284
|
+
from_clause_items << { item: next_item[:item].join_expr.larg, type: next_item[:type] }
|
285
|
+
from_clause_items << { item: next_item[:item].join_expr.rarg, type: next_item[:type] }
|
286
|
+
subselect_items << next_item[:item].join_expr.quals
|
287
|
+
when :row_expr
|
288
|
+
from_clause_items += next_item[:item].row_expr.args.map { |a| { item: a, type: next_item[:type] } }
|
289
|
+
when :range_var
|
290
|
+
rangevar = next_item[:item].range_var
|
291
|
+
next if rangevar.schemaname.empty? && @cte_names.include?(rangevar.relname)
|
292
|
+
|
293
|
+
table = [rangevar.schemaname, rangevar.relname].reject { |s| s.nil? || s.empty? }.join('.')
|
294
|
+
@tables << {
|
295
|
+
name: table,
|
296
|
+
type: next_item[:type],
|
297
|
+
location: rangevar.location,
|
298
|
+
schemaname: (rangevar.schemaname unless rangevar.schemaname.empty?),
|
299
|
+
relname: rangevar.relname,
|
300
|
+
inh: rangevar.inh
|
301
|
+
}
|
302
|
+
@aliases[rangevar.alias.aliasname] = table if rangevar.alias
|
303
|
+
when :range_subselect
|
304
|
+
statements << next_item[:item].range_subselect.subquery
|
305
|
+
when :range_function
|
306
|
+
subselect_items += next_item[:item].range_function.functions
|
307
|
+
end
|
244
308
|
end
|
309
|
+
|
310
|
+
break if subselect_items.empty? && statements.empty? && from_clause_items.empty?
|
245
311
|
end
|
246
312
|
|
247
313
|
@tables.uniq!
|