/src/postgres/src/backend/nodes/nodeFuncs.c
Line | Count | Source |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * nodeFuncs.c |
4 | | * Various general-purpose manipulations of Node trees |
5 | | * |
6 | | * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group |
7 | | * Portions Copyright (c) 1994, Regents of the University of California |
8 | | * |
9 | | * |
10 | | * IDENTIFICATION |
11 | | * src/backend/nodes/nodeFuncs.c |
12 | | * |
13 | | *------------------------------------------------------------------------- |
14 | | */ |
15 | | #include "postgres.h" |
16 | | |
17 | | #include "catalog/pg_collation.h" |
18 | | #include "catalog/pg_type.h" |
19 | | #include "miscadmin.h" |
20 | | #include "nodes/execnodes.h" |
21 | | #include "nodes/nodeFuncs.h" |
22 | | #include "nodes/pathnodes.h" |
23 | | #include "utils/builtins.h" |
24 | | #include "utils/lsyscache.h" |
25 | | |
26 | | static bool expression_returns_set_walker(Node *node, void *context); |
27 | | static int leftmostLoc(int loc1, int loc2); |
28 | | static bool fix_opfuncids_walker(Node *node, void *context); |
29 | | static bool planstate_walk_subplans(List *plans, |
30 | | planstate_tree_walker_callback walker, |
31 | | void *context); |
32 | | static bool planstate_walk_members(PlanState **planstates, int nplans, |
33 | | planstate_tree_walker_callback walker, |
34 | | void *context); |
35 | | |
36 | | |
37 | | /* |
38 | | * exprType - |
39 | | * returns the Oid of the type of the expression's result. |
40 | | */ |
41 | | Oid |
42 | | exprType(const Node *expr) |
43 | 0 | { |
44 | 0 | Oid type; |
45 | |
|
46 | 0 | if (!expr) |
47 | 0 | return InvalidOid; |
48 | | |
49 | 0 | switch (nodeTag(expr)) |
50 | 0 | { |
51 | 0 | case T_Var: |
52 | 0 | type = ((const Var *) expr)->vartype; |
53 | 0 | break; |
54 | 0 | case T_Const: |
55 | 0 | type = ((const Const *) expr)->consttype; |
56 | 0 | break; |
57 | 0 | case T_Param: |
58 | 0 | type = ((const Param *) expr)->paramtype; |
59 | 0 | break; |
60 | 0 | case T_Aggref: |
61 | 0 | type = ((const Aggref *) expr)->aggtype; |
62 | 0 | break; |
63 | 0 | case T_GroupingFunc: |
64 | 0 | type = INT4OID; |
65 | 0 | break; |
66 | 0 | case T_WindowFunc: |
67 | 0 | type = ((const WindowFunc *) expr)->wintype; |
68 | 0 | break; |
69 | 0 | case T_MergeSupportFunc: |
70 | 0 | type = ((const MergeSupportFunc *) expr)->msftype; |
71 | 0 | break; |
72 | 0 | case T_SubscriptingRef: |
73 | 0 | type = ((const SubscriptingRef *) expr)->refrestype; |
74 | 0 | break; |
75 | 0 | case T_FuncExpr: |
76 | 0 | type = ((const FuncExpr *) expr)->funcresulttype; |
77 | 0 | break; |
78 | 0 | case T_NamedArgExpr: |
79 | 0 | type = exprType((Node *) ((const NamedArgExpr *) expr)->arg); |
80 | 0 | break; |
81 | 0 | case T_OpExpr: |
82 | 0 | type = ((const OpExpr *) expr)->opresulttype; |
83 | 0 | break; |
84 | 0 | case T_DistinctExpr: |
85 | 0 | type = ((const DistinctExpr *) expr)->opresulttype; |
86 | 0 | break; |
87 | 0 | case T_NullIfExpr: |
88 | 0 | type = ((const NullIfExpr *) expr)->opresulttype; |
89 | 0 | break; |
90 | 0 | case T_ScalarArrayOpExpr: |
91 | 0 | type = BOOLOID; |
92 | 0 | break; |
93 | 0 | case T_BoolExpr: |
94 | 0 | type = BOOLOID; |
95 | 0 | break; |
96 | 0 | case T_SubLink: |
97 | 0 | { |
98 | 0 | const SubLink *sublink = (const SubLink *) expr; |
99 | |
|
100 | 0 | if (sublink->subLinkType == EXPR_SUBLINK || |
101 | 0 | sublink->subLinkType == ARRAY_SUBLINK) |
102 | 0 | { |
103 | | /* get the type of the subselect's first target column */ |
104 | 0 | Query *qtree = (Query *) sublink->subselect; |
105 | 0 | TargetEntry *tent; |
106 | |
|
107 | 0 | if (!qtree || !IsA(qtree, Query)) |
108 | 0 | elog(ERROR, "cannot get type for untransformed sublink"); |
109 | 0 | tent = linitial_node(TargetEntry, qtree->targetList); |
110 | 0 | Assert(!tent->resjunk); |
111 | 0 | type = exprType((Node *) tent->expr); |
112 | 0 | if (sublink->subLinkType == ARRAY_SUBLINK) |
113 | 0 | { |
114 | 0 | type = get_promoted_array_type(type); |
115 | 0 | if (!OidIsValid(type)) |
116 | 0 | ereport(ERROR, |
117 | 0 | (errcode(ERRCODE_UNDEFINED_OBJECT), |
118 | 0 | errmsg("could not find array type for data type %s", |
119 | 0 | format_type_be(exprType((Node *) tent->expr))))); |
120 | 0 | } |
121 | 0 | } |
122 | 0 | else if (sublink->subLinkType == MULTIEXPR_SUBLINK) |
123 | 0 | { |
124 | | /* MULTIEXPR is always considered to return RECORD */ |
125 | 0 | type = RECORDOID; |
126 | 0 | } |
127 | 0 | else |
128 | 0 | { |
129 | | /* for all other sublink types, result is boolean */ |
130 | 0 | type = BOOLOID; |
131 | 0 | } |
132 | 0 | } |
133 | 0 | break; |
134 | 0 | case T_SubPlan: |
135 | 0 | { |
136 | 0 | const SubPlan *subplan = (const SubPlan *) expr; |
137 | |
|
138 | 0 | if (subplan->subLinkType == EXPR_SUBLINK || |
139 | 0 | subplan->subLinkType == ARRAY_SUBLINK) |
140 | 0 | { |
141 | | /* get the type of the subselect's first target column */ |
142 | 0 | type = subplan->firstColType; |
143 | 0 | if (subplan->subLinkType == ARRAY_SUBLINK) |
144 | 0 | { |
145 | 0 | type = get_promoted_array_type(type); |
146 | 0 | if (!OidIsValid(type)) |
147 | 0 | ereport(ERROR, |
148 | 0 | (errcode(ERRCODE_UNDEFINED_OBJECT), |
149 | 0 | errmsg("could not find array type for data type %s", |
150 | 0 | format_type_be(subplan->firstColType)))); |
151 | 0 | } |
152 | 0 | } |
153 | 0 | else if (subplan->subLinkType == MULTIEXPR_SUBLINK) |
154 | 0 | { |
155 | | /* MULTIEXPR is always considered to return RECORD */ |
156 | 0 | type = RECORDOID; |
157 | 0 | } |
158 | 0 | else |
159 | 0 | { |
160 | | /* for all other subplan types, result is boolean */ |
161 | 0 | type = BOOLOID; |
162 | 0 | } |
163 | 0 | } |
164 | 0 | break; |
165 | 0 | case T_AlternativeSubPlan: |
166 | 0 | { |
167 | 0 | const AlternativeSubPlan *asplan = (const AlternativeSubPlan *) expr; |
168 | | |
169 | | /* subplans should all return the same thing */ |
170 | 0 | type = exprType((Node *) linitial(asplan->subplans)); |
171 | 0 | } |
172 | 0 | break; |
173 | 0 | case T_FieldSelect: |
174 | 0 | type = ((const FieldSelect *) expr)->resulttype; |
175 | 0 | break; |
176 | 0 | case T_FieldStore: |
177 | 0 | type = ((const FieldStore *) expr)->resulttype; |
178 | 0 | break; |
179 | 0 | case T_RelabelType: |
180 | 0 | type = ((const RelabelType *) expr)->resulttype; |
181 | 0 | break; |
182 | 0 | case T_CoerceViaIO: |
183 | 0 | type = ((const CoerceViaIO *) expr)->resulttype; |
184 | 0 | break; |
185 | 0 | case T_ArrayCoerceExpr: |
186 | 0 | type = ((const ArrayCoerceExpr *) expr)->resulttype; |
187 | 0 | break; |
188 | 0 | case T_ConvertRowtypeExpr: |
189 | 0 | type = ((const ConvertRowtypeExpr *) expr)->resulttype; |
190 | 0 | break; |
191 | 0 | case T_CollateExpr: |
192 | 0 | type = exprType((Node *) ((const CollateExpr *) expr)->arg); |
193 | 0 | break; |
194 | 0 | case T_CaseExpr: |
195 | 0 | type = ((const CaseExpr *) expr)->casetype; |
196 | 0 | break; |
197 | 0 | case T_CaseTestExpr: |
198 | 0 | type = ((const CaseTestExpr *) expr)->typeId; |
199 | 0 | break; |
200 | 0 | case T_ArrayExpr: |
201 | 0 | type = ((const ArrayExpr *) expr)->array_typeid; |
202 | 0 | break; |
203 | 0 | case T_RowExpr: |
204 | 0 | type = ((const RowExpr *) expr)->row_typeid; |
205 | 0 | break; |
206 | 0 | case T_RowCompareExpr: |
207 | 0 | type = BOOLOID; |
208 | 0 | break; |
209 | 0 | case T_CoalesceExpr: |
210 | 0 | type = ((const CoalesceExpr *) expr)->coalescetype; |
211 | 0 | break; |
212 | 0 | case T_MinMaxExpr: |
213 | 0 | type = ((const MinMaxExpr *) expr)->minmaxtype; |
214 | 0 | break; |
215 | 0 | case T_SQLValueFunction: |
216 | 0 | type = ((const SQLValueFunction *) expr)->type; |
217 | 0 | break; |
218 | 0 | case T_XmlExpr: |
219 | 0 | if (((const XmlExpr *) expr)->op == IS_DOCUMENT) |
220 | 0 | type = BOOLOID; |
221 | 0 | else if (((const XmlExpr *) expr)->op == IS_XMLSERIALIZE) |
222 | 0 | type = TEXTOID; |
223 | 0 | else |
224 | 0 | type = XMLOID; |
225 | 0 | break; |
226 | 0 | case T_JsonValueExpr: |
227 | 0 | { |
228 | 0 | const JsonValueExpr *jve = (const JsonValueExpr *) expr; |
229 | |
|
230 | 0 | type = exprType((Node *) jve->formatted_expr); |
231 | 0 | } |
232 | 0 | break; |
233 | 0 | case T_JsonConstructorExpr: |
234 | 0 | type = ((const JsonConstructorExpr *) expr)->returning->typid; |
235 | 0 | break; |
236 | 0 | case T_JsonIsPredicate: |
237 | 0 | type = BOOLOID; |
238 | 0 | break; |
239 | 0 | case T_JsonExpr: |
240 | 0 | { |
241 | 0 | const JsonExpr *jexpr = (const JsonExpr *) expr; |
242 | |
|
243 | 0 | type = jexpr->returning->typid; |
244 | 0 | break; |
245 | 0 | } |
246 | 0 | case T_JsonBehavior: |
247 | 0 | { |
248 | 0 | const JsonBehavior *behavior = (const JsonBehavior *) expr; |
249 | |
|
250 | 0 | type = exprType(behavior->expr); |
251 | 0 | break; |
252 | 0 | } |
253 | 0 | case T_NullTest: |
254 | 0 | type = BOOLOID; |
255 | 0 | break; |
256 | 0 | case T_BooleanTest: |
257 | 0 | type = BOOLOID; |
258 | 0 | break; |
259 | 0 | case T_CoerceToDomain: |
260 | 0 | type = ((const CoerceToDomain *) expr)->resulttype; |
261 | 0 | break; |
262 | 0 | case T_CoerceToDomainValue: |
263 | 0 | type = ((const CoerceToDomainValue *) expr)->typeId; |
264 | 0 | break; |
265 | 0 | case T_SetToDefault: |
266 | 0 | type = ((const SetToDefault *) expr)->typeId; |
267 | 0 | break; |
268 | 0 | case T_CurrentOfExpr: |
269 | 0 | type = BOOLOID; |
270 | 0 | break; |
271 | 0 | case T_NextValueExpr: |
272 | 0 | type = ((const NextValueExpr *) expr)->typeId; |
273 | 0 | break; |
274 | 0 | case T_InferenceElem: |
275 | 0 | { |
276 | 0 | const InferenceElem *n = (const InferenceElem *) expr; |
277 | |
|
278 | 0 | type = exprType((Node *) n->expr); |
279 | 0 | } |
280 | 0 | break; |
281 | 0 | case T_ReturningExpr: |
282 | 0 | type = exprType((Node *) ((const ReturningExpr *) expr)->retexpr); |
283 | 0 | break; |
284 | 0 | case T_PlaceHolderVar: |
285 | 0 | type = exprType((Node *) ((const PlaceHolderVar *) expr)->phexpr); |
286 | 0 | break; |
287 | 0 | default: |
288 | 0 | elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr)); |
289 | 0 | type = InvalidOid; /* keep compiler quiet */ |
290 | 0 | break; |
291 | 0 | } |
292 | 0 | return type; |
293 | 0 | } |
294 | | |
295 | | /* |
296 | | * exprTypmod - |
297 | | * returns the type-specific modifier of the expression's result type, |
298 | | * if it can be determined. In many cases, it can't and we return -1. |
299 | | */ |
300 | | int32 |
301 | | exprTypmod(const Node *expr) |
302 | 0 | { |
303 | 0 | if (!expr) |
304 | 0 | return -1; |
305 | | |
306 | 0 | switch (nodeTag(expr)) |
307 | 0 | { |
308 | 0 | case T_Var: |
309 | 0 | return ((const Var *) expr)->vartypmod; |
310 | 0 | case T_Const: |
311 | 0 | return ((const Const *) expr)->consttypmod; |
312 | 0 | case T_Param: |
313 | 0 | return ((const Param *) expr)->paramtypmod; |
314 | 0 | case T_SubscriptingRef: |
315 | 0 | return ((const SubscriptingRef *) expr)->reftypmod; |
316 | 0 | case T_FuncExpr: |
317 | 0 | { |
318 | 0 | int32 coercedTypmod; |
319 | | |
320 | | /* Be smart about length-coercion functions... */ |
321 | 0 | if (exprIsLengthCoercion(expr, &coercedTypmod)) |
322 | 0 | return coercedTypmod; |
323 | 0 | } |
324 | 0 | break; |
325 | 0 | case T_NamedArgExpr: |
326 | 0 | return exprTypmod((Node *) ((const NamedArgExpr *) expr)->arg); |
327 | 0 | case T_NullIfExpr: |
328 | 0 | { |
329 | | /* |
330 | | * Result is either first argument or NULL, so we can report |
331 | | * first argument's typmod if known. |
332 | | */ |
333 | 0 | const NullIfExpr *nexpr = (const NullIfExpr *) expr; |
334 | |
|
335 | 0 | return exprTypmod((Node *) linitial(nexpr->args)); |
336 | 0 | } |
337 | 0 | break; |
338 | 0 | case T_SubLink: |
339 | 0 | { |
340 | 0 | const SubLink *sublink = (const SubLink *) expr; |
341 | |
|
342 | 0 | if (sublink->subLinkType == EXPR_SUBLINK || |
343 | 0 | sublink->subLinkType == ARRAY_SUBLINK) |
344 | 0 | { |
345 | | /* get the typmod of the subselect's first target column */ |
346 | 0 | Query *qtree = (Query *) sublink->subselect; |
347 | 0 | TargetEntry *tent; |
348 | |
|
349 | 0 | if (!qtree || !IsA(qtree, Query)) |
350 | 0 | elog(ERROR, "cannot get type for untransformed sublink"); |
351 | 0 | tent = linitial_node(TargetEntry, qtree->targetList); |
352 | 0 | Assert(!tent->resjunk); |
353 | 0 | return exprTypmod((Node *) tent->expr); |
354 | | /* note we don't need to care if it's an array */ |
355 | 0 | } |
356 | | /* otherwise, result is RECORD or BOOLEAN, typmod is -1 */ |
357 | 0 | } |
358 | 0 | break; |
359 | 0 | case T_SubPlan: |
360 | 0 | { |
361 | 0 | const SubPlan *subplan = (const SubPlan *) expr; |
362 | |
|
363 | 0 | if (subplan->subLinkType == EXPR_SUBLINK || |
364 | 0 | subplan->subLinkType == ARRAY_SUBLINK) |
365 | 0 | { |
366 | | /* get the typmod of the subselect's first target column */ |
367 | | /* note we don't need to care if it's an array */ |
368 | 0 | return subplan->firstColTypmod; |
369 | 0 | } |
370 | | /* otherwise, result is RECORD or BOOLEAN, typmod is -1 */ |
371 | 0 | } |
372 | 0 | break; |
373 | 0 | case T_AlternativeSubPlan: |
374 | 0 | { |
375 | 0 | const AlternativeSubPlan *asplan = (const AlternativeSubPlan *) expr; |
376 | | |
377 | | /* subplans should all return the same thing */ |
378 | 0 | return exprTypmod((Node *) linitial(asplan->subplans)); |
379 | 0 | } |
380 | 0 | break; |
381 | 0 | case T_FieldSelect: |
382 | 0 | return ((const FieldSelect *) expr)->resulttypmod; |
383 | 0 | case T_RelabelType: |
384 | 0 | return ((const RelabelType *) expr)->resulttypmod; |
385 | 0 | case T_ArrayCoerceExpr: |
386 | 0 | return ((const ArrayCoerceExpr *) expr)->resulttypmod; |
387 | 0 | case T_CollateExpr: |
388 | 0 | return exprTypmod((Node *) ((const CollateExpr *) expr)->arg); |
389 | 0 | case T_CaseExpr: |
390 | 0 | { |
391 | | /* |
392 | | * If all the alternatives agree on type/typmod, return that |
393 | | * typmod, else use -1 |
394 | | */ |
395 | 0 | const CaseExpr *cexpr = (const CaseExpr *) expr; |
396 | 0 | Oid casetype = cexpr->casetype; |
397 | 0 | int32 typmod; |
398 | 0 | ListCell *arg; |
399 | |
|
400 | 0 | if (!cexpr->defresult) |
401 | 0 | return -1; |
402 | 0 | if (exprType((Node *) cexpr->defresult) != casetype) |
403 | 0 | return -1; |
404 | 0 | typmod = exprTypmod((Node *) cexpr->defresult); |
405 | 0 | if (typmod < 0) |
406 | 0 | return -1; /* no point in trying harder */ |
407 | 0 | foreach(arg, cexpr->args) |
408 | 0 | { |
409 | 0 | CaseWhen *w = lfirst_node(CaseWhen, arg); |
410 | |
|
411 | 0 | if (exprType((Node *) w->result) != casetype) |
412 | 0 | return -1; |
413 | 0 | if (exprTypmod((Node *) w->result) != typmod) |
414 | 0 | return -1; |
415 | 0 | } |
416 | 0 | return typmod; |
417 | 0 | } |
418 | 0 | break; |
419 | 0 | case T_CaseTestExpr: |
420 | 0 | return ((const CaseTestExpr *) expr)->typeMod; |
421 | 0 | case T_ArrayExpr: |
422 | 0 | { |
423 | | /* |
424 | | * If all the elements agree on type/typmod, return that |
425 | | * typmod, else use -1 |
426 | | */ |
427 | 0 | const ArrayExpr *arrayexpr = (const ArrayExpr *) expr; |
428 | 0 | Oid commontype; |
429 | 0 | int32 typmod; |
430 | 0 | ListCell *elem; |
431 | |
|
432 | 0 | if (arrayexpr->elements == NIL) |
433 | 0 | return -1; |
434 | 0 | typmod = exprTypmod((Node *) linitial(arrayexpr->elements)); |
435 | 0 | if (typmod < 0) |
436 | 0 | return -1; /* no point in trying harder */ |
437 | 0 | if (arrayexpr->multidims) |
438 | 0 | commontype = arrayexpr->array_typeid; |
439 | 0 | else |
440 | 0 | commontype = arrayexpr->element_typeid; |
441 | 0 | foreach(elem, arrayexpr->elements) |
442 | 0 | { |
443 | 0 | Node *e = (Node *) lfirst(elem); |
444 | |
|
445 | 0 | if (exprType(e) != commontype) |
446 | 0 | return -1; |
447 | 0 | if (exprTypmod(e) != typmod) |
448 | 0 | return -1; |
449 | 0 | } |
450 | 0 | return typmod; |
451 | 0 | } |
452 | 0 | break; |
453 | 0 | case T_CoalesceExpr: |
454 | 0 | { |
455 | | /* |
456 | | * If all the alternatives agree on type/typmod, return that |
457 | | * typmod, else use -1 |
458 | | */ |
459 | 0 | const CoalesceExpr *cexpr = (const CoalesceExpr *) expr; |
460 | 0 | Oid coalescetype = cexpr->coalescetype; |
461 | 0 | int32 typmod; |
462 | 0 | ListCell *arg; |
463 | |
|
464 | 0 | if (exprType((Node *) linitial(cexpr->args)) != coalescetype) |
465 | 0 | return -1; |
466 | 0 | typmod = exprTypmod((Node *) linitial(cexpr->args)); |
467 | 0 | if (typmod < 0) |
468 | 0 | return -1; /* no point in trying harder */ |
469 | 0 | for_each_from(arg, cexpr->args, 1) |
470 | 0 | { |
471 | 0 | Node *e = (Node *) lfirst(arg); |
472 | |
|
473 | 0 | if (exprType(e) != coalescetype) |
474 | 0 | return -1; |
475 | 0 | if (exprTypmod(e) != typmod) |
476 | 0 | return -1; |
477 | 0 | } |
478 | 0 | return typmod; |
479 | 0 | } |
480 | 0 | break; |
481 | 0 | case T_MinMaxExpr: |
482 | 0 | { |
483 | | /* |
484 | | * If all the alternatives agree on type/typmod, return that |
485 | | * typmod, else use -1 |
486 | | */ |
487 | 0 | const MinMaxExpr *mexpr = (const MinMaxExpr *) expr; |
488 | 0 | Oid minmaxtype = mexpr->minmaxtype; |
489 | 0 | int32 typmod; |
490 | 0 | ListCell *arg; |
491 | |
|
492 | 0 | if (exprType((Node *) linitial(mexpr->args)) != minmaxtype) |
493 | 0 | return -1; |
494 | 0 | typmod = exprTypmod((Node *) linitial(mexpr->args)); |
495 | 0 | if (typmod < 0) |
496 | 0 | return -1; /* no point in trying harder */ |
497 | 0 | for_each_from(arg, mexpr->args, 1) |
498 | 0 | { |
499 | 0 | Node *e = (Node *) lfirst(arg); |
500 | |
|
501 | 0 | if (exprType(e) != minmaxtype) |
502 | 0 | return -1; |
503 | 0 | if (exprTypmod(e) != typmod) |
504 | 0 | return -1; |
505 | 0 | } |
506 | 0 | return typmod; |
507 | 0 | } |
508 | 0 | break; |
509 | 0 | case T_SQLValueFunction: |
510 | 0 | return ((const SQLValueFunction *) expr)->typmod; |
511 | 0 | case T_JsonValueExpr: |
512 | 0 | return exprTypmod((Node *) ((const JsonValueExpr *) expr)->formatted_expr); |
513 | 0 | case T_JsonConstructorExpr: |
514 | 0 | return ((const JsonConstructorExpr *) expr)->returning->typmod; |
515 | 0 | case T_JsonExpr: |
516 | 0 | { |
517 | 0 | const JsonExpr *jexpr = (const JsonExpr *) expr; |
518 | |
|
519 | 0 | return jexpr->returning->typmod; |
520 | 0 | } |
521 | 0 | break; |
522 | 0 | case T_JsonBehavior: |
523 | 0 | { |
524 | 0 | const JsonBehavior *behavior = (const JsonBehavior *) expr; |
525 | |
|
526 | 0 | return exprTypmod(behavior->expr); |
527 | 0 | } |
528 | 0 | break; |
529 | 0 | case T_CoerceToDomain: |
530 | 0 | return ((const CoerceToDomain *) expr)->resulttypmod; |
531 | 0 | case T_CoerceToDomainValue: |
532 | 0 | return ((const CoerceToDomainValue *) expr)->typeMod; |
533 | 0 | case T_SetToDefault: |
534 | 0 | return ((const SetToDefault *) expr)->typeMod; |
535 | 0 | case T_ReturningExpr: |
536 | 0 | return exprTypmod((Node *) ((const ReturningExpr *) expr)->retexpr); |
537 | 0 | case T_PlaceHolderVar: |
538 | 0 | return exprTypmod((Node *) ((const PlaceHolderVar *) expr)->phexpr); |
539 | 0 | default: |
540 | 0 | break; |
541 | 0 | } |
542 | 0 | return -1; |
543 | 0 | } |
544 | | |
545 | | /* |
546 | | * exprIsLengthCoercion |
547 | | * Detect whether an expression tree is an application of a datatype's |
548 | | * typmod-coercion function. Optionally extract the result's typmod. |
549 | | * |
550 | | * If coercedTypmod is not NULL, the typmod is stored there if the expression |
551 | | * is a length-coercion function, else -1 is stored there. |
552 | | * |
553 | | * Note that a combined type-and-length coercion will be treated as a |
554 | | * length coercion by this routine. |
555 | | */ |
556 | | bool |
557 | | exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod) |
558 | 0 | { |
559 | 0 | if (coercedTypmod != NULL) |
560 | 0 | *coercedTypmod = -1; /* default result on failure */ |
561 | | |
562 | | /* |
563 | | * Scalar-type length coercions are FuncExprs, array-type length coercions |
564 | | * are ArrayCoerceExprs |
565 | | */ |
566 | 0 | if (expr && IsA(expr, FuncExpr)) |
567 | 0 | { |
568 | 0 | const FuncExpr *func = (const FuncExpr *) expr; |
569 | 0 | int nargs; |
570 | 0 | Const *second_arg; |
571 | | |
572 | | /* |
573 | | * If it didn't come from a coercion context, reject. |
574 | | */ |
575 | 0 | if (func->funcformat != COERCE_EXPLICIT_CAST && |
576 | 0 | func->funcformat != COERCE_IMPLICIT_CAST) |
577 | 0 | return false; |
578 | | |
579 | | /* |
580 | | * If it's not a two-argument or three-argument function with the |
581 | | * second argument being an int4 constant, it can't have been created |
582 | | * from a length coercion (it must be a type coercion, instead). |
583 | | */ |
584 | 0 | nargs = list_length(func->args); |
585 | 0 | if (nargs < 2 || nargs > 3) |
586 | 0 | return false; |
587 | | |
588 | 0 | second_arg = (Const *) lsecond(func->args); |
589 | 0 | if (!IsA(second_arg, Const) || |
590 | 0 | second_arg->consttype != INT4OID || |
591 | 0 | second_arg->constisnull) |
592 | 0 | return false; |
593 | | |
594 | | /* |
595 | | * OK, it is indeed a length-coercion function. |
596 | | */ |
597 | 0 | if (coercedTypmod != NULL) |
598 | 0 | *coercedTypmod = DatumGetInt32(second_arg->constvalue); |
599 | |
|
600 | 0 | return true; |
601 | 0 | } |
602 | | |
603 | 0 | if (expr && IsA(expr, ArrayCoerceExpr)) |
604 | 0 | { |
605 | 0 | const ArrayCoerceExpr *acoerce = (const ArrayCoerceExpr *) expr; |
606 | | |
607 | | /* It's not a length coercion unless there's a nondefault typmod */ |
608 | 0 | if (acoerce->resulttypmod < 0) |
609 | 0 | return false; |
610 | | |
611 | | /* |
612 | | * OK, it is indeed a length-coercion expression. |
613 | | */ |
614 | 0 | if (coercedTypmod != NULL) |
615 | 0 | *coercedTypmod = acoerce->resulttypmod; |
616 | |
|
617 | 0 | return true; |
618 | 0 | } |
619 | | |
620 | 0 | return false; |
621 | 0 | } |
622 | | |
623 | | /* |
624 | | * applyRelabelType |
625 | | * Add a RelabelType node if needed to make the expression expose |
626 | | * the specified type, typmod, and collation. |
627 | | * |
628 | | * This is primarily intended to be used during planning. Therefore, it must |
629 | | * maintain the post-eval_const_expressions invariants that there are not |
630 | | * adjacent RelabelTypes, and that the tree is fully const-folded (hence, |
631 | | * we mustn't return a RelabelType atop a Const). If we do find a Const, |
632 | | * we'll modify it in-place if "overwrite_ok" is true; that should only be |
633 | | * passed as true if caller knows the Const is newly generated. |
634 | | */ |
635 | | Node * |
636 | | applyRelabelType(Node *arg, Oid rtype, int32 rtypmod, Oid rcollid, |
637 | | CoercionForm rformat, int rlocation, bool overwrite_ok) |
638 | 0 | { |
639 | | /* |
640 | | * If we find stacked RelabelTypes (eg, from foo::int::oid) we can discard |
641 | | * all but the top one, and must do so to ensure that semantically |
642 | | * equivalent expressions are equal(). |
643 | | */ |
644 | 0 | while (arg && IsA(arg, RelabelType)) |
645 | 0 | arg = (Node *) ((RelabelType *) arg)->arg; |
646 | |
|
647 | 0 | if (arg && IsA(arg, Const)) |
648 | 0 | { |
649 | | /* Modify the Const directly to preserve const-flatness. */ |
650 | 0 | Const *con = (Const *) arg; |
651 | |
|
652 | 0 | if (!overwrite_ok) |
653 | 0 | con = copyObject(con); |
654 | 0 | con->consttype = rtype; |
655 | 0 | con->consttypmod = rtypmod; |
656 | 0 | con->constcollid = rcollid; |
657 | | /* We keep the Const's original location. */ |
658 | 0 | return (Node *) con; |
659 | 0 | } |
660 | 0 | else if (exprType(arg) == rtype && |
661 | 0 | exprTypmod(arg) == rtypmod && |
662 | 0 | exprCollation(arg) == rcollid) |
663 | 0 | { |
664 | | /* Sometimes we find a nest of relabels that net out to nothing. */ |
665 | 0 | return arg; |
666 | 0 | } |
667 | 0 | else |
668 | 0 | { |
669 | | /* Nope, gotta have a RelabelType. */ |
670 | 0 | RelabelType *newrelabel = makeNode(RelabelType); |
671 | |
|
672 | 0 | newrelabel->arg = (Expr *) arg; |
673 | 0 | newrelabel->resulttype = rtype; |
674 | 0 | newrelabel->resulttypmod = rtypmod; |
675 | 0 | newrelabel->resultcollid = rcollid; |
676 | 0 | newrelabel->relabelformat = rformat; |
677 | 0 | newrelabel->location = rlocation; |
678 | 0 | return (Node *) newrelabel; |
679 | 0 | } |
680 | 0 | } |
681 | | |
682 | | /* |
683 | | * relabel_to_typmod |
684 | | * Add a RelabelType node that changes just the typmod of the expression. |
685 | | * |
686 | | * Convenience function for a common usage of applyRelabelType. |
687 | | */ |
688 | | Node * |
689 | | relabel_to_typmod(Node *expr, int32 typmod) |
690 | 0 | { |
691 | 0 | return applyRelabelType(expr, exprType(expr), typmod, exprCollation(expr), |
692 | 0 | COERCE_EXPLICIT_CAST, -1, false); |
693 | 0 | } |
694 | | |
695 | | /* |
696 | | * strip_implicit_coercions: remove implicit coercions at top level of tree |
697 | | * |
698 | | * This doesn't modify or copy the input expression tree, just return a |
699 | | * pointer to a suitable place within it. |
700 | | * |
701 | | * Note: there isn't any useful thing we can do with a RowExpr here, so |
702 | | * just return it unchanged, even if it's marked as an implicit coercion. |
703 | | */ |
704 | | Node * |
705 | | strip_implicit_coercions(Node *node) |
706 | 0 | { |
707 | 0 | if (node == NULL) |
708 | 0 | return NULL; |
709 | 0 | if (IsA(node, FuncExpr)) |
710 | 0 | { |
711 | 0 | FuncExpr *f = (FuncExpr *) node; |
712 | |
|
713 | 0 | if (f->funcformat == COERCE_IMPLICIT_CAST) |
714 | 0 | return strip_implicit_coercions(linitial(f->args)); |
715 | 0 | } |
716 | 0 | else if (IsA(node, RelabelType)) |
717 | 0 | { |
718 | 0 | RelabelType *r = (RelabelType *) node; |
719 | |
|
720 | 0 | if (r->relabelformat == COERCE_IMPLICIT_CAST) |
721 | 0 | return strip_implicit_coercions((Node *) r->arg); |
722 | 0 | } |
723 | 0 | else if (IsA(node, CoerceViaIO)) |
724 | 0 | { |
725 | 0 | CoerceViaIO *c = (CoerceViaIO *) node; |
726 | |
|
727 | 0 | if (c->coerceformat == COERCE_IMPLICIT_CAST) |
728 | 0 | return strip_implicit_coercions((Node *) c->arg); |
729 | 0 | } |
730 | 0 | else if (IsA(node, ArrayCoerceExpr)) |
731 | 0 | { |
732 | 0 | ArrayCoerceExpr *c = (ArrayCoerceExpr *) node; |
733 | |
|
734 | 0 | if (c->coerceformat == COERCE_IMPLICIT_CAST) |
735 | 0 | return strip_implicit_coercions((Node *) c->arg); |
736 | 0 | } |
737 | 0 | else if (IsA(node, ConvertRowtypeExpr)) |
738 | 0 | { |
739 | 0 | ConvertRowtypeExpr *c = (ConvertRowtypeExpr *) node; |
740 | |
|
741 | 0 | if (c->convertformat == COERCE_IMPLICIT_CAST) |
742 | 0 | return strip_implicit_coercions((Node *) c->arg); |
743 | 0 | } |
744 | 0 | else if (IsA(node, CoerceToDomain)) |
745 | 0 | { |
746 | 0 | CoerceToDomain *c = (CoerceToDomain *) node; |
747 | |
|
748 | 0 | if (c->coercionformat == COERCE_IMPLICIT_CAST) |
749 | 0 | return strip_implicit_coercions((Node *) c->arg); |
750 | 0 | } |
751 | 0 | return node; |
752 | 0 | } |
753 | | |
754 | | /* |
755 | | * expression_returns_set |
756 | | * Test whether an expression returns a set result. |
757 | | * |
758 | | * Because we use expression_tree_walker(), this can also be applied to |
759 | | * whole targetlists; it'll produce true if any one of the tlist items |
760 | | * returns a set. |
761 | | */ |
762 | | bool |
763 | | expression_returns_set(Node *clause) |
764 | 0 | { |
765 | 0 | return expression_returns_set_walker(clause, NULL); |
766 | 0 | } |
767 | | |
768 | | static bool |
769 | | expression_returns_set_walker(Node *node, void *context) |
770 | 0 | { |
771 | 0 | if (node == NULL) |
772 | 0 | return false; |
773 | 0 | if (IsA(node, FuncExpr)) |
774 | 0 | { |
775 | 0 | FuncExpr *expr = (FuncExpr *) node; |
776 | |
|
777 | 0 | if (expr->funcretset) |
778 | 0 | return true; |
779 | | /* else fall through to check args */ |
780 | 0 | } |
781 | 0 | if (IsA(node, OpExpr)) |
782 | 0 | { |
783 | 0 | OpExpr *expr = (OpExpr *) node; |
784 | |
|
785 | 0 | if (expr->opretset) |
786 | 0 | return true; |
787 | | /* else fall through to check args */ |
788 | 0 | } |
789 | | |
790 | | /* |
791 | | * If you add any more cases that return sets, also fix |
792 | | * expression_returns_set_rows() in clauses.c and IS_SRF_CALL() in |
793 | | * tlist.c. |
794 | | */ |
795 | | |
796 | | /* Avoid recursion for some cases that parser checks not to return a set */ |
797 | 0 | if (IsA(node, Aggref)) |
798 | 0 | return false; |
799 | 0 | if (IsA(node, GroupingFunc)) |
800 | 0 | return false; |
801 | 0 | if (IsA(node, WindowFunc)) |
802 | 0 | return false; |
803 | | |
804 | 0 | return expression_tree_walker(node, expression_returns_set_walker, |
805 | 0 | context); |
806 | 0 | } |
807 | | |
808 | | |
809 | | /* |
810 | | * exprCollation - |
811 | | * returns the Oid of the collation of the expression's result. |
812 | | * |
813 | | * Note: expression nodes that can invoke functions generally have an |
814 | | * "inputcollid" field, which is what the function should use as collation. |
815 | | * That is the resolved common collation of the node's inputs. It is often |
816 | | * but not always the same as the result collation; in particular, if the |
817 | | * function produces a non-collatable result type from collatable inputs |
818 | | * or vice versa, the two are different. |
819 | | */ |
820 | | Oid |
821 | | exprCollation(const Node *expr) |
822 | 0 | { |
823 | 0 | Oid coll; |
824 | |
|
825 | 0 | if (!expr) |
826 | 0 | return InvalidOid; |
827 | | |
828 | 0 | switch (nodeTag(expr)) |
829 | 0 | { |
830 | 0 | case T_Var: |
831 | 0 | coll = ((const Var *) expr)->varcollid; |
832 | 0 | break; |
833 | 0 | case T_Const: |
834 | 0 | coll = ((const Const *) expr)->constcollid; |
835 | 0 | break; |
836 | 0 | case T_Param: |
837 | 0 | coll = ((const Param *) expr)->paramcollid; |
838 | 0 | break; |
839 | 0 | case T_Aggref: |
840 | 0 | coll = ((const Aggref *) expr)->aggcollid; |
841 | 0 | break; |
842 | 0 | case T_GroupingFunc: |
843 | 0 | coll = InvalidOid; |
844 | 0 | break; |
845 | 0 | case T_WindowFunc: |
846 | 0 | coll = ((const WindowFunc *) expr)->wincollid; |
847 | 0 | break; |
848 | 0 | case T_MergeSupportFunc: |
849 | 0 | coll = ((const MergeSupportFunc *) expr)->msfcollid; |
850 | 0 | break; |
851 | 0 | case T_SubscriptingRef: |
852 | 0 | coll = ((const SubscriptingRef *) expr)->refcollid; |
853 | 0 | break; |
854 | 0 | case T_FuncExpr: |
855 | 0 | coll = ((const FuncExpr *) expr)->funccollid; |
856 | 0 | break; |
857 | 0 | case T_NamedArgExpr: |
858 | 0 | coll = exprCollation((Node *) ((const NamedArgExpr *) expr)->arg); |
859 | 0 | break; |
860 | 0 | case T_OpExpr: |
861 | 0 | coll = ((const OpExpr *) expr)->opcollid; |
862 | 0 | break; |
863 | 0 | case T_DistinctExpr: |
864 | 0 | coll = ((const DistinctExpr *) expr)->opcollid; |
865 | 0 | break; |
866 | 0 | case T_NullIfExpr: |
867 | 0 | coll = ((const NullIfExpr *) expr)->opcollid; |
868 | 0 | break; |
869 | 0 | case T_ScalarArrayOpExpr: |
870 | | /* ScalarArrayOpExpr's result is boolean ... */ |
871 | 0 | coll = InvalidOid; /* ... so it has no collation */ |
872 | 0 | break; |
873 | 0 | case T_BoolExpr: |
874 | | /* BoolExpr's result is boolean ... */ |
875 | 0 | coll = InvalidOid; /* ... so it has no collation */ |
876 | 0 | break; |
877 | 0 | case T_SubLink: |
878 | 0 | { |
879 | 0 | const SubLink *sublink = (const SubLink *) expr; |
880 | |
|
881 | 0 | if (sublink->subLinkType == EXPR_SUBLINK || |
882 | 0 | sublink->subLinkType == ARRAY_SUBLINK) |
883 | 0 | { |
884 | | /* get the collation of subselect's first target column */ |
885 | 0 | Query *qtree = (Query *) sublink->subselect; |
886 | 0 | TargetEntry *tent; |
887 | |
|
888 | 0 | if (!qtree || !IsA(qtree, Query)) |
889 | 0 | elog(ERROR, "cannot get collation for untransformed sublink"); |
890 | 0 | tent = linitial_node(TargetEntry, qtree->targetList); |
891 | 0 | Assert(!tent->resjunk); |
892 | 0 | coll = exprCollation((Node *) tent->expr); |
893 | | /* collation doesn't change if it's converted to array */ |
894 | 0 | } |
895 | 0 | else |
896 | 0 | { |
897 | | /* otherwise, SubLink's result is RECORD or BOOLEAN */ |
898 | 0 | coll = InvalidOid; /* ... so it has no collation */ |
899 | 0 | } |
900 | 0 | } |
901 | 0 | break; |
902 | 0 | case T_SubPlan: |
903 | 0 | { |
904 | 0 | const SubPlan *subplan = (const SubPlan *) expr; |
905 | |
|
906 | 0 | if (subplan->subLinkType == EXPR_SUBLINK || |
907 | 0 | subplan->subLinkType == ARRAY_SUBLINK) |
908 | 0 | { |
909 | | /* get the collation of subselect's first target column */ |
910 | 0 | coll = subplan->firstColCollation; |
911 | | /* collation doesn't change if it's converted to array */ |
912 | 0 | } |
913 | 0 | else |
914 | 0 | { |
915 | | /* otherwise, SubPlan's result is RECORD or BOOLEAN */ |
916 | 0 | coll = InvalidOid; /* ... so it has no collation */ |
917 | 0 | } |
918 | 0 | } |
919 | 0 | break; |
920 | 0 | case T_AlternativeSubPlan: |
921 | 0 | { |
922 | 0 | const AlternativeSubPlan *asplan = (const AlternativeSubPlan *) expr; |
923 | | |
924 | | /* subplans should all return the same thing */ |
925 | 0 | coll = exprCollation((Node *) linitial(asplan->subplans)); |
926 | 0 | } |
927 | 0 | break; |
928 | 0 | case T_FieldSelect: |
929 | 0 | coll = ((const FieldSelect *) expr)->resultcollid; |
930 | 0 | break; |
931 | 0 | case T_FieldStore: |
932 | | /* FieldStore's result is composite ... */ |
933 | 0 | coll = InvalidOid; /* ... so it has no collation */ |
934 | 0 | break; |
935 | 0 | case T_RelabelType: |
936 | 0 | coll = ((const RelabelType *) expr)->resultcollid; |
937 | 0 | break; |
938 | 0 | case T_CoerceViaIO: |
939 | 0 | coll = ((const CoerceViaIO *) expr)->resultcollid; |
940 | 0 | break; |
941 | 0 | case T_ArrayCoerceExpr: |
942 | 0 | coll = ((const ArrayCoerceExpr *) expr)->resultcollid; |
943 | 0 | break; |
944 | 0 | case T_ConvertRowtypeExpr: |
945 | | /* ConvertRowtypeExpr's result is composite ... */ |
946 | 0 | coll = InvalidOid; /* ... so it has no collation */ |
947 | 0 | break; |
948 | 0 | case T_CollateExpr: |
949 | 0 | coll = ((const CollateExpr *) expr)->collOid; |
950 | 0 | break; |
951 | 0 | case T_CaseExpr: |
952 | 0 | coll = ((const CaseExpr *) expr)->casecollid; |
953 | 0 | break; |
954 | 0 | case T_CaseTestExpr: |
955 | 0 | coll = ((const CaseTestExpr *) expr)->collation; |
956 | 0 | break; |
957 | 0 | case T_ArrayExpr: |
958 | 0 | coll = ((const ArrayExpr *) expr)->array_collid; |
959 | 0 | break; |
960 | 0 | case T_RowExpr: |
961 | | /* RowExpr's result is composite ... */ |
962 | 0 | coll = InvalidOid; /* ... so it has no collation */ |
963 | 0 | break; |
964 | 0 | case T_RowCompareExpr: |
965 | | /* RowCompareExpr's result is boolean ... */ |
966 | 0 | coll = InvalidOid; /* ... so it has no collation */ |
967 | 0 | break; |
968 | 0 | case T_CoalesceExpr: |
969 | 0 | coll = ((const CoalesceExpr *) expr)->coalescecollid; |
970 | 0 | break; |
971 | 0 | case T_MinMaxExpr: |
972 | 0 | coll = ((const MinMaxExpr *) expr)->minmaxcollid; |
973 | 0 | break; |
974 | 0 | case T_SQLValueFunction: |
975 | | /* Returns either NAME or a non-collatable type */ |
976 | 0 | if (((const SQLValueFunction *) expr)->type == NAMEOID) |
977 | 0 | coll = C_COLLATION_OID; |
978 | 0 | else |
979 | 0 | coll = InvalidOid; |
980 | 0 | break; |
981 | 0 | case T_XmlExpr: |
982 | | |
983 | | /* |
984 | | * XMLSERIALIZE returns text from non-collatable inputs, so its |
985 | | * collation is always default. The other cases return boolean or |
986 | | * XML, which are non-collatable. |
987 | | */ |
988 | 0 | if (((const XmlExpr *) expr)->op == IS_XMLSERIALIZE) |
989 | 0 | coll = DEFAULT_COLLATION_OID; |
990 | 0 | else |
991 | 0 | coll = InvalidOid; |
992 | 0 | break; |
993 | 0 | case T_JsonValueExpr: |
994 | 0 | coll = exprCollation((Node *) ((const JsonValueExpr *) expr)->formatted_expr); |
995 | 0 | break; |
996 | 0 | case T_JsonConstructorExpr: |
997 | 0 | { |
998 | 0 | const JsonConstructorExpr *ctor = (const JsonConstructorExpr *) expr; |
999 | | |
1000 | | /* |
1001 | | * Collation comes from coercion if present, otherwise from |
1002 | | * func. The func fallback is needed in cases where func |
1003 | | * already produces the final output type and no coercion is |
1004 | | * needed (cf. the JSCTOR_JSON_ARRAY_QUERY case). |
1005 | | */ |
1006 | 0 | if (ctor->coercion) |
1007 | 0 | coll = exprCollation((Node *) ctor->coercion); |
1008 | 0 | else if (ctor->func) |
1009 | 0 | coll = exprCollation((Node *) ctor->func); |
1010 | 0 | else |
1011 | 0 | coll = InvalidOid; |
1012 | 0 | } |
1013 | 0 | break; |
1014 | 0 | case T_JsonIsPredicate: |
1015 | | /* IS JSON's result is boolean ... */ |
1016 | 0 | coll = InvalidOid; /* ... so it has no collation */ |
1017 | 0 | break; |
1018 | 0 | case T_JsonExpr: |
1019 | 0 | { |
1020 | 0 | const JsonExpr *jsexpr = (const JsonExpr *) expr; |
1021 | |
|
1022 | 0 | coll = jsexpr->collation; |
1023 | 0 | } |
1024 | 0 | break; |
1025 | 0 | case T_JsonBehavior: |
1026 | 0 | { |
1027 | 0 | const JsonBehavior *behavior = (const JsonBehavior *) expr; |
1028 | |
|
1029 | 0 | if (behavior->expr) |
1030 | 0 | coll = exprCollation(behavior->expr); |
1031 | 0 | else |
1032 | 0 | coll = InvalidOid; |
1033 | 0 | } |
1034 | 0 | break; |
1035 | 0 | case T_NullTest: |
1036 | | /* NullTest's result is boolean ... */ |
1037 | 0 | coll = InvalidOid; /* ... so it has no collation */ |
1038 | 0 | break; |
1039 | 0 | case T_BooleanTest: |
1040 | | /* BooleanTest's result is boolean ... */ |
1041 | 0 | coll = InvalidOid; /* ... so it has no collation */ |
1042 | 0 | break; |
1043 | 0 | case T_CoerceToDomain: |
1044 | 0 | coll = ((const CoerceToDomain *) expr)->resultcollid; |
1045 | 0 | break; |
1046 | 0 | case T_CoerceToDomainValue: |
1047 | 0 | coll = ((const CoerceToDomainValue *) expr)->collation; |
1048 | 0 | break; |
1049 | 0 | case T_SetToDefault: |
1050 | 0 | coll = ((const SetToDefault *) expr)->collation; |
1051 | 0 | break; |
1052 | 0 | case T_CurrentOfExpr: |
1053 | | /* CurrentOfExpr's result is boolean ... */ |
1054 | 0 | coll = InvalidOid; /* ... so it has no collation */ |
1055 | 0 | break; |
1056 | 0 | case T_NextValueExpr: |
1057 | | /* NextValueExpr's result is an integer type ... */ |
1058 | 0 | coll = InvalidOid; /* ... so it has no collation */ |
1059 | 0 | break; |
1060 | 0 | case T_InferenceElem: |
1061 | 0 | coll = exprCollation((Node *) ((const InferenceElem *) expr)->expr); |
1062 | 0 | break; |
1063 | 0 | case T_ReturningExpr: |
1064 | 0 | coll = exprCollation((Node *) ((const ReturningExpr *) expr)->retexpr); |
1065 | 0 | break; |
1066 | 0 | case T_PlaceHolderVar: |
1067 | 0 | coll = exprCollation((Node *) ((const PlaceHolderVar *) expr)->phexpr); |
1068 | 0 | break; |
1069 | 0 | default: |
1070 | 0 | elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr)); |
1071 | 0 | coll = InvalidOid; /* keep compiler quiet */ |
1072 | 0 | break; |
1073 | 0 | } |
1074 | 0 | return coll; |
1075 | 0 | } |
1076 | | |
1077 | | /* |
1078 | | * exprInputCollation - |
1079 | | * returns the Oid of the collation a function should use, if available. |
1080 | | * |
1081 | | * Result is InvalidOid if the node type doesn't store this information. |
1082 | | */ |
1083 | | Oid |
1084 | | exprInputCollation(const Node *expr) |
1085 | 0 | { |
1086 | 0 | Oid coll; |
1087 | |
|
1088 | 0 | if (!expr) |
1089 | 0 | return InvalidOid; |
1090 | | |
1091 | 0 | switch (nodeTag(expr)) |
1092 | 0 | { |
1093 | 0 | case T_Aggref: |
1094 | 0 | coll = ((const Aggref *) expr)->inputcollid; |
1095 | 0 | break; |
1096 | 0 | case T_WindowFunc: |
1097 | 0 | coll = ((const WindowFunc *) expr)->inputcollid; |
1098 | 0 | break; |
1099 | 0 | case T_FuncExpr: |
1100 | 0 | coll = ((const FuncExpr *) expr)->inputcollid; |
1101 | 0 | break; |
1102 | 0 | case T_OpExpr: |
1103 | 0 | coll = ((const OpExpr *) expr)->inputcollid; |
1104 | 0 | break; |
1105 | 0 | case T_DistinctExpr: |
1106 | 0 | coll = ((const DistinctExpr *) expr)->inputcollid; |
1107 | 0 | break; |
1108 | 0 | case T_NullIfExpr: |
1109 | 0 | coll = ((const NullIfExpr *) expr)->inputcollid; |
1110 | 0 | break; |
1111 | 0 | case T_ScalarArrayOpExpr: |
1112 | 0 | coll = ((const ScalarArrayOpExpr *) expr)->inputcollid; |
1113 | 0 | break; |
1114 | 0 | case T_MinMaxExpr: |
1115 | 0 | coll = ((const MinMaxExpr *) expr)->inputcollid; |
1116 | 0 | break; |
1117 | 0 | default: |
1118 | 0 | coll = InvalidOid; |
1119 | 0 | break; |
1120 | 0 | } |
1121 | 0 | return coll; |
1122 | 0 | } |
1123 | | |
1124 | | /* |
1125 | | * exprSetCollation - |
1126 | | * Assign collation information to an expression tree node. |
1127 | | * |
1128 | | * Note: since this is only used during parse analysis, we don't need to |
1129 | | * worry about subplans, PlaceHolderVars, or ReturningExprs. |
1130 | | */ |
1131 | | void |
1132 | | exprSetCollation(Node *expr, Oid collation) |
1133 | 0 | { |
1134 | 0 | switch (nodeTag(expr)) |
1135 | 0 | { |
1136 | 0 | case T_Var: |
1137 | 0 | ((Var *) expr)->varcollid = collation; |
1138 | 0 | break; |
1139 | 0 | case T_Const: |
1140 | 0 | ((Const *) expr)->constcollid = collation; |
1141 | 0 | break; |
1142 | 0 | case T_Param: |
1143 | 0 | ((Param *) expr)->paramcollid = collation; |
1144 | 0 | break; |
1145 | 0 | case T_Aggref: |
1146 | 0 | ((Aggref *) expr)->aggcollid = collation; |
1147 | 0 | break; |
1148 | 0 | case T_GroupingFunc: |
1149 | 0 | Assert(!OidIsValid(collation)); |
1150 | 0 | break; |
1151 | 0 | case T_WindowFunc: |
1152 | 0 | ((WindowFunc *) expr)->wincollid = collation; |
1153 | 0 | break; |
1154 | 0 | case T_MergeSupportFunc: |
1155 | 0 | ((MergeSupportFunc *) expr)->msfcollid = collation; |
1156 | 0 | break; |
1157 | 0 | case T_SubscriptingRef: |
1158 | 0 | ((SubscriptingRef *) expr)->refcollid = collation; |
1159 | 0 | break; |
1160 | 0 | case T_FuncExpr: |
1161 | 0 | ((FuncExpr *) expr)->funccollid = collation; |
1162 | 0 | break; |
1163 | 0 | case T_NamedArgExpr: |
1164 | 0 | Assert(collation == exprCollation((Node *) ((NamedArgExpr *) expr)->arg)); |
1165 | 0 | break; |
1166 | 0 | case T_OpExpr: |
1167 | 0 | ((OpExpr *) expr)->opcollid = collation; |
1168 | 0 | break; |
1169 | 0 | case T_DistinctExpr: |
1170 | 0 | ((DistinctExpr *) expr)->opcollid = collation; |
1171 | 0 | break; |
1172 | 0 | case T_NullIfExpr: |
1173 | 0 | ((NullIfExpr *) expr)->opcollid = collation; |
1174 | 0 | break; |
1175 | 0 | case T_ScalarArrayOpExpr: |
1176 | | /* ScalarArrayOpExpr's result is boolean ... */ |
1177 | 0 | Assert(!OidIsValid(collation)); /* ... so never set a collation */ |
1178 | 0 | break; |
1179 | 0 | case T_BoolExpr: |
1180 | | /* BoolExpr's result is boolean ... */ |
1181 | 0 | Assert(!OidIsValid(collation)); /* ... so never set a collation */ |
1182 | 0 | break; |
1183 | 0 | case T_SubLink: |
1184 | | #ifdef USE_ASSERT_CHECKING |
1185 | | { |
1186 | | SubLink *sublink = (SubLink *) expr; |
1187 | | |
1188 | | if (sublink->subLinkType == EXPR_SUBLINK || |
1189 | | sublink->subLinkType == ARRAY_SUBLINK) |
1190 | | { |
1191 | | /* get the collation of subselect's first target column */ |
1192 | | Query *qtree = (Query *) sublink->subselect; |
1193 | | TargetEntry *tent; |
1194 | | |
1195 | | if (!qtree || !IsA(qtree, Query)) |
1196 | | elog(ERROR, "cannot set collation for untransformed sublink"); |
1197 | | tent = linitial_node(TargetEntry, qtree->targetList); |
1198 | | Assert(!tent->resjunk); |
1199 | | Assert(collation == exprCollation((Node *) tent->expr)); |
1200 | | } |
1201 | | else |
1202 | | { |
1203 | | /* otherwise, result is RECORD or BOOLEAN */ |
1204 | | Assert(!OidIsValid(collation)); |
1205 | | } |
1206 | | } |
1207 | | #endif /* USE_ASSERT_CHECKING */ |
1208 | 0 | break; |
1209 | 0 | case T_FieldSelect: |
1210 | 0 | ((FieldSelect *) expr)->resultcollid = collation; |
1211 | 0 | break; |
1212 | 0 | case T_FieldStore: |
1213 | | /* FieldStore's result is composite ... */ |
1214 | 0 | Assert(!OidIsValid(collation)); /* ... so never set a collation */ |
1215 | 0 | break; |
1216 | 0 | case T_RelabelType: |
1217 | 0 | ((RelabelType *) expr)->resultcollid = collation; |
1218 | 0 | break; |
1219 | 0 | case T_CoerceViaIO: |
1220 | 0 | ((CoerceViaIO *) expr)->resultcollid = collation; |
1221 | 0 | break; |
1222 | 0 | case T_ArrayCoerceExpr: |
1223 | 0 | ((ArrayCoerceExpr *) expr)->resultcollid = collation; |
1224 | 0 | break; |
1225 | 0 | case T_ConvertRowtypeExpr: |
1226 | | /* ConvertRowtypeExpr's result is composite ... */ |
1227 | 0 | Assert(!OidIsValid(collation)); /* ... so never set a collation */ |
1228 | 0 | break; |
1229 | 0 | case T_CaseExpr: |
1230 | 0 | ((CaseExpr *) expr)->casecollid = collation; |
1231 | 0 | break; |
1232 | 0 | case T_ArrayExpr: |
1233 | 0 | ((ArrayExpr *) expr)->array_collid = collation; |
1234 | 0 | break; |
1235 | 0 | case T_RowExpr: |
1236 | | /* RowExpr's result is composite ... */ |
1237 | 0 | Assert(!OidIsValid(collation)); /* ... so never set a collation */ |
1238 | 0 | break; |
1239 | 0 | case T_RowCompareExpr: |
1240 | | /* RowCompareExpr's result is boolean ... */ |
1241 | 0 | Assert(!OidIsValid(collation)); /* ... so never set a collation */ |
1242 | 0 | break; |
1243 | 0 | case T_CoalesceExpr: |
1244 | 0 | ((CoalesceExpr *) expr)->coalescecollid = collation; |
1245 | 0 | break; |
1246 | 0 | case T_MinMaxExpr: |
1247 | 0 | ((MinMaxExpr *) expr)->minmaxcollid = collation; |
1248 | 0 | break; |
1249 | 0 | case T_SQLValueFunction: |
1250 | 0 | Assert((((SQLValueFunction *) expr)->type == NAMEOID) ? |
1251 | 0 | (collation == C_COLLATION_OID) : |
1252 | 0 | (collation == InvalidOid)); |
1253 | 0 | break; |
1254 | 0 | case T_XmlExpr: |
1255 | 0 | Assert((((XmlExpr *) expr)->op == IS_XMLSERIALIZE) ? |
1256 | 0 | (collation == DEFAULT_COLLATION_OID) : |
1257 | 0 | (collation == InvalidOid)); |
1258 | 0 | break; |
1259 | 0 | case T_JsonValueExpr: |
1260 | 0 | exprSetCollation((Node *) ((JsonValueExpr *) expr)->formatted_expr, |
1261 | 0 | collation); |
1262 | 0 | break; |
1263 | 0 | case T_JsonConstructorExpr: |
1264 | 0 | { |
1265 | 0 | JsonConstructorExpr *ctor = (JsonConstructorExpr *) expr; |
1266 | | |
1267 | | /* See comment in exprCollation() */ |
1268 | 0 | if (ctor->coercion) |
1269 | 0 | exprSetCollation((Node *) ctor->coercion, collation); |
1270 | 0 | else if (ctor->func) |
1271 | 0 | exprSetCollation((Node *) ctor->func, collation); |
1272 | 0 | else |
1273 | 0 | Assert(!OidIsValid(collation)); /* result is always a |
1274 | | * json[b] type */ |
1275 | 0 | } |
1276 | 0 | break; |
1277 | 0 | case T_JsonIsPredicate: |
1278 | 0 | Assert(!OidIsValid(collation)); /* result is always boolean */ |
1279 | 0 | break; |
1280 | 0 | case T_JsonExpr: |
1281 | 0 | { |
1282 | 0 | JsonExpr *jexpr = (JsonExpr *) expr; |
1283 | |
|
1284 | 0 | jexpr->collation = collation; |
1285 | 0 | } |
1286 | 0 | break; |
1287 | 0 | case T_JsonBehavior: |
1288 | 0 | Assert(((JsonBehavior *) expr)->expr == NULL || |
1289 | 0 | exprCollation(((JsonBehavior *) expr)->expr) == collation); |
1290 | 0 | break; |
1291 | 0 | case T_NullTest: |
1292 | | /* NullTest's result is boolean ... */ |
1293 | 0 | Assert(!OidIsValid(collation)); /* ... so never set a collation */ |
1294 | 0 | break; |
1295 | 0 | case T_BooleanTest: |
1296 | | /* BooleanTest's result is boolean ... */ |
1297 | 0 | Assert(!OidIsValid(collation)); /* ... so never set a collation */ |
1298 | 0 | break; |
1299 | 0 | case T_CoerceToDomain: |
1300 | 0 | ((CoerceToDomain *) expr)->resultcollid = collation; |
1301 | 0 | break; |
1302 | 0 | case T_CoerceToDomainValue: |
1303 | 0 | ((CoerceToDomainValue *) expr)->collation = collation; |
1304 | 0 | break; |
1305 | 0 | case T_SetToDefault: |
1306 | 0 | ((SetToDefault *) expr)->collation = collation; |
1307 | 0 | break; |
1308 | 0 | case T_CurrentOfExpr: |
1309 | | /* CurrentOfExpr's result is boolean ... */ |
1310 | 0 | Assert(!OidIsValid(collation)); /* ... so never set a collation */ |
1311 | 0 | break; |
1312 | 0 | case T_NextValueExpr: |
1313 | | /* NextValueExpr's result is an integer type ... */ |
1314 | 0 | Assert(!OidIsValid(collation)); /* ... so never set a collation */ |
1315 | 0 | break; |
1316 | 0 | default: |
1317 | 0 | elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr)); |
1318 | 0 | break; |
1319 | 0 | } |
1320 | 0 | } |
1321 | | |
1322 | | /* |
1323 | | * exprSetInputCollation - |
1324 | | * Assign input-collation information to an expression tree node. |
1325 | | * |
1326 | | * This is a no-op for node types that don't store their input collation. |
1327 | | * Note we omit RowCompareExpr, which needs special treatment since it |
1328 | | * contains multiple input collation OIDs. |
1329 | | */ |
1330 | | void |
1331 | | exprSetInputCollation(Node *expr, Oid inputcollation) |
1332 | 0 | { |
1333 | 0 | switch (nodeTag(expr)) |
1334 | 0 | { |
1335 | 0 | case T_Aggref: |
1336 | 0 | ((Aggref *) expr)->inputcollid = inputcollation; |
1337 | 0 | break; |
1338 | 0 | case T_WindowFunc: |
1339 | 0 | ((WindowFunc *) expr)->inputcollid = inputcollation; |
1340 | 0 | break; |
1341 | 0 | case T_FuncExpr: |
1342 | 0 | ((FuncExpr *) expr)->inputcollid = inputcollation; |
1343 | 0 | break; |
1344 | 0 | case T_OpExpr: |
1345 | 0 | ((OpExpr *) expr)->inputcollid = inputcollation; |
1346 | 0 | break; |
1347 | 0 | case T_DistinctExpr: |
1348 | 0 | ((DistinctExpr *) expr)->inputcollid = inputcollation; |
1349 | 0 | break; |
1350 | 0 | case T_NullIfExpr: |
1351 | 0 | ((NullIfExpr *) expr)->inputcollid = inputcollation; |
1352 | 0 | break; |
1353 | 0 | case T_ScalarArrayOpExpr: |
1354 | 0 | ((ScalarArrayOpExpr *) expr)->inputcollid = inputcollation; |
1355 | 0 | break; |
1356 | 0 | case T_MinMaxExpr: |
1357 | 0 | ((MinMaxExpr *) expr)->inputcollid = inputcollation; |
1358 | 0 | break; |
1359 | 0 | default: |
1360 | 0 | break; |
1361 | 0 | } |
1362 | 0 | } |
1363 | | |
1364 | | |
1365 | | /* |
1366 | | * exprLocation - |
1367 | | * returns the parse location of an expression tree, for error reports |
1368 | | * |
1369 | | * -1 is returned if the location can't be determined. |
1370 | | * |
1371 | | * For expressions larger than a single token, the intent here is to |
1372 | | * return the location of the expression's leftmost token, not necessarily |
1373 | | * the topmost Node's location field. For example, an OpExpr's location |
1374 | | * field will point at the operator name, but if it is not a prefix operator |
1375 | | * then we should return the location of the left-hand operand instead. |
1376 | | * The reason is that we want to reference the entire expression not just |
1377 | | * that operator, and pointing to its start seems to be the most natural way. |
1378 | | * |
1379 | | * The location is not perfect --- for example, since the grammar doesn't |
1380 | | * explicitly represent parentheses in the parsetree, given something that |
1381 | | * had been written "(a + b) * c" we are going to point at "a" not "(". |
1382 | | * But it should be plenty good enough for error reporting purposes. |
1383 | | * |
1384 | | * You might think that this code is overly general, for instance why check |
1385 | | * the operands of a FuncExpr node, when the function name can be expected |
1386 | | * to be to the left of them? There are a couple of reasons. The grammar |
1387 | | * sometimes builds expressions that aren't quite what the user wrote; |
1388 | | * for instance x IS NOT BETWEEN ... becomes a NOT-expression whose keyword |
1389 | | * pointer is to the right of its leftmost argument. Also, nodes that were |
1390 | | * inserted implicitly by parse analysis (such as FuncExprs for implicit |
1391 | | * coercions) will have location -1, and so we can have odd combinations of |
1392 | | * known and unknown locations in a tree. |
1393 | | */ |
1394 | | int |
1395 | | exprLocation(const Node *expr) |
1396 | 0 | { |
1397 | 0 | int loc; |
1398 | |
|
1399 | 0 | if (expr == NULL) |
1400 | 0 | return -1; |
1401 | 0 | switch (nodeTag(expr)) |
1402 | 0 | { |
1403 | 0 | case T_RangeVar: |
1404 | 0 | loc = ((const RangeVar *) expr)->location; |
1405 | 0 | break; |
1406 | 0 | case T_TableFunc: |
1407 | 0 | loc = ((const TableFunc *) expr)->location; |
1408 | 0 | break; |
1409 | 0 | case T_Var: |
1410 | 0 | loc = ((const Var *) expr)->location; |
1411 | 0 | break; |
1412 | 0 | case T_Const: |
1413 | 0 | loc = ((const Const *) expr)->location; |
1414 | 0 | break; |
1415 | 0 | case T_Param: |
1416 | 0 | loc = ((const Param *) expr)->location; |
1417 | 0 | break; |
1418 | 0 | case T_Aggref: |
1419 | | /* function name should always be the first thing */ |
1420 | 0 | loc = ((const Aggref *) expr)->location; |
1421 | 0 | break; |
1422 | 0 | case T_GroupingFunc: |
1423 | 0 | loc = ((const GroupingFunc *) expr)->location; |
1424 | 0 | break; |
1425 | 0 | case T_WindowFunc: |
1426 | | /* function name should always be the first thing */ |
1427 | 0 | loc = ((const WindowFunc *) expr)->location; |
1428 | 0 | break; |
1429 | 0 | case T_MergeSupportFunc: |
1430 | 0 | loc = ((const MergeSupportFunc *) expr)->location; |
1431 | 0 | break; |
1432 | 0 | case T_SubscriptingRef: |
1433 | | /* just use container argument's location */ |
1434 | 0 | loc = exprLocation((Node *) ((const SubscriptingRef *) expr)->refexpr); |
1435 | 0 | break; |
1436 | 0 | case T_FuncExpr: |
1437 | 0 | { |
1438 | 0 | const FuncExpr *fexpr = (const FuncExpr *) expr; |
1439 | | |
1440 | | /* consider both function name and leftmost arg */ |
1441 | 0 | loc = leftmostLoc(fexpr->location, |
1442 | 0 | exprLocation((Node *) fexpr->args)); |
1443 | 0 | } |
1444 | 0 | break; |
1445 | 0 | case T_NamedArgExpr: |
1446 | 0 | { |
1447 | 0 | const NamedArgExpr *na = (const NamedArgExpr *) expr; |
1448 | | |
1449 | | /* consider both argument name and value */ |
1450 | 0 | loc = leftmostLoc(na->location, |
1451 | 0 | exprLocation((Node *) na->arg)); |
1452 | 0 | } |
1453 | 0 | break; |
1454 | 0 | case T_OpExpr: |
1455 | 0 | case T_DistinctExpr: /* struct-equivalent to OpExpr */ |
1456 | 0 | case T_NullIfExpr: /* struct-equivalent to OpExpr */ |
1457 | 0 | { |
1458 | 0 | const OpExpr *opexpr = (const OpExpr *) expr; |
1459 | | |
1460 | | /* consider both operator name and leftmost arg */ |
1461 | 0 | loc = leftmostLoc(opexpr->location, |
1462 | 0 | exprLocation((Node *) opexpr->args)); |
1463 | 0 | } |
1464 | 0 | break; |
1465 | 0 | case T_ScalarArrayOpExpr: |
1466 | 0 | { |
1467 | 0 | const ScalarArrayOpExpr *saopexpr = (const ScalarArrayOpExpr *) expr; |
1468 | | |
1469 | | /* consider both operator name and leftmost arg */ |
1470 | 0 | loc = leftmostLoc(saopexpr->location, |
1471 | 0 | exprLocation((Node *) saopexpr->args)); |
1472 | 0 | } |
1473 | 0 | break; |
1474 | 0 | case T_BoolExpr: |
1475 | 0 | { |
1476 | 0 | const BoolExpr *bexpr = (const BoolExpr *) expr; |
1477 | | |
1478 | | /* |
1479 | | * Same as above, to handle either NOT or AND/OR. We can't |
1480 | | * special-case NOT because of the way that it's used for |
1481 | | * things like IS NOT BETWEEN. |
1482 | | */ |
1483 | 0 | loc = leftmostLoc(bexpr->location, |
1484 | 0 | exprLocation((Node *) bexpr->args)); |
1485 | 0 | } |
1486 | 0 | break; |
1487 | 0 | case T_SubLink: |
1488 | 0 | { |
1489 | 0 | const SubLink *sublink = (const SubLink *) expr; |
1490 | | |
1491 | | /* check the testexpr, if any, and the operator/keyword */ |
1492 | 0 | loc = leftmostLoc(exprLocation(sublink->testexpr), |
1493 | 0 | sublink->location); |
1494 | 0 | } |
1495 | 0 | break; |
1496 | 0 | case T_FieldSelect: |
1497 | | /* just use argument's location */ |
1498 | 0 | loc = exprLocation((Node *) ((const FieldSelect *) expr)->arg); |
1499 | 0 | break; |
1500 | 0 | case T_FieldStore: |
1501 | | /* just use argument's location */ |
1502 | 0 | loc = exprLocation((Node *) ((const FieldStore *) expr)->arg); |
1503 | 0 | break; |
1504 | 0 | case T_RelabelType: |
1505 | 0 | { |
1506 | 0 | const RelabelType *rexpr = (const RelabelType *) expr; |
1507 | | |
1508 | | /* Much as above */ |
1509 | 0 | loc = leftmostLoc(rexpr->location, |
1510 | 0 | exprLocation((Node *) rexpr->arg)); |
1511 | 0 | } |
1512 | 0 | break; |
1513 | 0 | case T_CoerceViaIO: |
1514 | 0 | { |
1515 | 0 | const CoerceViaIO *cexpr = (const CoerceViaIO *) expr; |
1516 | | |
1517 | | /* Much as above */ |
1518 | 0 | loc = leftmostLoc(cexpr->location, |
1519 | 0 | exprLocation((Node *) cexpr->arg)); |
1520 | 0 | } |
1521 | 0 | break; |
1522 | 0 | case T_ArrayCoerceExpr: |
1523 | 0 | { |
1524 | 0 | const ArrayCoerceExpr *cexpr = (const ArrayCoerceExpr *) expr; |
1525 | | |
1526 | | /* Much as above */ |
1527 | 0 | loc = leftmostLoc(cexpr->location, |
1528 | 0 | exprLocation((Node *) cexpr->arg)); |
1529 | 0 | } |
1530 | 0 | break; |
1531 | 0 | case T_ConvertRowtypeExpr: |
1532 | 0 | { |
1533 | 0 | const ConvertRowtypeExpr *cexpr = (const ConvertRowtypeExpr *) expr; |
1534 | | |
1535 | | /* Much as above */ |
1536 | 0 | loc = leftmostLoc(cexpr->location, |
1537 | 0 | exprLocation((Node *) cexpr->arg)); |
1538 | 0 | } |
1539 | 0 | break; |
1540 | 0 | case T_CollateExpr: |
1541 | | /* just use argument's location */ |
1542 | 0 | loc = exprLocation((Node *) ((const CollateExpr *) expr)->arg); |
1543 | 0 | break; |
1544 | 0 | case T_CaseExpr: |
1545 | | /* CASE keyword should always be the first thing */ |
1546 | 0 | loc = ((const CaseExpr *) expr)->location; |
1547 | 0 | break; |
1548 | 0 | case T_CaseWhen: |
1549 | | /* WHEN keyword should always be the first thing */ |
1550 | 0 | loc = ((const CaseWhen *) expr)->location; |
1551 | 0 | break; |
1552 | 0 | case T_ArrayExpr: |
1553 | | /* the location points at ARRAY or [, which must be leftmost */ |
1554 | 0 | loc = ((const ArrayExpr *) expr)->location; |
1555 | 0 | break; |
1556 | 0 | case T_RowExpr: |
1557 | | /* the location points at ROW or (, which must be leftmost */ |
1558 | 0 | loc = ((const RowExpr *) expr)->location; |
1559 | 0 | break; |
1560 | 0 | case T_RowCompareExpr: |
1561 | | /* just use leftmost argument's location */ |
1562 | 0 | loc = exprLocation((Node *) ((const RowCompareExpr *) expr)->largs); |
1563 | 0 | break; |
1564 | 0 | case T_CoalesceExpr: |
1565 | | /* COALESCE keyword should always be the first thing */ |
1566 | 0 | loc = ((const CoalesceExpr *) expr)->location; |
1567 | 0 | break; |
1568 | 0 | case T_MinMaxExpr: |
1569 | | /* GREATEST/LEAST keyword should always be the first thing */ |
1570 | 0 | loc = ((const MinMaxExpr *) expr)->location; |
1571 | 0 | break; |
1572 | 0 | case T_SQLValueFunction: |
1573 | | /* function keyword should always be the first thing */ |
1574 | 0 | loc = ((const SQLValueFunction *) expr)->location; |
1575 | 0 | break; |
1576 | 0 | case T_XmlExpr: |
1577 | 0 | { |
1578 | 0 | const XmlExpr *xexpr = (const XmlExpr *) expr; |
1579 | | |
1580 | | /* consider both function name and leftmost arg */ |
1581 | 0 | loc = leftmostLoc(xexpr->location, |
1582 | 0 | exprLocation((Node *) xexpr->args)); |
1583 | 0 | } |
1584 | 0 | break; |
1585 | 0 | case T_JsonFormat: |
1586 | 0 | loc = ((const JsonFormat *) expr)->location; |
1587 | 0 | break; |
1588 | 0 | case T_JsonValueExpr: |
1589 | 0 | loc = exprLocation((Node *) ((const JsonValueExpr *) expr)->raw_expr); |
1590 | 0 | break; |
1591 | 0 | case T_JsonConstructorExpr: |
1592 | 0 | loc = ((const JsonConstructorExpr *) expr)->location; |
1593 | 0 | break; |
1594 | 0 | case T_JsonIsPredicate: |
1595 | 0 | loc = ((const JsonIsPredicate *) expr)->location; |
1596 | 0 | break; |
1597 | 0 | case T_JsonExpr: |
1598 | 0 | { |
1599 | 0 | const JsonExpr *jsexpr = (const JsonExpr *) expr; |
1600 | | |
1601 | | /* consider both function name and leftmost arg */ |
1602 | 0 | loc = leftmostLoc(jsexpr->location, |
1603 | 0 | exprLocation(jsexpr->formatted_expr)); |
1604 | 0 | } |
1605 | 0 | break; |
1606 | 0 | case T_JsonBehavior: |
1607 | 0 | loc = exprLocation(((const JsonBehavior *) expr)->expr); |
1608 | 0 | break; |
1609 | 0 | case T_NullTest: |
1610 | 0 | { |
1611 | 0 | const NullTest *nexpr = (const NullTest *) expr; |
1612 | | |
1613 | | /* Much as above */ |
1614 | 0 | loc = leftmostLoc(nexpr->location, |
1615 | 0 | exprLocation((Node *) nexpr->arg)); |
1616 | 0 | } |
1617 | 0 | break; |
1618 | 0 | case T_BooleanTest: |
1619 | 0 | { |
1620 | 0 | const BooleanTest *bexpr = (const BooleanTest *) expr; |
1621 | | |
1622 | | /* Much as above */ |
1623 | 0 | loc = leftmostLoc(bexpr->location, |
1624 | 0 | exprLocation((Node *) bexpr->arg)); |
1625 | 0 | } |
1626 | 0 | break; |
1627 | 0 | case T_CoerceToDomain: |
1628 | 0 | { |
1629 | 0 | const CoerceToDomain *cexpr = (const CoerceToDomain *) expr; |
1630 | | |
1631 | | /* Much as above */ |
1632 | 0 | loc = leftmostLoc(cexpr->location, |
1633 | 0 | exprLocation((Node *) cexpr->arg)); |
1634 | 0 | } |
1635 | 0 | break; |
1636 | 0 | case T_CoerceToDomainValue: |
1637 | 0 | loc = ((const CoerceToDomainValue *) expr)->location; |
1638 | 0 | break; |
1639 | 0 | case T_SetToDefault: |
1640 | 0 | loc = ((const SetToDefault *) expr)->location; |
1641 | 0 | break; |
1642 | 0 | case T_ReturningExpr: |
1643 | 0 | loc = exprLocation((Node *) ((const ReturningExpr *) expr)->retexpr); |
1644 | 0 | break; |
1645 | 0 | case T_TargetEntry: |
1646 | | /* just use argument's location */ |
1647 | 0 | loc = exprLocation((Node *) ((const TargetEntry *) expr)->expr); |
1648 | 0 | break; |
1649 | 0 | case T_IntoClause: |
1650 | | /* use the contained RangeVar's location --- close enough */ |
1651 | 0 | loc = exprLocation((Node *) ((const IntoClause *) expr)->rel); |
1652 | 0 | break; |
1653 | 0 | case T_List: |
1654 | 0 | { |
1655 | | /* report location of first list member that has a location */ |
1656 | 0 | ListCell *lc; |
1657 | |
|
1658 | 0 | loc = -1; /* just to suppress compiler warning */ |
1659 | 0 | foreach(lc, (const List *) expr) |
1660 | 0 | { |
1661 | 0 | loc = exprLocation((Node *) lfirst(lc)); |
1662 | 0 | if (loc >= 0) |
1663 | 0 | break; |
1664 | 0 | } |
1665 | 0 | } |
1666 | 0 | break; |
1667 | 0 | case T_A_Expr: |
1668 | 0 | { |
1669 | 0 | const A_Expr *aexpr = (const A_Expr *) expr; |
1670 | | |
1671 | | /* use leftmost of operator or left operand (if any) */ |
1672 | | /* we assume right operand can't be to left of operator */ |
1673 | 0 | loc = leftmostLoc(aexpr->location, |
1674 | 0 | exprLocation(aexpr->lexpr)); |
1675 | 0 | } |
1676 | 0 | break; |
1677 | 0 | case T_ColumnRef: |
1678 | 0 | loc = ((const ColumnRef *) expr)->location; |
1679 | 0 | break; |
1680 | 0 | case T_ParamRef: |
1681 | 0 | loc = ((const ParamRef *) expr)->location; |
1682 | 0 | break; |
1683 | 0 | case T_A_Const: |
1684 | 0 | loc = ((const A_Const *) expr)->location; |
1685 | 0 | break; |
1686 | 0 | case T_FuncCall: |
1687 | 0 | { |
1688 | 0 | const FuncCall *fc = (const FuncCall *) expr; |
1689 | | |
1690 | | /* consider both function name and leftmost arg */ |
1691 | | /* (we assume any ORDER BY nodes must be to right of name) */ |
1692 | 0 | loc = leftmostLoc(fc->location, |
1693 | 0 | exprLocation((Node *) fc->args)); |
1694 | 0 | } |
1695 | 0 | break; |
1696 | 0 | case T_A_ArrayExpr: |
1697 | | /* the location points at ARRAY or [, which must be leftmost */ |
1698 | 0 | loc = ((const A_ArrayExpr *) expr)->location; |
1699 | 0 | break; |
1700 | 0 | case T_ResTarget: |
1701 | | /* we need not examine the contained expression (if any) */ |
1702 | 0 | loc = ((const ResTarget *) expr)->location; |
1703 | 0 | break; |
1704 | 0 | case T_MultiAssignRef: |
1705 | 0 | loc = exprLocation(((const MultiAssignRef *) expr)->source); |
1706 | 0 | break; |
1707 | 0 | case T_TypeCast: |
1708 | 0 | { |
1709 | 0 | const TypeCast *tc = (const TypeCast *) expr; |
1710 | | |
1711 | | /* |
1712 | | * This could represent CAST(), ::, or TypeName 'literal', so |
1713 | | * any of the components might be leftmost. |
1714 | | */ |
1715 | 0 | loc = exprLocation(tc->arg); |
1716 | 0 | loc = leftmostLoc(loc, tc->typeName->location); |
1717 | 0 | loc = leftmostLoc(loc, tc->location); |
1718 | 0 | } |
1719 | 0 | break; |
1720 | 0 | case T_CollateClause: |
1721 | | /* just use argument's location */ |
1722 | 0 | loc = exprLocation(((const CollateClause *) expr)->arg); |
1723 | 0 | break; |
1724 | 0 | case T_SortBy: |
1725 | | /* just use argument's location (ignore operator, if any) */ |
1726 | 0 | loc = exprLocation(((const SortBy *) expr)->node); |
1727 | 0 | break; |
1728 | 0 | case T_WindowDef: |
1729 | 0 | loc = ((const WindowDef *) expr)->location; |
1730 | 0 | break; |
1731 | 0 | case T_RangeTableSample: |
1732 | 0 | loc = ((const RangeTableSample *) expr)->location; |
1733 | 0 | break; |
1734 | 0 | case T_TypeName: |
1735 | 0 | loc = ((const TypeName *) expr)->location; |
1736 | 0 | break; |
1737 | 0 | case T_ColumnDef: |
1738 | 0 | loc = ((const ColumnDef *) expr)->location; |
1739 | 0 | break; |
1740 | 0 | case T_IndexElem: |
1741 | 0 | loc = ((const IndexElem *) expr)->location; |
1742 | 0 | break; |
1743 | 0 | case T_Constraint: |
1744 | 0 | loc = ((const Constraint *) expr)->location; |
1745 | 0 | break; |
1746 | 0 | case T_FunctionParameter: |
1747 | 0 | loc = ((const FunctionParameter *) expr)->location; |
1748 | 0 | break; |
1749 | 0 | case T_XmlSerialize: |
1750 | | /* XMLSERIALIZE keyword should always be the first thing */ |
1751 | 0 | loc = ((const XmlSerialize *) expr)->location; |
1752 | 0 | break; |
1753 | 0 | case T_GroupingSet: |
1754 | 0 | loc = ((const GroupingSet *) expr)->location; |
1755 | 0 | break; |
1756 | 0 | case T_WithClause: |
1757 | 0 | loc = ((const WithClause *) expr)->location; |
1758 | 0 | break; |
1759 | 0 | case T_InferClause: |
1760 | 0 | loc = ((const InferClause *) expr)->location; |
1761 | 0 | break; |
1762 | 0 | case T_OnConflictClause: |
1763 | 0 | loc = ((const OnConflictClause *) expr)->location; |
1764 | 0 | break; |
1765 | 0 | case T_CTESearchClause: |
1766 | 0 | loc = ((const CTESearchClause *) expr)->location; |
1767 | 0 | break; |
1768 | 0 | case T_CTECycleClause: |
1769 | 0 | loc = ((const CTECycleClause *) expr)->location; |
1770 | 0 | break; |
1771 | 0 | case T_CommonTableExpr: |
1772 | 0 | loc = ((const CommonTableExpr *) expr)->location; |
1773 | 0 | break; |
1774 | 0 | case T_JsonKeyValue: |
1775 | | /* just use the key's location */ |
1776 | 0 | loc = exprLocation((Node *) ((const JsonKeyValue *) expr)->key); |
1777 | 0 | break; |
1778 | 0 | case T_JsonObjectConstructor: |
1779 | 0 | loc = ((const JsonObjectConstructor *) expr)->location; |
1780 | 0 | break; |
1781 | 0 | case T_JsonArrayConstructor: |
1782 | 0 | loc = ((const JsonArrayConstructor *) expr)->location; |
1783 | 0 | break; |
1784 | 0 | case T_JsonArrayQueryConstructor: |
1785 | 0 | loc = ((const JsonArrayQueryConstructor *) expr)->location; |
1786 | 0 | break; |
1787 | 0 | case T_JsonAggConstructor: |
1788 | 0 | loc = ((const JsonAggConstructor *) expr)->location; |
1789 | 0 | break; |
1790 | 0 | case T_JsonObjectAgg: |
1791 | 0 | loc = exprLocation((Node *) ((const JsonObjectAgg *) expr)->constructor); |
1792 | 0 | break; |
1793 | 0 | case T_JsonArrayAgg: |
1794 | 0 | loc = exprLocation((Node *) ((const JsonArrayAgg *) expr)->constructor); |
1795 | 0 | break; |
1796 | 0 | case T_PlaceHolderVar: |
1797 | | /* just use argument's location */ |
1798 | 0 | loc = exprLocation((Node *) ((const PlaceHolderVar *) expr)->phexpr); |
1799 | 0 | break; |
1800 | 0 | case T_InferenceElem: |
1801 | | /* just use nested expr's location */ |
1802 | 0 | loc = exprLocation((Node *) ((const InferenceElem *) expr)->expr); |
1803 | 0 | break; |
1804 | 0 | case T_PartitionElem: |
1805 | 0 | loc = ((const PartitionElem *) expr)->location; |
1806 | 0 | break; |
1807 | 0 | case T_PartitionSpec: |
1808 | 0 | loc = ((const PartitionSpec *) expr)->location; |
1809 | 0 | break; |
1810 | 0 | case T_PartitionBoundSpec: |
1811 | 0 | loc = ((const PartitionBoundSpec *) expr)->location; |
1812 | 0 | break; |
1813 | 0 | case T_PartitionRangeDatum: |
1814 | 0 | loc = ((const PartitionRangeDatum *) expr)->location; |
1815 | 0 | break; |
1816 | 0 | default: |
1817 | | /* for any other node type it's just unknown... */ |
1818 | 0 | loc = -1; |
1819 | 0 | break; |
1820 | 0 | } |
1821 | 0 | return loc; |
1822 | 0 | } |
1823 | | |
1824 | | /* |
1825 | | * leftmostLoc - support for exprLocation |
1826 | | * |
1827 | | * Take the minimum of two parse location values, but ignore unknowns |
1828 | | */ |
1829 | | static int |
1830 | | leftmostLoc(int loc1, int loc2) |
1831 | 0 | { |
1832 | 0 | if (loc1 < 0) |
1833 | 0 | return loc2; |
1834 | 0 | else if (loc2 < 0) |
1835 | 0 | return loc1; |
1836 | 0 | else |
1837 | 0 | return Min(loc1, loc2); |
1838 | 0 | } |
1839 | | |
1840 | | |
1841 | | /* |
1842 | | * fix_opfuncids |
1843 | | * Calculate opfuncid field from opno for each OpExpr node in given tree. |
1844 | | * The given tree can be anything expression_tree_walker handles. |
1845 | | * |
1846 | | * The argument is modified in-place. (This is OK since we'd want the |
1847 | | * same change for any node, even if it gets visited more than once due to |
1848 | | * shared structure.) |
1849 | | */ |
1850 | | void |
1851 | | fix_opfuncids(Node *node) |
1852 | 0 | { |
1853 | | /* This tree walk requires no special setup, so away we go... */ |
1854 | 0 | fix_opfuncids_walker(node, NULL); |
1855 | 0 | } |
1856 | | |
1857 | | static bool |
1858 | | fix_opfuncids_walker(Node *node, void *context) |
1859 | 0 | { |
1860 | 0 | if (node == NULL) |
1861 | 0 | return false; |
1862 | 0 | if (IsA(node, OpExpr)) |
1863 | 0 | set_opfuncid((OpExpr *) node); |
1864 | 0 | else if (IsA(node, DistinctExpr)) |
1865 | 0 | set_opfuncid((OpExpr *) node); /* rely on struct equivalence */ |
1866 | 0 | else if (IsA(node, NullIfExpr)) |
1867 | 0 | set_opfuncid((OpExpr *) node); /* rely on struct equivalence */ |
1868 | 0 | else if (IsA(node, ScalarArrayOpExpr)) |
1869 | 0 | set_sa_opfuncid((ScalarArrayOpExpr *) node); |
1870 | 0 | return expression_tree_walker(node, fix_opfuncids_walker, context); |
1871 | 0 | } |
1872 | | |
1873 | | /* |
1874 | | * set_opfuncid |
1875 | | * Set the opfuncid (procedure OID) in an OpExpr node, |
1876 | | * if it hasn't been set already. |
1877 | | * |
1878 | | * Because of struct equivalence, this can also be used for |
1879 | | * DistinctExpr and NullIfExpr nodes. |
1880 | | */ |
1881 | | void |
1882 | | set_opfuncid(OpExpr *opexpr) |
1883 | 0 | { |
1884 | 0 | if (opexpr->opfuncid == InvalidOid) |
1885 | 0 | opexpr->opfuncid = get_opcode(opexpr->opno); |
1886 | 0 | } |
1887 | | |
1888 | | /* |
1889 | | * set_sa_opfuncid |
1890 | | * As above, for ScalarArrayOpExpr nodes. |
1891 | | */ |
1892 | | void |
1893 | | set_sa_opfuncid(ScalarArrayOpExpr *opexpr) |
1894 | 0 | { |
1895 | 0 | if (opexpr->opfuncid == InvalidOid) |
1896 | 0 | opexpr->opfuncid = get_opcode(opexpr->opno); |
1897 | 0 | } |
1898 | | |
1899 | | |
1900 | | /* |
1901 | | * check_functions_in_node - |
1902 | | * apply checker() to each function OID contained in given expression node |
1903 | | * |
1904 | | * Returns true if the checker() function does; for nodes representing more |
1905 | | * than one function call, returns true if the checker() function does so |
1906 | | * for any of those functions. Returns false if node does not invoke any |
1907 | | * SQL-visible function. Caller must not pass node == NULL. |
1908 | | * |
1909 | | * This function examines only the given node; it does not recurse into any |
1910 | | * sub-expressions. Callers typically prefer to keep control of the recursion |
1911 | | * for themselves, in case additional checks should be made, or because they |
1912 | | * have special rules about which parts of the tree need to be visited. |
1913 | | * |
1914 | | * Note: we ignore MinMaxExpr, SQLValueFunction, XmlExpr, CoerceToDomain, |
1915 | | * and NextValueExpr nodes, because they do not contain SQL function OIDs. |
1916 | | * However, they can invoke SQL-visible functions, so callers should take |
1917 | | * thought about how to treat them. |
1918 | | */ |
1919 | | bool |
1920 | | check_functions_in_node(Node *node, check_function_callback checker, |
1921 | | void *context) |
1922 | 0 | { |
1923 | 0 | switch (nodeTag(node)) |
1924 | 0 | { |
1925 | 0 | case T_Aggref: |
1926 | 0 | { |
1927 | 0 | Aggref *expr = (Aggref *) node; |
1928 | |
|
1929 | 0 | if (checker(expr->aggfnoid, context)) |
1930 | 0 | return true; |
1931 | 0 | } |
1932 | 0 | break; |
1933 | 0 | case T_WindowFunc: |
1934 | 0 | { |
1935 | 0 | WindowFunc *expr = (WindowFunc *) node; |
1936 | |
|
1937 | 0 | if (checker(expr->winfnoid, context)) |
1938 | 0 | return true; |
1939 | 0 | } |
1940 | 0 | break; |
1941 | 0 | case T_FuncExpr: |
1942 | 0 | { |
1943 | 0 | FuncExpr *expr = (FuncExpr *) node; |
1944 | |
|
1945 | 0 | if (checker(expr->funcid, context)) |
1946 | 0 | return true; |
1947 | 0 | } |
1948 | 0 | break; |
1949 | 0 | case T_OpExpr: |
1950 | 0 | case T_DistinctExpr: /* struct-equivalent to OpExpr */ |
1951 | 0 | case T_NullIfExpr: /* struct-equivalent to OpExpr */ |
1952 | 0 | { |
1953 | 0 | OpExpr *expr = (OpExpr *) node; |
1954 | | |
1955 | | /* Set opfuncid if it wasn't set already */ |
1956 | 0 | set_opfuncid(expr); |
1957 | 0 | if (checker(expr->opfuncid, context)) |
1958 | 0 | return true; |
1959 | 0 | } |
1960 | 0 | break; |
1961 | 0 | case T_ScalarArrayOpExpr: |
1962 | 0 | { |
1963 | 0 | ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; |
1964 | |
|
1965 | 0 | set_sa_opfuncid(expr); |
1966 | 0 | if (checker(expr->opfuncid, context)) |
1967 | 0 | return true; |
1968 | 0 | } |
1969 | 0 | break; |
1970 | 0 | case T_CoerceViaIO: |
1971 | 0 | { |
1972 | 0 | CoerceViaIO *expr = (CoerceViaIO *) node; |
1973 | 0 | Oid iofunc; |
1974 | 0 | Oid typioparam; |
1975 | 0 | bool typisvarlena; |
1976 | | |
1977 | | /* check the result type's input function */ |
1978 | 0 | getTypeInputInfo(expr->resulttype, |
1979 | 0 | &iofunc, &typioparam); |
1980 | 0 | if (checker(iofunc, context)) |
1981 | 0 | return true; |
1982 | | /* check the input type's output function */ |
1983 | 0 | getTypeOutputInfo(exprType((Node *) expr->arg), |
1984 | 0 | &iofunc, &typisvarlena); |
1985 | 0 | if (checker(iofunc, context)) |
1986 | 0 | return true; |
1987 | 0 | } |
1988 | 0 | break; |
1989 | 0 | case T_RowCompareExpr: |
1990 | 0 | { |
1991 | 0 | RowCompareExpr *rcexpr = (RowCompareExpr *) node; |
1992 | 0 | ListCell *opid; |
1993 | |
|
1994 | 0 | foreach(opid, rcexpr->opnos) |
1995 | 0 | { |
1996 | 0 | Oid opfuncid = get_opcode(lfirst_oid(opid)); |
1997 | |
|
1998 | 0 | if (checker(opfuncid, context)) |
1999 | 0 | return true; |
2000 | 0 | } |
2001 | 0 | } |
2002 | 0 | break; |
2003 | 0 | default: |
2004 | 0 | break; |
2005 | 0 | } |
2006 | 0 | return false; |
2007 | 0 | } |
2008 | | |
2009 | | |
2010 | | /* |
2011 | | * Standard expression-tree walking support |
2012 | | * |
2013 | | * We used to have near-duplicate code in many different routines that |
2014 | | * understood how to recurse through an expression node tree. That was |
2015 | | * a pain to maintain, and we frequently had bugs due to some particular |
2016 | | * routine neglecting to support a particular node type. In most cases, |
2017 | | * these routines only actually care about certain node types, and don't |
2018 | | * care about other types except insofar as they have to recurse through |
2019 | | * non-primitive node types. Therefore, we now provide generic tree-walking |
2020 | | * logic to consolidate the redundant "boilerplate" code. There are |
2021 | | * two versions: expression_tree_walker() and expression_tree_mutator(). |
2022 | | */ |
2023 | | |
2024 | | /* |
2025 | | * expression_tree_walker() is designed to support routines that traverse |
2026 | | * a tree in a read-only fashion (although it will also work for routines |
2027 | | * that modify nodes in-place but never add/delete/replace nodes). |
2028 | | * A walker routine should look like this: |
2029 | | * |
2030 | | * bool my_walker (Node *node, my_struct *context) |
2031 | | * { |
2032 | | * if (node == NULL) |
2033 | | * return false; |
2034 | | * // check for nodes that special work is required for, eg: |
2035 | | * if (IsA(node, Var)) |
2036 | | * { |
2037 | | * ... do special actions for Var nodes |
2038 | | * } |
2039 | | * else if (IsA(node, ...)) |
2040 | | * { |
2041 | | * ... do special actions for other node types |
2042 | | * } |
2043 | | * // for any node type not specially processed, do: |
2044 | | * return expression_tree_walker(node, my_walker, context); |
2045 | | * } |
2046 | | * |
2047 | | * The "context" argument points to a struct that holds whatever context |
2048 | | * information the walker routine needs --- it can be used to return data |
2049 | | * gathered by the walker, too. This argument is not touched by |
2050 | | * expression_tree_walker, but it is passed down to recursive sub-invocations |
2051 | | * of my_walker. The tree walk is started from a setup routine that |
2052 | | * fills in the appropriate context struct, calls my_walker with the top-level |
2053 | | * node of the tree, and then examines the results. |
2054 | | * |
2055 | | * The walker routine should return "false" to continue the tree walk, or |
2056 | | * "true" to abort the walk and immediately return "true" to the top-level |
2057 | | * caller. This can be used to short-circuit the traversal if the walker |
2058 | | * has found what it came for. "false" is returned to the top-level caller |
2059 | | * iff no invocation of the walker returned "true". |
2060 | | * |
2061 | | * The node types handled by expression_tree_walker include all those |
2062 | | * normally found in target lists and qualifier clauses during the planning |
2063 | | * stage. In particular, it handles List nodes since a cnf-ified qual clause |
2064 | | * will have List structure at the top level, and it handles TargetEntry nodes |
2065 | | * so that a scan of a target list can be handled without additional code. |
2066 | | * Also, RangeTblRef, FromExpr, JoinExpr, and SetOperationStmt nodes are |
2067 | | * handled, so that query jointrees and setOperation trees can be processed |
2068 | | * without additional code. |
2069 | | * |
2070 | | * expression_tree_walker will handle SubLink nodes by recursing normally |
2071 | | * into the "testexpr" subtree (which is an expression belonging to the outer |
2072 | | * plan). It will also call the walker on the sub-Query node; however, when |
2073 | | * expression_tree_walker itself is called on a Query node, it does nothing |
2074 | | * and returns "false". The net effect is that unless the walker does |
2075 | | * something special at a Query node, sub-selects will not be visited during |
2076 | | * an expression tree walk. This is exactly the behavior wanted in many cases |
2077 | | * --- and for those walkers that do want to recurse into sub-selects, special |
2078 | | * behavior is typically needed anyway at the entry to a sub-select (such as |
2079 | | * incrementing a depth counter). A walker that wants to examine sub-selects |
2080 | | * should include code along the lines of: |
2081 | | * |
2082 | | * if (IsA(node, Query)) |
2083 | | * { |
2084 | | * adjust context for subquery; |
2085 | | * result = query_tree_walker((Query *) node, my_walker, context, |
2086 | | * 0); // adjust flags as needed |
2087 | | * restore context if needed; |
2088 | | * return result; |
2089 | | * } |
2090 | | * |
2091 | | * query_tree_walker is a convenience routine (see below) that calls the |
2092 | | * walker on all the expression subtrees of the given Query node. |
2093 | | * |
2094 | | * expression_tree_walker will handle SubPlan nodes by recursing normally |
2095 | | * into the "testexpr" and the "args" list (which are expressions belonging to |
2096 | | * the outer plan). It will not touch the completed subplan, however. Since |
2097 | | * there is no link to the original Query, it is not possible to recurse into |
2098 | | * subselects of an already-planned expression tree. This is OK for current |
2099 | | * uses, but may need to be revisited in future. |
2100 | | */ |
2101 | | |
2102 | | pg_attribute_no_sanitize_function() |
2103 | | bool |
2104 | | expression_tree_walker_impl(Node *node, |
2105 | | tree_walker_callback walker, |
2106 | | void *context) |
2107 | 0 | { |
2108 | 0 | ListCell *temp; |
2109 | | |
2110 | | /* |
2111 | | * The walker has already visited the current node, and so we need only |
2112 | | * recurse into any sub-nodes it has. |
2113 | | * |
2114 | | * We assume that the walker is not interested in List nodes per se, so |
2115 | | * when we expect a List we just recurse directly to self without |
2116 | | * bothering to call the walker. |
2117 | | */ |
2118 | 0 | #define WALK(n) walker((Node *) (n), context) |
2119 | |
|
2120 | 0 | #define LIST_WALK(l) expression_tree_walker_impl((Node *) (l), walker, context) |
2121 | |
|
2122 | 0 | if (node == NULL) |
2123 | 0 | return false; |
2124 | | |
2125 | | /* Guard against stack overflow due to overly complex expressions */ |
2126 | 0 | check_stack_depth(); |
2127 | |
|
2128 | 0 | switch (nodeTag(node)) |
2129 | 0 | { |
2130 | 0 | case T_Var: |
2131 | 0 | case T_Const: |
2132 | 0 | case T_Param: |
2133 | 0 | case T_CaseTestExpr: |
2134 | 0 | case T_SQLValueFunction: |
2135 | 0 | case T_CoerceToDomainValue: |
2136 | 0 | case T_SetToDefault: |
2137 | 0 | case T_CurrentOfExpr: |
2138 | 0 | case T_NextValueExpr: |
2139 | 0 | case T_RangeTblRef: |
2140 | 0 | case T_SortGroupClause: |
2141 | 0 | case T_CTESearchClause: |
2142 | 0 | case T_MergeSupportFunc: |
2143 | | /* primitive node types with no expression subnodes */ |
2144 | 0 | break; |
2145 | 0 | case T_WithCheckOption: |
2146 | 0 | return WALK(((WithCheckOption *) node)->qual); |
2147 | 0 | case T_Aggref: |
2148 | 0 | { |
2149 | 0 | Aggref *expr = (Aggref *) node; |
2150 | | |
2151 | | /* recurse directly on Lists */ |
2152 | 0 | if (LIST_WALK(expr->aggdirectargs)) |
2153 | 0 | return true; |
2154 | 0 | if (LIST_WALK(expr->args)) |
2155 | 0 | return true; |
2156 | 0 | if (LIST_WALK(expr->aggorder)) |
2157 | 0 | return true; |
2158 | 0 | if (LIST_WALK(expr->aggdistinct)) |
2159 | 0 | return true; |
2160 | 0 | if (WALK(expr->aggfilter)) |
2161 | 0 | return true; |
2162 | 0 | } |
2163 | 0 | break; |
2164 | 0 | case T_GroupingFunc: |
2165 | 0 | { |
2166 | 0 | GroupingFunc *grouping = (GroupingFunc *) node; |
2167 | |
|
2168 | 0 | if (LIST_WALK(grouping->args)) |
2169 | 0 | return true; |
2170 | 0 | } |
2171 | 0 | break; |
2172 | 0 | case T_WindowFunc: |
2173 | 0 | { |
2174 | 0 | WindowFunc *expr = (WindowFunc *) node; |
2175 | | |
2176 | | /* recurse directly on List */ |
2177 | 0 | if (LIST_WALK(expr->args)) |
2178 | 0 | return true; |
2179 | 0 | if (WALK(expr->aggfilter)) |
2180 | 0 | return true; |
2181 | 0 | if (WALK(expr->runCondition)) |
2182 | 0 | return true; |
2183 | 0 | } |
2184 | 0 | break; |
2185 | 0 | case T_WindowFuncRunCondition: |
2186 | 0 | { |
2187 | 0 | WindowFuncRunCondition *expr = (WindowFuncRunCondition *) node; |
2188 | |
|
2189 | 0 | if (WALK(expr->arg)) |
2190 | 0 | return true; |
2191 | 0 | } |
2192 | 0 | break; |
2193 | 0 | case T_SubscriptingRef: |
2194 | 0 | { |
2195 | 0 | SubscriptingRef *sbsref = (SubscriptingRef *) node; |
2196 | | |
2197 | | /* recurse directly for upper/lower container index lists */ |
2198 | 0 | if (LIST_WALK(sbsref->refupperindexpr)) |
2199 | 0 | return true; |
2200 | 0 | if (LIST_WALK(sbsref->reflowerindexpr)) |
2201 | 0 | return true; |
2202 | | /* walker must see the refexpr and refassgnexpr, however */ |
2203 | 0 | if (WALK(sbsref->refexpr)) |
2204 | 0 | return true; |
2205 | | |
2206 | 0 | if (WALK(sbsref->refassgnexpr)) |
2207 | 0 | return true; |
2208 | 0 | } |
2209 | 0 | break; |
2210 | 0 | case T_FuncExpr: |
2211 | 0 | { |
2212 | 0 | FuncExpr *expr = (FuncExpr *) node; |
2213 | |
|
2214 | 0 | if (LIST_WALK(expr->args)) |
2215 | 0 | return true; |
2216 | 0 | } |
2217 | 0 | break; |
2218 | 0 | case T_NamedArgExpr: |
2219 | 0 | return WALK(((NamedArgExpr *) node)->arg); |
2220 | 0 | case T_OpExpr: |
2221 | 0 | case T_DistinctExpr: /* struct-equivalent to OpExpr */ |
2222 | 0 | case T_NullIfExpr: /* struct-equivalent to OpExpr */ |
2223 | 0 | { |
2224 | 0 | OpExpr *expr = (OpExpr *) node; |
2225 | |
|
2226 | 0 | if (LIST_WALK(expr->args)) |
2227 | 0 | return true; |
2228 | 0 | } |
2229 | 0 | break; |
2230 | 0 | case T_ScalarArrayOpExpr: |
2231 | 0 | { |
2232 | 0 | ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; |
2233 | |
|
2234 | 0 | if (LIST_WALK(expr->args)) |
2235 | 0 | return true; |
2236 | 0 | } |
2237 | 0 | break; |
2238 | 0 | case T_BoolExpr: |
2239 | 0 | { |
2240 | 0 | BoolExpr *expr = (BoolExpr *) node; |
2241 | |
|
2242 | 0 | if (LIST_WALK(expr->args)) |
2243 | 0 | return true; |
2244 | 0 | } |
2245 | 0 | break; |
2246 | 0 | case T_SubLink: |
2247 | 0 | { |
2248 | 0 | SubLink *sublink = (SubLink *) node; |
2249 | |
|
2250 | 0 | if (WALK(sublink->testexpr)) |
2251 | 0 | return true; |
2252 | | |
2253 | | /* |
2254 | | * Also invoke the walker on the sublink's Query node, so it |
2255 | | * can recurse into the sub-query if it wants to. |
2256 | | */ |
2257 | 0 | return WALK(sublink->subselect); |
2258 | 0 | } |
2259 | 0 | break; |
2260 | 0 | case T_SubPlan: |
2261 | 0 | { |
2262 | 0 | SubPlan *subplan = (SubPlan *) node; |
2263 | | |
2264 | | /* recurse into the testexpr, but not into the Plan */ |
2265 | 0 | if (WALK(subplan->testexpr)) |
2266 | 0 | return true; |
2267 | | /* also examine args list */ |
2268 | 0 | if (LIST_WALK(subplan->args)) |
2269 | 0 | return true; |
2270 | 0 | } |
2271 | 0 | break; |
2272 | 0 | case T_AlternativeSubPlan: |
2273 | 0 | return LIST_WALK(((AlternativeSubPlan *) node)->subplans); |
2274 | 0 | case T_FieldSelect: |
2275 | 0 | return WALK(((FieldSelect *) node)->arg); |
2276 | 0 | case T_FieldStore: |
2277 | 0 | { |
2278 | 0 | FieldStore *fstore = (FieldStore *) node; |
2279 | |
|
2280 | 0 | if (WALK(fstore->arg)) |
2281 | 0 | return true; |
2282 | 0 | if (WALK(fstore->newvals)) |
2283 | 0 | return true; |
2284 | 0 | } |
2285 | 0 | break; |
2286 | 0 | case T_RelabelType: |
2287 | 0 | return WALK(((RelabelType *) node)->arg); |
2288 | 0 | case T_CoerceViaIO: |
2289 | 0 | return WALK(((CoerceViaIO *) node)->arg); |
2290 | 0 | case T_ArrayCoerceExpr: |
2291 | 0 | { |
2292 | 0 | ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; |
2293 | |
|
2294 | 0 | if (WALK(acoerce->arg)) |
2295 | 0 | return true; |
2296 | 0 | if (WALK(acoerce->elemexpr)) |
2297 | 0 | return true; |
2298 | 0 | } |
2299 | 0 | break; |
2300 | 0 | case T_ConvertRowtypeExpr: |
2301 | 0 | return WALK(((ConvertRowtypeExpr *) node)->arg); |
2302 | 0 | case T_CollateExpr: |
2303 | 0 | return WALK(((CollateExpr *) node)->arg); |
2304 | 0 | case T_CaseExpr: |
2305 | 0 | { |
2306 | 0 | CaseExpr *caseexpr = (CaseExpr *) node; |
2307 | |
|
2308 | 0 | if (WALK(caseexpr->arg)) |
2309 | 0 | return true; |
2310 | | /* we assume walker doesn't care about CaseWhens, either */ |
2311 | 0 | foreach(temp, caseexpr->args) |
2312 | 0 | { |
2313 | 0 | CaseWhen *when = lfirst_node(CaseWhen, temp); |
2314 | |
|
2315 | 0 | if (WALK(when->expr)) |
2316 | 0 | return true; |
2317 | 0 | if (WALK(when->result)) |
2318 | 0 | return true; |
2319 | 0 | } |
2320 | 0 | if (WALK(caseexpr->defresult)) |
2321 | 0 | return true; |
2322 | 0 | } |
2323 | 0 | break; |
2324 | 0 | case T_ArrayExpr: |
2325 | 0 | return WALK(((ArrayExpr *) node)->elements); |
2326 | 0 | case T_RowExpr: |
2327 | | /* Assume colnames isn't interesting */ |
2328 | 0 | return WALK(((RowExpr *) node)->args); |
2329 | 0 | case T_RowCompareExpr: |
2330 | 0 | { |
2331 | 0 | RowCompareExpr *rcexpr = (RowCompareExpr *) node; |
2332 | |
|
2333 | 0 | if (WALK(rcexpr->largs)) |
2334 | 0 | return true; |
2335 | 0 | if (WALK(rcexpr->rargs)) |
2336 | 0 | return true; |
2337 | 0 | } |
2338 | 0 | break; |
2339 | 0 | case T_CoalesceExpr: |
2340 | 0 | return WALK(((CoalesceExpr *) node)->args); |
2341 | 0 | case T_MinMaxExpr: |
2342 | 0 | return WALK(((MinMaxExpr *) node)->args); |
2343 | 0 | case T_XmlExpr: |
2344 | 0 | { |
2345 | 0 | XmlExpr *xexpr = (XmlExpr *) node; |
2346 | |
|
2347 | 0 | if (WALK(xexpr->named_args)) |
2348 | 0 | return true; |
2349 | | /* we assume walker doesn't care about arg_names */ |
2350 | 0 | if (WALK(xexpr->args)) |
2351 | 0 | return true; |
2352 | 0 | } |
2353 | 0 | break; |
2354 | 0 | case T_JsonValueExpr: |
2355 | 0 | { |
2356 | 0 | JsonValueExpr *jve = (JsonValueExpr *) node; |
2357 | |
|
2358 | 0 | if (WALK(jve->raw_expr)) |
2359 | 0 | return true; |
2360 | 0 | if (WALK(jve->formatted_expr)) |
2361 | 0 | return true; |
2362 | 0 | } |
2363 | 0 | break; |
2364 | 0 | case T_JsonConstructorExpr: |
2365 | 0 | { |
2366 | 0 | JsonConstructorExpr *ctor = (JsonConstructorExpr *) node; |
2367 | |
|
2368 | 0 | if (WALK(ctor->args)) |
2369 | 0 | return true; |
2370 | 0 | if (WALK(ctor->func)) |
2371 | 0 | return true; |
2372 | 0 | if (WALK(ctor->coercion)) |
2373 | 0 | return true; |
2374 | 0 | } |
2375 | 0 | break; |
2376 | 0 | case T_JsonIsPredicate: |
2377 | 0 | return WALK(((JsonIsPredicate *) node)->expr); |
2378 | 0 | case T_JsonExpr: |
2379 | 0 | { |
2380 | 0 | JsonExpr *jexpr = (JsonExpr *) node; |
2381 | |
|
2382 | 0 | if (WALK(jexpr->formatted_expr)) |
2383 | 0 | return true; |
2384 | 0 | if (WALK(jexpr->path_spec)) |
2385 | 0 | return true; |
2386 | 0 | if (WALK(jexpr->passing_values)) |
2387 | 0 | return true; |
2388 | | /* we assume walker doesn't care about passing_names */ |
2389 | 0 | if (WALK(jexpr->on_empty)) |
2390 | 0 | return true; |
2391 | 0 | if (WALK(jexpr->on_error)) |
2392 | 0 | return true; |
2393 | 0 | } |
2394 | 0 | break; |
2395 | 0 | case T_JsonBehavior: |
2396 | 0 | { |
2397 | 0 | JsonBehavior *behavior = (JsonBehavior *) node; |
2398 | |
|
2399 | 0 | if (WALK(behavior->expr)) |
2400 | 0 | return true; |
2401 | 0 | } |
2402 | 0 | break; |
2403 | 0 | case T_NullTest: |
2404 | 0 | return WALK(((NullTest *) node)->arg); |
2405 | 0 | case T_BooleanTest: |
2406 | 0 | return WALK(((BooleanTest *) node)->arg); |
2407 | 0 | case T_CoerceToDomain: |
2408 | 0 | return WALK(((CoerceToDomain *) node)->arg); |
2409 | 0 | case T_TargetEntry: |
2410 | 0 | return WALK(((TargetEntry *) node)->expr); |
2411 | 0 | case T_Query: |
2412 | | /* Do nothing with a sub-Query, per discussion above */ |
2413 | 0 | break; |
2414 | 0 | case T_WindowClause: |
2415 | 0 | { |
2416 | 0 | WindowClause *wc = (WindowClause *) node; |
2417 | |
|
2418 | 0 | if (WALK(wc->partitionClause)) |
2419 | 0 | return true; |
2420 | 0 | if (WALK(wc->orderClause)) |
2421 | 0 | return true; |
2422 | 0 | if (WALK(wc->startOffset)) |
2423 | 0 | return true; |
2424 | 0 | if (WALK(wc->endOffset)) |
2425 | 0 | return true; |
2426 | 0 | } |
2427 | 0 | break; |
2428 | 0 | case T_CTECycleClause: |
2429 | 0 | { |
2430 | 0 | CTECycleClause *cc = (CTECycleClause *) node; |
2431 | |
|
2432 | 0 | if (WALK(cc->cycle_mark_value)) |
2433 | 0 | return true; |
2434 | 0 | if (WALK(cc->cycle_mark_default)) |
2435 | 0 | return true; |
2436 | 0 | } |
2437 | 0 | break; |
2438 | 0 | case T_CommonTableExpr: |
2439 | 0 | { |
2440 | 0 | CommonTableExpr *cte = (CommonTableExpr *) node; |
2441 | | |
2442 | | /* |
2443 | | * Invoke the walker on the CTE's Query node, so it can |
2444 | | * recurse into the sub-query if it wants to. |
2445 | | */ |
2446 | 0 | if (WALK(cte->ctequery)) |
2447 | 0 | return true; |
2448 | | |
2449 | 0 | if (WALK(cte->search_clause)) |
2450 | 0 | return true; |
2451 | 0 | if (WALK(cte->cycle_clause)) |
2452 | 0 | return true; |
2453 | 0 | } |
2454 | 0 | break; |
2455 | 0 | case T_JsonKeyValue: |
2456 | 0 | { |
2457 | 0 | JsonKeyValue *kv = (JsonKeyValue *) node; |
2458 | |
|
2459 | 0 | if (WALK(kv->key)) |
2460 | 0 | return true; |
2461 | 0 | if (WALK(kv->value)) |
2462 | 0 | return true; |
2463 | 0 | } |
2464 | 0 | break; |
2465 | 0 | case T_JsonObjectConstructor: |
2466 | 0 | { |
2467 | 0 | JsonObjectConstructor *ctor = (JsonObjectConstructor *) node; |
2468 | |
|
2469 | 0 | if (LIST_WALK(ctor->exprs)) |
2470 | 0 | return true; |
2471 | 0 | } |
2472 | 0 | break; |
2473 | 0 | case T_JsonArrayConstructor: |
2474 | 0 | { |
2475 | 0 | JsonArrayConstructor *ctor = (JsonArrayConstructor *) node; |
2476 | |
|
2477 | 0 | if (LIST_WALK(ctor->exprs)) |
2478 | 0 | return true; |
2479 | 0 | } |
2480 | 0 | break; |
2481 | 0 | case T_JsonArrayQueryConstructor: |
2482 | 0 | { |
2483 | 0 | JsonArrayQueryConstructor *ctor = (JsonArrayQueryConstructor *) node; |
2484 | |
|
2485 | 0 | if (WALK(ctor->query)) |
2486 | 0 | return true; |
2487 | 0 | } |
2488 | 0 | break; |
2489 | 0 | case T_JsonAggConstructor: |
2490 | 0 | { |
2491 | 0 | JsonAggConstructor *ctor = (JsonAggConstructor *) node; |
2492 | |
|
2493 | 0 | if (WALK(ctor->agg_filter)) |
2494 | 0 | return true; |
2495 | 0 | if (WALK(ctor->agg_order)) |
2496 | 0 | return true; |
2497 | 0 | if (WALK(ctor->over)) |
2498 | 0 | return true; |
2499 | 0 | } |
2500 | 0 | break; |
2501 | 0 | case T_JsonObjectAgg: |
2502 | 0 | { |
2503 | 0 | JsonObjectAgg *ctor = (JsonObjectAgg *) node; |
2504 | |
|
2505 | 0 | if (WALK(ctor->constructor)) |
2506 | 0 | return true; |
2507 | 0 | if (WALK(ctor->arg)) |
2508 | 0 | return true; |
2509 | 0 | } |
2510 | 0 | break; |
2511 | 0 | case T_JsonArrayAgg: |
2512 | 0 | { |
2513 | 0 | JsonArrayAgg *ctor = (JsonArrayAgg *) node; |
2514 | |
|
2515 | 0 | if (WALK(ctor->constructor)) |
2516 | 0 | return true; |
2517 | 0 | if (WALK(ctor->arg)) |
2518 | 0 | return true; |
2519 | 0 | } |
2520 | 0 | break; |
2521 | | |
2522 | 0 | case T_PartitionBoundSpec: |
2523 | 0 | { |
2524 | 0 | PartitionBoundSpec *pbs = (PartitionBoundSpec *) node; |
2525 | |
|
2526 | 0 | if (WALK(pbs->listdatums)) |
2527 | 0 | return true; |
2528 | 0 | if (WALK(pbs->lowerdatums)) |
2529 | 0 | return true; |
2530 | 0 | if (WALK(pbs->upperdatums)) |
2531 | 0 | return true; |
2532 | 0 | } |
2533 | 0 | break; |
2534 | 0 | case T_PartitionRangeDatum: |
2535 | 0 | { |
2536 | 0 | PartitionRangeDatum *prd = (PartitionRangeDatum *) node; |
2537 | |
|
2538 | 0 | if (WALK(prd->value)) |
2539 | 0 | return true; |
2540 | 0 | } |
2541 | 0 | break; |
2542 | 0 | case T_List: |
2543 | 0 | foreach(temp, (List *) node) |
2544 | 0 | { |
2545 | 0 | if (WALK(lfirst(temp))) |
2546 | 0 | return true; |
2547 | 0 | } |
2548 | 0 | break; |
2549 | 0 | case T_FromExpr: |
2550 | 0 | { |
2551 | 0 | FromExpr *from = (FromExpr *) node; |
2552 | |
|
2553 | 0 | if (LIST_WALK(from->fromlist)) |
2554 | 0 | return true; |
2555 | 0 | if (WALK(from->quals)) |
2556 | 0 | return true; |
2557 | 0 | } |
2558 | 0 | break; |
2559 | 0 | case T_OnConflictExpr: |
2560 | 0 | { |
2561 | 0 | OnConflictExpr *onconflict = (OnConflictExpr *) node; |
2562 | |
|
2563 | 0 | if (WALK(onconflict->arbiterElems)) |
2564 | 0 | return true; |
2565 | 0 | if (WALK(onconflict->arbiterWhere)) |
2566 | 0 | return true; |
2567 | 0 | if (WALK(onconflict->onConflictSet)) |
2568 | 0 | return true; |
2569 | 0 | if (WALK(onconflict->onConflictWhere)) |
2570 | 0 | return true; |
2571 | 0 | if (WALK(onconflict->exclRelTlist)) |
2572 | 0 | return true; |
2573 | 0 | } |
2574 | 0 | break; |
2575 | 0 | case T_MergeAction: |
2576 | 0 | { |
2577 | 0 | MergeAction *action = (MergeAction *) node; |
2578 | |
|
2579 | 0 | if (WALK(action->qual)) |
2580 | 0 | return true; |
2581 | 0 | if (WALK(action->targetList)) |
2582 | 0 | return true; |
2583 | 0 | } |
2584 | 0 | break; |
2585 | 0 | case T_PartitionPruneStepOp: |
2586 | 0 | { |
2587 | 0 | PartitionPruneStepOp *opstep = (PartitionPruneStepOp *) node; |
2588 | |
|
2589 | 0 | if (WALK(opstep->exprs)) |
2590 | 0 | return true; |
2591 | 0 | } |
2592 | 0 | break; |
2593 | 0 | case T_PartitionPruneStepCombine: |
2594 | | /* no expression subnodes */ |
2595 | 0 | break; |
2596 | 0 | case T_JoinExpr: |
2597 | 0 | { |
2598 | 0 | JoinExpr *join = (JoinExpr *) node; |
2599 | |
|
2600 | 0 | if (WALK(join->larg)) |
2601 | 0 | return true; |
2602 | 0 | if (WALK(join->rarg)) |
2603 | 0 | return true; |
2604 | 0 | if (WALK(join->quals)) |
2605 | 0 | return true; |
2606 | | |
2607 | | /* |
2608 | | * alias clause, using list are deemed uninteresting. |
2609 | | */ |
2610 | 0 | } |
2611 | 0 | break; |
2612 | 0 | case T_SetOperationStmt: |
2613 | 0 | { |
2614 | 0 | SetOperationStmt *setop = (SetOperationStmt *) node; |
2615 | |
|
2616 | 0 | if (WALK(setop->larg)) |
2617 | 0 | return true; |
2618 | 0 | if (WALK(setop->rarg)) |
2619 | 0 | return true; |
2620 | | |
2621 | | /* groupClauses are deemed uninteresting */ |
2622 | 0 | } |
2623 | 0 | break; |
2624 | 0 | case T_IndexClause: |
2625 | 0 | { |
2626 | 0 | IndexClause *iclause = (IndexClause *) node; |
2627 | |
|
2628 | 0 | if (WALK(iclause->rinfo)) |
2629 | 0 | return true; |
2630 | 0 | if (LIST_WALK(iclause->indexquals)) |
2631 | 0 | return true; |
2632 | 0 | } |
2633 | 0 | break; |
2634 | 0 | case T_PlaceHolderVar: |
2635 | 0 | return WALK(((PlaceHolderVar *) node)->phexpr); |
2636 | 0 | case T_InferenceElem: |
2637 | 0 | return WALK(((InferenceElem *) node)->expr); |
2638 | 0 | case T_ReturningExpr: |
2639 | 0 | return WALK(((ReturningExpr *) node)->retexpr); |
2640 | 0 | case T_AppendRelInfo: |
2641 | 0 | { |
2642 | 0 | AppendRelInfo *appinfo = (AppendRelInfo *) node; |
2643 | |
|
2644 | 0 | if (LIST_WALK(appinfo->translated_vars)) |
2645 | 0 | return true; |
2646 | 0 | } |
2647 | 0 | break; |
2648 | 0 | case T_PlaceHolderInfo: |
2649 | 0 | return WALK(((PlaceHolderInfo *) node)->ph_var); |
2650 | 0 | case T_RangeTblFunction: |
2651 | 0 | return WALK(((RangeTblFunction *) node)->funcexpr); |
2652 | 0 | case T_TableSampleClause: |
2653 | 0 | { |
2654 | 0 | TableSampleClause *tsc = (TableSampleClause *) node; |
2655 | |
|
2656 | 0 | if (LIST_WALK(tsc->args)) |
2657 | 0 | return true; |
2658 | 0 | if (WALK(tsc->repeatable)) |
2659 | 0 | return true; |
2660 | 0 | } |
2661 | 0 | break; |
2662 | 0 | case T_TableFunc: |
2663 | 0 | { |
2664 | 0 | TableFunc *tf = (TableFunc *) node; |
2665 | |
|
2666 | 0 | if (WALK(tf->ns_uris)) |
2667 | 0 | return true; |
2668 | 0 | if (WALK(tf->docexpr)) |
2669 | 0 | return true; |
2670 | 0 | if (WALK(tf->rowexpr)) |
2671 | 0 | return true; |
2672 | 0 | if (WALK(tf->colexprs)) |
2673 | 0 | return true; |
2674 | 0 | if (WALK(tf->coldefexprs)) |
2675 | 0 | return true; |
2676 | 0 | if (WALK(tf->colvalexprs)) |
2677 | 0 | return true; |
2678 | 0 | if (WALK(tf->passingvalexprs)) |
2679 | 0 | return true; |
2680 | 0 | } |
2681 | 0 | break; |
2682 | 0 | default: |
2683 | 0 | elog(ERROR, "unrecognized node type: %d", |
2684 | 0 | (int) nodeTag(node)); |
2685 | 0 | break; |
2686 | 0 | } |
2687 | 0 | return false; |
2688 | | |
2689 | | /* The WALK() macro can be re-used below, but LIST_WALK() not so much */ |
2690 | 0 | #undef LIST_WALK |
2691 | 0 | } |
2692 | | |
2693 | | /* |
2694 | | * query_tree_walker --- initiate a walk of a Query's expressions |
2695 | | * |
2696 | | * This routine exists just to reduce the number of places that need to know |
2697 | | * where all the expression subtrees of a Query are. Note it can be used |
2698 | | * for starting a walk at top level of a Query regardless of whether the |
2699 | | * walker intends to descend into subqueries. It is also useful for |
2700 | | * descending into subqueries within a walker. |
2701 | | * |
2702 | | * Some callers want to suppress visitation of certain items in the sub-Query, |
2703 | | * typically because they need to process them specially, or don't actually |
2704 | | * want to recurse into subqueries. This is supported by the flags argument, |
2705 | | * which is the bitwise OR of flag values to add or suppress visitation of |
2706 | | * indicated items. (More flag bits may be added as needed.) |
2707 | | */ |
2708 | | pg_attribute_no_sanitize_function() |
2709 | | bool |
2710 | | query_tree_walker_impl(Query *query, |
2711 | | tree_walker_callback walker, |
2712 | | void *context, |
2713 | | int flags) |
2714 | 0 | { |
2715 | 0 | Assert(query != NULL && IsA(query, Query)); |
2716 | | |
2717 | | /* |
2718 | | * We don't walk any utilityStmt here. However, we can't easily assert |
2719 | | * that it is absent, since there are at least two code paths by which |
2720 | | * action statements from CREATE RULE end up here, and NOTIFY is allowed |
2721 | | * in a rule action. |
2722 | | */ |
2723 | |
|
2724 | 0 | if (WALK(query->targetList)) |
2725 | 0 | return true; |
2726 | 0 | if (WALK(query->withCheckOptions)) |
2727 | 0 | return true; |
2728 | 0 | if (WALK(query->onConflict)) |
2729 | 0 | return true; |
2730 | 0 | if (WALK(query->mergeActionList)) |
2731 | 0 | return true; |
2732 | 0 | if (WALK(query->mergeJoinCondition)) |
2733 | 0 | return true; |
2734 | 0 | if (WALK(query->returningList)) |
2735 | 0 | return true; |
2736 | 0 | if (WALK(query->jointree)) |
2737 | 0 | return true; |
2738 | 0 | if (WALK(query->setOperations)) |
2739 | 0 | return true; |
2740 | 0 | if (WALK(query->havingQual)) |
2741 | 0 | return true; |
2742 | 0 | if (WALK(query->limitOffset)) |
2743 | 0 | return true; |
2744 | 0 | if (WALK(query->limitCount)) |
2745 | 0 | return true; |
2746 | | |
2747 | | /* |
2748 | | * Most callers aren't interested in SortGroupClause nodes since those |
2749 | | * don't contain actual expressions. However they do contain OIDs which |
2750 | | * may be needed by dependency walkers etc. |
2751 | | */ |
2752 | 0 | if ((flags & QTW_EXAMINE_SORTGROUP)) |
2753 | 0 | { |
2754 | 0 | if (WALK(query->groupClause)) |
2755 | 0 | return true; |
2756 | 0 | if (WALK(query->windowClause)) |
2757 | 0 | return true; |
2758 | 0 | if (WALK(query->sortClause)) |
2759 | 0 | return true; |
2760 | 0 | if (WALK(query->distinctClause)) |
2761 | 0 | return true; |
2762 | 0 | } |
2763 | 0 | else |
2764 | 0 | { |
2765 | | /* |
2766 | | * But we need to walk the expressions under WindowClause nodes even |
2767 | | * if we're not interested in SortGroupClause nodes. |
2768 | | */ |
2769 | 0 | ListCell *lc; |
2770 | |
|
2771 | 0 | foreach(lc, query->windowClause) |
2772 | 0 | { |
2773 | 0 | WindowClause *wc = lfirst_node(WindowClause, lc); |
2774 | |
|
2775 | 0 | if (WALK(wc->startOffset)) |
2776 | 0 | return true; |
2777 | 0 | if (WALK(wc->endOffset)) |
2778 | 0 | return true; |
2779 | 0 | } |
2780 | 0 | } |
2781 | | |
2782 | | /* |
2783 | | * groupingSets and rowMarks are not walked: |
2784 | | * |
2785 | | * groupingSets contain only ressortgrouprefs (integers) which are |
2786 | | * meaningless without the corresponding groupClause or tlist. |
2787 | | * Accordingly, any walker that needs to care about them needs to handle |
2788 | | * them itself in its Query processing. |
2789 | | * |
2790 | | * rowMarks is not walked because it contains only rangetable indexes (and |
2791 | | * flags etc.) and therefore should be handled at Query level similarly. |
2792 | | */ |
2793 | | |
2794 | 0 | if (!(flags & QTW_IGNORE_CTE_SUBQUERIES)) |
2795 | 0 | { |
2796 | 0 | if (WALK(query->cteList)) |
2797 | 0 | return true; |
2798 | 0 | } |
2799 | 0 | if (!(flags & QTW_IGNORE_RANGE_TABLE)) |
2800 | 0 | { |
2801 | 0 | if (range_table_walker(query->rtable, walker, context, flags)) |
2802 | 0 | return true; |
2803 | 0 | } |
2804 | 0 | return false; |
2805 | 0 | } |
2806 | | |
2807 | | /* |
2808 | | * range_table_walker is just the part of query_tree_walker that scans |
2809 | | * a query's rangetable. This is split out since it can be useful on |
2810 | | * its own. |
2811 | | */ |
2812 | | bool |
2813 | | range_table_walker_impl(List *rtable, |
2814 | | tree_walker_callback walker, |
2815 | | void *context, |
2816 | | int flags) |
2817 | 0 | { |
2818 | 0 | ListCell *rt; |
2819 | |
|
2820 | 0 | foreach(rt, rtable) |
2821 | 0 | { |
2822 | 0 | RangeTblEntry *rte = lfirst_node(RangeTblEntry, rt); |
2823 | |
|
2824 | 0 | if (range_table_entry_walker(rte, walker, context, flags)) |
2825 | 0 | return true; |
2826 | 0 | } |
2827 | 0 | return false; |
2828 | 0 | } |
2829 | | |
2830 | | /* |
2831 | | * Some callers even want to scan the expressions in individual RTEs. |
2832 | | */ |
2833 | | pg_attribute_no_sanitize_function() |
2834 | | bool |
2835 | | range_table_entry_walker_impl(RangeTblEntry *rte, |
2836 | | tree_walker_callback walker, |
2837 | | void *context, |
2838 | | int flags) |
2839 | 0 | { |
2840 | | /* |
2841 | | * Walkers might need to examine the RTE node itself either before or |
2842 | | * after visiting its contents (or, conceivably, both). Note that if you |
2843 | | * specify neither flag, the walker won't be called on the RTE at all. |
2844 | | */ |
2845 | 0 | if (flags & QTW_EXAMINE_RTES_BEFORE) |
2846 | 0 | if (WALK(rte)) |
2847 | 0 | return true; |
2848 | | |
2849 | 0 | switch (rte->rtekind) |
2850 | 0 | { |
2851 | 0 | case RTE_RELATION: |
2852 | 0 | if (WALK(rte->tablesample)) |
2853 | 0 | return true; |
2854 | 0 | break; |
2855 | 0 | case RTE_SUBQUERY: |
2856 | 0 | if (!(flags & QTW_IGNORE_RT_SUBQUERIES)) |
2857 | 0 | if (WALK(rte->subquery)) |
2858 | 0 | return true; |
2859 | 0 | break; |
2860 | 0 | case RTE_JOIN: |
2861 | 0 | if (!(flags & QTW_IGNORE_JOINALIASES)) |
2862 | 0 | if (WALK(rte->joinaliasvars)) |
2863 | 0 | return true; |
2864 | 0 | break; |
2865 | 0 | case RTE_FUNCTION: |
2866 | 0 | if (WALK(rte->functions)) |
2867 | 0 | return true; |
2868 | 0 | break; |
2869 | 0 | case RTE_TABLEFUNC: |
2870 | 0 | if (WALK(rte->tablefunc)) |
2871 | 0 | return true; |
2872 | 0 | break; |
2873 | 0 | case RTE_VALUES: |
2874 | 0 | if (WALK(rte->values_lists)) |
2875 | 0 | return true; |
2876 | 0 | break; |
2877 | 0 | case RTE_CTE: |
2878 | 0 | case RTE_NAMEDTUPLESTORE: |
2879 | 0 | case RTE_RESULT: |
2880 | | /* nothing to do */ |
2881 | 0 | break; |
2882 | 0 | case RTE_GROUP: |
2883 | 0 | if (!(flags & QTW_IGNORE_GROUPEXPRS)) |
2884 | 0 | if (WALK(rte->groupexprs)) |
2885 | 0 | return true; |
2886 | 0 | break; |
2887 | 0 | } |
2888 | | |
2889 | 0 | if (WALK(rte->securityQuals)) |
2890 | 0 | return true; |
2891 | | |
2892 | 0 | if (flags & QTW_EXAMINE_RTES_AFTER) |
2893 | 0 | if (WALK(rte)) |
2894 | 0 | return true; |
2895 | | |
2896 | 0 | return false; |
2897 | 0 | } |
2898 | | |
2899 | | |
2900 | | /* |
2901 | | * expression_tree_mutator() is designed to support routines that make a |
2902 | | * modified copy of an expression tree, with some nodes being added, |
2903 | | * removed, or replaced by new subtrees. The original tree is (normally) |
2904 | | * not changed. Each recursion level is responsible for returning a copy of |
2905 | | * (or appropriately modified substitute for) the subtree it is handed. |
2906 | | * A mutator routine should look like this: |
2907 | | * |
2908 | | * Node * my_mutator (Node *node, my_struct *context) |
2909 | | * { |
2910 | | * if (node == NULL) |
2911 | | * return NULL; |
2912 | | * // check for nodes that special work is required for, eg: |
2913 | | * if (IsA(node, Var)) |
2914 | | * { |
2915 | | * ... create and return modified copy of Var node |
2916 | | * } |
2917 | | * else if (IsA(node, ...)) |
2918 | | * { |
2919 | | * ... do special transformations of other node types |
2920 | | * } |
2921 | | * // for any node type not specially processed, do: |
2922 | | * return expression_tree_mutator(node, my_mutator, context); |
2923 | | * } |
2924 | | * |
2925 | | * The "context" argument points to a struct that holds whatever context |
2926 | | * information the mutator routine needs --- it can be used to return extra |
2927 | | * data gathered by the mutator, too. This argument is not touched by |
2928 | | * expression_tree_mutator, but it is passed down to recursive sub-invocations |
2929 | | * of my_mutator. The tree walk is started from a setup routine that |
2930 | | * fills in the appropriate context struct, calls my_mutator with the |
2931 | | * top-level node of the tree, and does any required post-processing. |
2932 | | * |
2933 | | * Each level of recursion must return an appropriately modified Node. |
2934 | | * If expression_tree_mutator() is called, it will make an exact copy |
2935 | | * of the given Node, but invoke my_mutator() to copy the sub-node(s) |
2936 | | * of that Node. In this way, my_mutator() has full control over the |
2937 | | * copying process but need not directly deal with expression trees |
2938 | | * that it has no interest in. |
2939 | | * |
2940 | | * Just as for expression_tree_walker, the node types handled by |
2941 | | * expression_tree_mutator include all those normally found in target lists |
2942 | | * and qualifier clauses during the planning stage. |
2943 | | * |
2944 | | * expression_tree_mutator will handle SubLink nodes by recursing normally |
2945 | | * into the "testexpr" subtree (which is an expression belonging to the outer |
2946 | | * plan). It will also call the mutator on the sub-Query node; however, when |
2947 | | * expression_tree_mutator itself is called on a Query node, it does nothing |
2948 | | * and returns the unmodified Query node. The net effect is that unless the |
2949 | | * mutator does something special at a Query node, sub-selects will not be |
2950 | | * visited or modified; the original sub-select will be linked to by the new |
2951 | | * SubLink node. Mutators that want to descend into sub-selects will usually |
2952 | | * do so by recognizing Query nodes and calling query_tree_mutator (below). |
2953 | | * |
2954 | | * expression_tree_mutator will handle a SubPlan node by recursing into the |
2955 | | * "testexpr" and the "args" list (which belong to the outer plan), but it |
2956 | | * will simply copy the link to the inner plan, since that's typically what |
2957 | | * expression tree mutators want. A mutator that wants to modify the subplan |
2958 | | * can force appropriate behavior by recognizing SubPlan expression nodes |
2959 | | * and doing the right thing. |
2960 | | */ |
2961 | | |
2962 | | pg_attribute_no_sanitize_function() |
2963 | | Node * |
2964 | | expression_tree_mutator_impl(Node *node, |
2965 | | tree_mutator_callback mutator, |
2966 | | void *context) |
2967 | 0 | { |
2968 | | /* |
2969 | | * The mutator has already decided not to modify the current node, but we |
2970 | | * must call the mutator for any sub-nodes. |
2971 | | */ |
2972 | |
|
2973 | 0 | #define FLATCOPY(newnode, node, nodetype) \ |
2974 | 0 | ( (newnode) = palloc_object(nodetype), \ |
2975 | 0 | memcpy((newnode), (node), sizeof(nodetype)) ) |
2976 | |
|
2977 | 0 | #define MUTATE(newfield, oldfield, fieldtype) \ |
2978 | 0 | ( (newfield) = (fieldtype) mutator((Node *) (oldfield), context) ) |
2979 | |
|
2980 | 0 | if (node == NULL) |
2981 | 0 | return NULL; |
2982 | | |
2983 | | /* Guard against stack overflow due to overly complex expressions */ |
2984 | 0 | check_stack_depth(); |
2985 | |
|
2986 | 0 | switch (nodeTag(node)) |
2987 | 0 | { |
2988 | | /* |
2989 | | * Primitive node types with no expression subnodes. Var and |
2990 | | * Const are frequent enough to deserve special cases, the others |
2991 | | * we just use copyObject for. |
2992 | | */ |
2993 | 0 | case T_Var: |
2994 | 0 | { |
2995 | 0 | Var *var = (Var *) node; |
2996 | 0 | Var *newnode; |
2997 | |
|
2998 | 0 | FLATCOPY(newnode, var, Var); |
2999 | | /* Assume we need not copy the varnullingrels bitmapset */ |
3000 | 0 | return (Node *) newnode; |
3001 | 0 | } |
3002 | 0 | break; |
3003 | 0 | case T_Const: |
3004 | 0 | { |
3005 | 0 | Const *oldnode = (Const *) node; |
3006 | 0 | Const *newnode; |
3007 | |
|
3008 | 0 | FLATCOPY(newnode, oldnode, Const); |
3009 | | /* XXX we don't bother with datumCopy; should we? */ |
3010 | 0 | return (Node *) newnode; |
3011 | 0 | } |
3012 | 0 | break; |
3013 | 0 | case T_Param: |
3014 | 0 | case T_CaseTestExpr: |
3015 | 0 | case T_SQLValueFunction: |
3016 | 0 | case T_JsonFormat: |
3017 | 0 | case T_CoerceToDomainValue: |
3018 | 0 | case T_SetToDefault: |
3019 | 0 | case T_CurrentOfExpr: |
3020 | 0 | case T_NextValueExpr: |
3021 | 0 | case T_RangeTblRef: |
3022 | 0 | case T_SortGroupClause: |
3023 | 0 | case T_CTESearchClause: |
3024 | 0 | case T_MergeSupportFunc: |
3025 | 0 | return copyObject(node); |
3026 | 0 | case T_WithCheckOption: |
3027 | 0 | { |
3028 | 0 | WithCheckOption *wco = (WithCheckOption *) node; |
3029 | 0 | WithCheckOption *newnode; |
3030 | |
|
3031 | 0 | FLATCOPY(newnode, wco, WithCheckOption); |
3032 | 0 | MUTATE(newnode->qual, wco->qual, Node *); |
3033 | 0 | return (Node *) newnode; |
3034 | 0 | } |
3035 | 0 | case T_Aggref: |
3036 | 0 | { |
3037 | 0 | Aggref *aggref = (Aggref *) node; |
3038 | 0 | Aggref *newnode; |
3039 | |
|
3040 | 0 | FLATCOPY(newnode, aggref, Aggref); |
3041 | | /* assume mutation doesn't change types of arguments */ |
3042 | 0 | newnode->aggargtypes = list_copy(aggref->aggargtypes); |
3043 | 0 | MUTATE(newnode->aggdirectargs, aggref->aggdirectargs, List *); |
3044 | 0 | MUTATE(newnode->args, aggref->args, List *); |
3045 | 0 | MUTATE(newnode->aggorder, aggref->aggorder, List *); |
3046 | 0 | MUTATE(newnode->aggdistinct, aggref->aggdistinct, List *); |
3047 | 0 | MUTATE(newnode->aggfilter, aggref->aggfilter, Expr *); |
3048 | 0 | return (Node *) newnode; |
3049 | 0 | } |
3050 | 0 | break; |
3051 | 0 | case T_GroupingFunc: |
3052 | 0 | { |
3053 | 0 | GroupingFunc *grouping = (GroupingFunc *) node; |
3054 | 0 | GroupingFunc *newnode; |
3055 | |
|
3056 | 0 | FLATCOPY(newnode, grouping, GroupingFunc); |
3057 | 0 | MUTATE(newnode->args, grouping->args, List *); |
3058 | | |
3059 | | /* |
3060 | | * We assume here that mutating the arguments does not change |
3061 | | * the semantics, i.e. that the arguments are not mutated in a |
3062 | | * way that makes them semantically different from their |
3063 | | * previously matching expressions in the GROUP BY clause. |
3064 | | * |
3065 | | * If a mutator somehow wanted to do this, it would have to |
3066 | | * handle the refs and cols lists itself as appropriate. |
3067 | | */ |
3068 | 0 | newnode->refs = list_copy(grouping->refs); |
3069 | 0 | newnode->cols = list_copy(grouping->cols); |
3070 | |
|
3071 | 0 | return (Node *) newnode; |
3072 | 0 | } |
3073 | 0 | break; |
3074 | 0 | case T_WindowFunc: |
3075 | 0 | { |
3076 | 0 | WindowFunc *wfunc = (WindowFunc *) node; |
3077 | 0 | WindowFunc *newnode; |
3078 | |
|
3079 | 0 | FLATCOPY(newnode, wfunc, WindowFunc); |
3080 | 0 | MUTATE(newnode->args, wfunc->args, List *); |
3081 | 0 | MUTATE(newnode->aggfilter, wfunc->aggfilter, Expr *); |
3082 | 0 | return (Node *) newnode; |
3083 | 0 | } |
3084 | 0 | break; |
3085 | 0 | case T_WindowFuncRunCondition: |
3086 | 0 | { |
3087 | 0 | WindowFuncRunCondition *wfuncrc = (WindowFuncRunCondition *) node; |
3088 | 0 | WindowFuncRunCondition *newnode; |
3089 | |
|
3090 | 0 | FLATCOPY(newnode, wfuncrc, WindowFuncRunCondition); |
3091 | 0 | MUTATE(newnode->arg, wfuncrc->arg, Expr *); |
3092 | 0 | return (Node *) newnode; |
3093 | 0 | } |
3094 | 0 | break; |
3095 | 0 | case T_SubscriptingRef: |
3096 | 0 | { |
3097 | 0 | SubscriptingRef *sbsref = (SubscriptingRef *) node; |
3098 | 0 | SubscriptingRef *newnode; |
3099 | |
|
3100 | 0 | FLATCOPY(newnode, sbsref, SubscriptingRef); |
3101 | 0 | MUTATE(newnode->refupperindexpr, sbsref->refupperindexpr, |
3102 | 0 | List *); |
3103 | 0 | MUTATE(newnode->reflowerindexpr, sbsref->reflowerindexpr, |
3104 | 0 | List *); |
3105 | 0 | MUTATE(newnode->refexpr, sbsref->refexpr, |
3106 | 0 | Expr *); |
3107 | 0 | MUTATE(newnode->refassgnexpr, sbsref->refassgnexpr, |
3108 | 0 | Expr *); |
3109 | |
|
3110 | 0 | return (Node *) newnode; |
3111 | 0 | } |
3112 | 0 | break; |
3113 | 0 | case T_FuncExpr: |
3114 | 0 | { |
3115 | 0 | FuncExpr *expr = (FuncExpr *) node; |
3116 | 0 | FuncExpr *newnode; |
3117 | |
|
3118 | 0 | FLATCOPY(newnode, expr, FuncExpr); |
3119 | 0 | MUTATE(newnode->args, expr->args, List *); |
3120 | 0 | return (Node *) newnode; |
3121 | 0 | } |
3122 | 0 | break; |
3123 | 0 | case T_NamedArgExpr: |
3124 | 0 | { |
3125 | 0 | NamedArgExpr *nexpr = (NamedArgExpr *) node; |
3126 | 0 | NamedArgExpr *newnode; |
3127 | |
|
3128 | 0 | FLATCOPY(newnode, nexpr, NamedArgExpr); |
3129 | 0 | MUTATE(newnode->arg, nexpr->arg, Expr *); |
3130 | 0 | return (Node *) newnode; |
3131 | 0 | } |
3132 | 0 | break; |
3133 | 0 | case T_OpExpr: |
3134 | 0 | { |
3135 | 0 | OpExpr *expr = (OpExpr *) node; |
3136 | 0 | OpExpr *newnode; |
3137 | |
|
3138 | 0 | FLATCOPY(newnode, expr, OpExpr); |
3139 | 0 | MUTATE(newnode->args, expr->args, List *); |
3140 | 0 | return (Node *) newnode; |
3141 | 0 | } |
3142 | 0 | break; |
3143 | 0 | case T_DistinctExpr: |
3144 | 0 | { |
3145 | 0 | DistinctExpr *expr = (DistinctExpr *) node; |
3146 | 0 | DistinctExpr *newnode; |
3147 | |
|
3148 | 0 | FLATCOPY(newnode, expr, DistinctExpr); |
3149 | 0 | MUTATE(newnode->args, expr->args, List *); |
3150 | 0 | return (Node *) newnode; |
3151 | 0 | } |
3152 | 0 | break; |
3153 | 0 | case T_NullIfExpr: |
3154 | 0 | { |
3155 | 0 | NullIfExpr *expr = (NullIfExpr *) node; |
3156 | 0 | NullIfExpr *newnode; |
3157 | |
|
3158 | 0 | FLATCOPY(newnode, expr, NullIfExpr); |
3159 | 0 | MUTATE(newnode->args, expr->args, List *); |
3160 | 0 | return (Node *) newnode; |
3161 | 0 | } |
3162 | 0 | break; |
3163 | 0 | case T_ScalarArrayOpExpr: |
3164 | 0 | { |
3165 | 0 | ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; |
3166 | 0 | ScalarArrayOpExpr *newnode; |
3167 | |
|
3168 | 0 | FLATCOPY(newnode, expr, ScalarArrayOpExpr); |
3169 | 0 | MUTATE(newnode->args, expr->args, List *); |
3170 | 0 | return (Node *) newnode; |
3171 | 0 | } |
3172 | 0 | break; |
3173 | 0 | case T_BoolExpr: |
3174 | 0 | { |
3175 | 0 | BoolExpr *expr = (BoolExpr *) node; |
3176 | 0 | BoolExpr *newnode; |
3177 | |
|
3178 | 0 | FLATCOPY(newnode, expr, BoolExpr); |
3179 | 0 | MUTATE(newnode->args, expr->args, List *); |
3180 | 0 | return (Node *) newnode; |
3181 | 0 | } |
3182 | 0 | break; |
3183 | 0 | case T_SubLink: |
3184 | 0 | { |
3185 | 0 | SubLink *sublink = (SubLink *) node; |
3186 | 0 | SubLink *newnode; |
3187 | |
|
3188 | 0 | FLATCOPY(newnode, sublink, SubLink); |
3189 | 0 | MUTATE(newnode->testexpr, sublink->testexpr, Node *); |
3190 | | |
3191 | | /* |
3192 | | * Also invoke the mutator on the sublink's Query node, so it |
3193 | | * can recurse into the sub-query if it wants to. |
3194 | | */ |
3195 | 0 | MUTATE(newnode->subselect, sublink->subselect, Node *); |
3196 | 0 | return (Node *) newnode; |
3197 | 0 | } |
3198 | 0 | break; |
3199 | 0 | case T_SubPlan: |
3200 | 0 | { |
3201 | 0 | SubPlan *subplan = (SubPlan *) node; |
3202 | 0 | SubPlan *newnode; |
3203 | |
|
3204 | 0 | FLATCOPY(newnode, subplan, SubPlan); |
3205 | | /* transform testexpr */ |
3206 | 0 | MUTATE(newnode->testexpr, subplan->testexpr, Node *); |
3207 | | /* transform args list (params to be passed to subplan) */ |
3208 | 0 | MUTATE(newnode->args, subplan->args, List *); |
3209 | | /* but not the sub-Plan itself, which is referenced as-is */ |
3210 | 0 | return (Node *) newnode; |
3211 | 0 | } |
3212 | 0 | break; |
3213 | 0 | case T_AlternativeSubPlan: |
3214 | 0 | { |
3215 | 0 | AlternativeSubPlan *asplan = (AlternativeSubPlan *) node; |
3216 | 0 | AlternativeSubPlan *newnode; |
3217 | |
|
3218 | 0 | FLATCOPY(newnode, asplan, AlternativeSubPlan); |
3219 | 0 | MUTATE(newnode->subplans, asplan->subplans, List *); |
3220 | 0 | return (Node *) newnode; |
3221 | 0 | } |
3222 | 0 | break; |
3223 | 0 | case T_FieldSelect: |
3224 | 0 | { |
3225 | 0 | FieldSelect *fselect = (FieldSelect *) node; |
3226 | 0 | FieldSelect *newnode; |
3227 | |
|
3228 | 0 | FLATCOPY(newnode, fselect, FieldSelect); |
3229 | 0 | MUTATE(newnode->arg, fselect->arg, Expr *); |
3230 | 0 | return (Node *) newnode; |
3231 | 0 | } |
3232 | 0 | break; |
3233 | 0 | case T_FieldStore: |
3234 | 0 | { |
3235 | 0 | FieldStore *fstore = (FieldStore *) node; |
3236 | 0 | FieldStore *newnode; |
3237 | |
|
3238 | 0 | FLATCOPY(newnode, fstore, FieldStore); |
3239 | 0 | MUTATE(newnode->arg, fstore->arg, Expr *); |
3240 | 0 | MUTATE(newnode->newvals, fstore->newvals, List *); |
3241 | 0 | newnode->fieldnums = list_copy(fstore->fieldnums); |
3242 | 0 | return (Node *) newnode; |
3243 | 0 | } |
3244 | 0 | break; |
3245 | 0 | case T_RelabelType: |
3246 | 0 | { |
3247 | 0 | RelabelType *relabel = (RelabelType *) node; |
3248 | 0 | RelabelType *newnode; |
3249 | |
|
3250 | 0 | FLATCOPY(newnode, relabel, RelabelType); |
3251 | 0 | MUTATE(newnode->arg, relabel->arg, Expr *); |
3252 | 0 | return (Node *) newnode; |
3253 | 0 | } |
3254 | 0 | break; |
3255 | 0 | case T_CoerceViaIO: |
3256 | 0 | { |
3257 | 0 | CoerceViaIO *iocoerce = (CoerceViaIO *) node; |
3258 | 0 | CoerceViaIO *newnode; |
3259 | |
|
3260 | 0 | FLATCOPY(newnode, iocoerce, CoerceViaIO); |
3261 | 0 | MUTATE(newnode->arg, iocoerce->arg, Expr *); |
3262 | 0 | return (Node *) newnode; |
3263 | 0 | } |
3264 | 0 | break; |
3265 | 0 | case T_ArrayCoerceExpr: |
3266 | 0 | { |
3267 | 0 | ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; |
3268 | 0 | ArrayCoerceExpr *newnode; |
3269 | |
|
3270 | 0 | FLATCOPY(newnode, acoerce, ArrayCoerceExpr); |
3271 | 0 | MUTATE(newnode->arg, acoerce->arg, Expr *); |
3272 | 0 | MUTATE(newnode->elemexpr, acoerce->elemexpr, Expr *); |
3273 | 0 | return (Node *) newnode; |
3274 | 0 | } |
3275 | 0 | break; |
3276 | 0 | case T_ConvertRowtypeExpr: |
3277 | 0 | { |
3278 | 0 | ConvertRowtypeExpr *convexpr = (ConvertRowtypeExpr *) node; |
3279 | 0 | ConvertRowtypeExpr *newnode; |
3280 | |
|
3281 | 0 | FLATCOPY(newnode, convexpr, ConvertRowtypeExpr); |
3282 | 0 | MUTATE(newnode->arg, convexpr->arg, Expr *); |
3283 | 0 | return (Node *) newnode; |
3284 | 0 | } |
3285 | 0 | break; |
3286 | 0 | case T_CollateExpr: |
3287 | 0 | { |
3288 | 0 | CollateExpr *collate = (CollateExpr *) node; |
3289 | 0 | CollateExpr *newnode; |
3290 | |
|
3291 | 0 | FLATCOPY(newnode, collate, CollateExpr); |
3292 | 0 | MUTATE(newnode->arg, collate->arg, Expr *); |
3293 | 0 | return (Node *) newnode; |
3294 | 0 | } |
3295 | 0 | break; |
3296 | 0 | case T_CaseExpr: |
3297 | 0 | { |
3298 | 0 | CaseExpr *caseexpr = (CaseExpr *) node; |
3299 | 0 | CaseExpr *newnode; |
3300 | |
|
3301 | 0 | FLATCOPY(newnode, caseexpr, CaseExpr); |
3302 | 0 | MUTATE(newnode->arg, caseexpr->arg, Expr *); |
3303 | 0 | MUTATE(newnode->args, caseexpr->args, List *); |
3304 | 0 | MUTATE(newnode->defresult, caseexpr->defresult, Expr *); |
3305 | 0 | return (Node *) newnode; |
3306 | 0 | } |
3307 | 0 | break; |
3308 | 0 | case T_CaseWhen: |
3309 | 0 | { |
3310 | 0 | CaseWhen *casewhen = (CaseWhen *) node; |
3311 | 0 | CaseWhen *newnode; |
3312 | |
|
3313 | 0 | FLATCOPY(newnode, casewhen, CaseWhen); |
3314 | 0 | MUTATE(newnode->expr, casewhen->expr, Expr *); |
3315 | 0 | MUTATE(newnode->result, casewhen->result, Expr *); |
3316 | 0 | return (Node *) newnode; |
3317 | 0 | } |
3318 | 0 | break; |
3319 | 0 | case T_ArrayExpr: |
3320 | 0 | { |
3321 | 0 | ArrayExpr *arrayexpr = (ArrayExpr *) node; |
3322 | 0 | ArrayExpr *newnode; |
3323 | |
|
3324 | 0 | FLATCOPY(newnode, arrayexpr, ArrayExpr); |
3325 | 0 | MUTATE(newnode->elements, arrayexpr->elements, List *); |
3326 | 0 | return (Node *) newnode; |
3327 | 0 | } |
3328 | 0 | break; |
3329 | 0 | case T_RowExpr: |
3330 | 0 | { |
3331 | 0 | RowExpr *rowexpr = (RowExpr *) node; |
3332 | 0 | RowExpr *newnode; |
3333 | |
|
3334 | 0 | FLATCOPY(newnode, rowexpr, RowExpr); |
3335 | 0 | MUTATE(newnode->args, rowexpr->args, List *); |
3336 | | /* Assume colnames needn't be duplicated */ |
3337 | 0 | return (Node *) newnode; |
3338 | 0 | } |
3339 | 0 | break; |
3340 | 0 | case T_RowCompareExpr: |
3341 | 0 | { |
3342 | 0 | RowCompareExpr *rcexpr = (RowCompareExpr *) node; |
3343 | 0 | RowCompareExpr *newnode; |
3344 | |
|
3345 | 0 | FLATCOPY(newnode, rcexpr, RowCompareExpr); |
3346 | 0 | MUTATE(newnode->largs, rcexpr->largs, List *); |
3347 | 0 | MUTATE(newnode->rargs, rcexpr->rargs, List *); |
3348 | 0 | return (Node *) newnode; |
3349 | 0 | } |
3350 | 0 | break; |
3351 | 0 | case T_CoalesceExpr: |
3352 | 0 | { |
3353 | 0 | CoalesceExpr *coalesceexpr = (CoalesceExpr *) node; |
3354 | 0 | CoalesceExpr *newnode; |
3355 | |
|
3356 | 0 | FLATCOPY(newnode, coalesceexpr, CoalesceExpr); |
3357 | 0 | MUTATE(newnode->args, coalesceexpr->args, List *); |
3358 | 0 | return (Node *) newnode; |
3359 | 0 | } |
3360 | 0 | break; |
3361 | 0 | case T_MinMaxExpr: |
3362 | 0 | { |
3363 | 0 | MinMaxExpr *minmaxexpr = (MinMaxExpr *) node; |
3364 | 0 | MinMaxExpr *newnode; |
3365 | |
|
3366 | 0 | FLATCOPY(newnode, minmaxexpr, MinMaxExpr); |
3367 | 0 | MUTATE(newnode->args, minmaxexpr->args, List *); |
3368 | 0 | return (Node *) newnode; |
3369 | 0 | } |
3370 | 0 | break; |
3371 | 0 | case T_XmlExpr: |
3372 | 0 | { |
3373 | 0 | XmlExpr *xexpr = (XmlExpr *) node; |
3374 | 0 | XmlExpr *newnode; |
3375 | |
|
3376 | 0 | FLATCOPY(newnode, xexpr, XmlExpr); |
3377 | 0 | MUTATE(newnode->named_args, xexpr->named_args, List *); |
3378 | | /* assume mutator does not care about arg_names */ |
3379 | 0 | MUTATE(newnode->args, xexpr->args, List *); |
3380 | 0 | return (Node *) newnode; |
3381 | 0 | } |
3382 | 0 | break; |
3383 | 0 | case T_JsonReturning: |
3384 | 0 | { |
3385 | 0 | JsonReturning *jr = (JsonReturning *) node; |
3386 | 0 | JsonReturning *newnode; |
3387 | |
|
3388 | 0 | FLATCOPY(newnode, jr, JsonReturning); |
3389 | 0 | MUTATE(newnode->format, jr->format, JsonFormat *); |
3390 | |
|
3391 | 0 | return (Node *) newnode; |
3392 | 0 | } |
3393 | 0 | case T_JsonValueExpr: |
3394 | 0 | { |
3395 | 0 | JsonValueExpr *jve = (JsonValueExpr *) node; |
3396 | 0 | JsonValueExpr *newnode; |
3397 | |
|
3398 | 0 | FLATCOPY(newnode, jve, JsonValueExpr); |
3399 | 0 | MUTATE(newnode->raw_expr, jve->raw_expr, Expr *); |
3400 | 0 | MUTATE(newnode->formatted_expr, jve->formatted_expr, Expr *); |
3401 | 0 | MUTATE(newnode->format, jve->format, JsonFormat *); |
3402 | |
|
3403 | 0 | return (Node *) newnode; |
3404 | 0 | } |
3405 | 0 | case T_JsonConstructorExpr: |
3406 | 0 | { |
3407 | 0 | JsonConstructorExpr *jce = (JsonConstructorExpr *) node; |
3408 | 0 | JsonConstructorExpr *newnode; |
3409 | |
|
3410 | 0 | FLATCOPY(newnode, jce, JsonConstructorExpr); |
3411 | 0 | MUTATE(newnode->args, jce->args, List *); |
3412 | 0 | MUTATE(newnode->func, jce->func, Expr *); |
3413 | 0 | MUTATE(newnode->coercion, jce->coercion, Expr *); |
3414 | 0 | MUTATE(newnode->returning, jce->returning, JsonReturning *); |
3415 | |
|
3416 | 0 | return (Node *) newnode; |
3417 | 0 | } |
3418 | 0 | case T_JsonIsPredicate: |
3419 | 0 | { |
3420 | 0 | JsonIsPredicate *pred = (JsonIsPredicate *) node; |
3421 | 0 | JsonIsPredicate *newnode; |
3422 | |
|
3423 | 0 | FLATCOPY(newnode, pred, JsonIsPredicate); |
3424 | 0 | MUTATE(newnode->expr, pred->expr, Node *); |
3425 | 0 | MUTATE(newnode->format, pred->format, JsonFormat *); |
3426 | |
|
3427 | 0 | return (Node *) newnode; |
3428 | 0 | } |
3429 | 0 | case T_JsonExpr: |
3430 | 0 | { |
3431 | 0 | JsonExpr *jexpr = (JsonExpr *) node; |
3432 | 0 | JsonExpr *newnode; |
3433 | |
|
3434 | 0 | FLATCOPY(newnode, jexpr, JsonExpr); |
3435 | 0 | MUTATE(newnode->formatted_expr, jexpr->formatted_expr, Node *); |
3436 | 0 | MUTATE(newnode->path_spec, jexpr->path_spec, Node *); |
3437 | 0 | MUTATE(newnode->passing_values, jexpr->passing_values, List *); |
3438 | | /* assume mutator does not care about passing_names */ |
3439 | 0 | MUTATE(newnode->on_empty, jexpr->on_empty, JsonBehavior *); |
3440 | 0 | MUTATE(newnode->on_error, jexpr->on_error, JsonBehavior *); |
3441 | 0 | return (Node *) newnode; |
3442 | 0 | } |
3443 | 0 | break; |
3444 | 0 | case T_JsonBehavior: |
3445 | 0 | { |
3446 | 0 | JsonBehavior *behavior = (JsonBehavior *) node; |
3447 | 0 | JsonBehavior *newnode; |
3448 | |
|
3449 | 0 | FLATCOPY(newnode, behavior, JsonBehavior); |
3450 | 0 | MUTATE(newnode->expr, behavior->expr, Node *); |
3451 | 0 | return (Node *) newnode; |
3452 | 0 | } |
3453 | 0 | break; |
3454 | 0 | case T_NullTest: |
3455 | 0 | { |
3456 | 0 | NullTest *ntest = (NullTest *) node; |
3457 | 0 | NullTest *newnode; |
3458 | |
|
3459 | 0 | FLATCOPY(newnode, ntest, NullTest); |
3460 | 0 | MUTATE(newnode->arg, ntest->arg, Expr *); |
3461 | 0 | return (Node *) newnode; |
3462 | 0 | } |
3463 | 0 | break; |
3464 | 0 | case T_BooleanTest: |
3465 | 0 | { |
3466 | 0 | BooleanTest *btest = (BooleanTest *) node; |
3467 | 0 | BooleanTest *newnode; |
3468 | |
|
3469 | 0 | FLATCOPY(newnode, btest, BooleanTest); |
3470 | 0 | MUTATE(newnode->arg, btest->arg, Expr *); |
3471 | 0 | return (Node *) newnode; |
3472 | 0 | } |
3473 | 0 | break; |
3474 | 0 | case T_CoerceToDomain: |
3475 | 0 | { |
3476 | 0 | CoerceToDomain *ctest = (CoerceToDomain *) node; |
3477 | 0 | CoerceToDomain *newnode; |
3478 | |
|
3479 | 0 | FLATCOPY(newnode, ctest, CoerceToDomain); |
3480 | 0 | MUTATE(newnode->arg, ctest->arg, Expr *); |
3481 | 0 | return (Node *) newnode; |
3482 | 0 | } |
3483 | 0 | break; |
3484 | 0 | case T_ReturningExpr: |
3485 | 0 | { |
3486 | 0 | ReturningExpr *rexpr = (ReturningExpr *) node; |
3487 | 0 | ReturningExpr *newnode; |
3488 | |
|
3489 | 0 | FLATCOPY(newnode, rexpr, ReturningExpr); |
3490 | 0 | MUTATE(newnode->retexpr, rexpr->retexpr, Expr *); |
3491 | 0 | return (Node *) newnode; |
3492 | 0 | } |
3493 | 0 | break; |
3494 | 0 | case T_TargetEntry: |
3495 | 0 | { |
3496 | 0 | TargetEntry *targetentry = (TargetEntry *) node; |
3497 | 0 | TargetEntry *newnode; |
3498 | |
|
3499 | 0 | FLATCOPY(newnode, targetentry, TargetEntry); |
3500 | 0 | MUTATE(newnode->expr, targetentry->expr, Expr *); |
3501 | 0 | return (Node *) newnode; |
3502 | 0 | } |
3503 | 0 | break; |
3504 | 0 | case T_Query: |
3505 | | /* Do nothing with a sub-Query, per discussion above */ |
3506 | 0 | return node; |
3507 | 0 | case T_WindowClause: |
3508 | 0 | { |
3509 | 0 | WindowClause *wc = (WindowClause *) node; |
3510 | 0 | WindowClause *newnode; |
3511 | |
|
3512 | 0 | FLATCOPY(newnode, wc, WindowClause); |
3513 | 0 | MUTATE(newnode->partitionClause, wc->partitionClause, List *); |
3514 | 0 | MUTATE(newnode->orderClause, wc->orderClause, List *); |
3515 | 0 | MUTATE(newnode->startOffset, wc->startOffset, Node *); |
3516 | 0 | MUTATE(newnode->endOffset, wc->endOffset, Node *); |
3517 | 0 | return (Node *) newnode; |
3518 | 0 | } |
3519 | 0 | break; |
3520 | 0 | case T_CTECycleClause: |
3521 | 0 | { |
3522 | 0 | CTECycleClause *cc = (CTECycleClause *) node; |
3523 | 0 | CTECycleClause *newnode; |
3524 | |
|
3525 | 0 | FLATCOPY(newnode, cc, CTECycleClause); |
3526 | 0 | MUTATE(newnode->cycle_mark_value, cc->cycle_mark_value, Node *); |
3527 | 0 | MUTATE(newnode->cycle_mark_default, cc->cycle_mark_default, Node *); |
3528 | 0 | return (Node *) newnode; |
3529 | 0 | } |
3530 | 0 | break; |
3531 | 0 | case T_CommonTableExpr: |
3532 | 0 | { |
3533 | 0 | CommonTableExpr *cte = (CommonTableExpr *) node; |
3534 | 0 | CommonTableExpr *newnode; |
3535 | |
|
3536 | 0 | FLATCOPY(newnode, cte, CommonTableExpr); |
3537 | | |
3538 | | /* |
3539 | | * Also invoke the mutator on the CTE's Query node, so it can |
3540 | | * recurse into the sub-query if it wants to. |
3541 | | */ |
3542 | 0 | MUTATE(newnode->ctequery, cte->ctequery, Node *); |
3543 | |
|
3544 | 0 | MUTATE(newnode->search_clause, cte->search_clause, CTESearchClause *); |
3545 | 0 | MUTATE(newnode->cycle_clause, cte->cycle_clause, CTECycleClause *); |
3546 | |
|
3547 | 0 | return (Node *) newnode; |
3548 | 0 | } |
3549 | 0 | break; |
3550 | 0 | case T_PartitionBoundSpec: |
3551 | 0 | { |
3552 | 0 | PartitionBoundSpec *pbs = (PartitionBoundSpec *) node; |
3553 | 0 | PartitionBoundSpec *newnode; |
3554 | |
|
3555 | 0 | FLATCOPY(newnode, pbs, PartitionBoundSpec); |
3556 | 0 | MUTATE(newnode->listdatums, pbs->listdatums, List *); |
3557 | 0 | MUTATE(newnode->lowerdatums, pbs->lowerdatums, List *); |
3558 | 0 | MUTATE(newnode->upperdatums, pbs->upperdatums, List *); |
3559 | 0 | return (Node *) newnode; |
3560 | 0 | } |
3561 | 0 | break; |
3562 | 0 | case T_PartitionRangeDatum: |
3563 | 0 | { |
3564 | 0 | PartitionRangeDatum *prd = (PartitionRangeDatum *) node; |
3565 | 0 | PartitionRangeDatum *newnode; |
3566 | |
|
3567 | 0 | FLATCOPY(newnode, prd, PartitionRangeDatum); |
3568 | 0 | MUTATE(newnode->value, prd->value, Node *); |
3569 | 0 | return (Node *) newnode; |
3570 | 0 | } |
3571 | 0 | break; |
3572 | 0 | case T_List: |
3573 | 0 | { |
3574 | | /* |
3575 | | * We assume the mutator isn't interested in the list nodes |
3576 | | * per se, so just invoke it on each list element. NOTE: this |
3577 | | * would fail badly on a list with integer elements! |
3578 | | */ |
3579 | 0 | List *resultlist; |
3580 | 0 | ListCell *temp; |
3581 | |
|
3582 | 0 | resultlist = NIL; |
3583 | 0 | foreach(temp, (List *) node) |
3584 | 0 | { |
3585 | 0 | resultlist = lappend(resultlist, |
3586 | 0 | mutator((Node *) lfirst(temp), |
3587 | 0 | context)); |
3588 | 0 | } |
3589 | 0 | return (Node *) resultlist; |
3590 | 0 | } |
3591 | 0 | break; |
3592 | 0 | case T_FromExpr: |
3593 | 0 | { |
3594 | 0 | FromExpr *from = (FromExpr *) node; |
3595 | 0 | FromExpr *newnode; |
3596 | |
|
3597 | 0 | FLATCOPY(newnode, from, FromExpr); |
3598 | 0 | MUTATE(newnode->fromlist, from->fromlist, List *); |
3599 | 0 | MUTATE(newnode->quals, from->quals, Node *); |
3600 | 0 | return (Node *) newnode; |
3601 | 0 | } |
3602 | 0 | break; |
3603 | 0 | case T_OnConflictExpr: |
3604 | 0 | { |
3605 | 0 | OnConflictExpr *oc = (OnConflictExpr *) node; |
3606 | 0 | OnConflictExpr *newnode; |
3607 | |
|
3608 | 0 | FLATCOPY(newnode, oc, OnConflictExpr); |
3609 | 0 | MUTATE(newnode->arbiterElems, oc->arbiterElems, List *); |
3610 | 0 | MUTATE(newnode->arbiterWhere, oc->arbiterWhere, Node *); |
3611 | 0 | MUTATE(newnode->onConflictSet, oc->onConflictSet, List *); |
3612 | 0 | MUTATE(newnode->onConflictWhere, oc->onConflictWhere, Node *); |
3613 | 0 | MUTATE(newnode->exclRelTlist, oc->exclRelTlist, List *); |
3614 | |
|
3615 | 0 | return (Node *) newnode; |
3616 | 0 | } |
3617 | 0 | break; |
3618 | 0 | case T_MergeAction: |
3619 | 0 | { |
3620 | 0 | MergeAction *action = (MergeAction *) node; |
3621 | 0 | MergeAction *newnode; |
3622 | |
|
3623 | 0 | FLATCOPY(newnode, action, MergeAction); |
3624 | 0 | MUTATE(newnode->qual, action->qual, Node *); |
3625 | 0 | MUTATE(newnode->targetList, action->targetList, List *); |
3626 | |
|
3627 | 0 | return (Node *) newnode; |
3628 | 0 | } |
3629 | 0 | break; |
3630 | 0 | case T_PartitionPruneStepOp: |
3631 | 0 | { |
3632 | 0 | PartitionPruneStepOp *opstep = (PartitionPruneStepOp *) node; |
3633 | 0 | PartitionPruneStepOp *newnode; |
3634 | |
|
3635 | 0 | FLATCOPY(newnode, opstep, PartitionPruneStepOp); |
3636 | 0 | MUTATE(newnode->exprs, opstep->exprs, List *); |
3637 | |
|
3638 | 0 | return (Node *) newnode; |
3639 | 0 | } |
3640 | 0 | break; |
3641 | 0 | case T_PartitionPruneStepCombine: |
3642 | | /* no expression sub-nodes */ |
3643 | 0 | return copyObject(node); |
3644 | 0 | case T_JoinExpr: |
3645 | 0 | { |
3646 | 0 | JoinExpr *join = (JoinExpr *) node; |
3647 | 0 | JoinExpr *newnode; |
3648 | |
|
3649 | 0 | FLATCOPY(newnode, join, JoinExpr); |
3650 | 0 | MUTATE(newnode->larg, join->larg, Node *); |
3651 | 0 | MUTATE(newnode->rarg, join->rarg, Node *); |
3652 | 0 | MUTATE(newnode->quals, join->quals, Node *); |
3653 | | /* We do not mutate alias or using by default */ |
3654 | 0 | return (Node *) newnode; |
3655 | 0 | } |
3656 | 0 | break; |
3657 | 0 | case T_SetOperationStmt: |
3658 | 0 | { |
3659 | 0 | SetOperationStmt *setop = (SetOperationStmt *) node; |
3660 | 0 | SetOperationStmt *newnode; |
3661 | |
|
3662 | 0 | FLATCOPY(newnode, setop, SetOperationStmt); |
3663 | 0 | MUTATE(newnode->larg, setop->larg, Node *); |
3664 | 0 | MUTATE(newnode->rarg, setop->rarg, Node *); |
3665 | | /* We do not mutate groupClauses by default */ |
3666 | 0 | return (Node *) newnode; |
3667 | 0 | } |
3668 | 0 | break; |
3669 | 0 | case T_IndexClause: |
3670 | 0 | { |
3671 | 0 | IndexClause *iclause = (IndexClause *) node; |
3672 | 0 | IndexClause *newnode; |
3673 | |
|
3674 | 0 | FLATCOPY(newnode, iclause, IndexClause); |
3675 | 0 | MUTATE(newnode->rinfo, iclause->rinfo, RestrictInfo *); |
3676 | 0 | MUTATE(newnode->indexquals, iclause->indexquals, List *); |
3677 | 0 | return (Node *) newnode; |
3678 | 0 | } |
3679 | 0 | break; |
3680 | 0 | case T_PlaceHolderVar: |
3681 | 0 | { |
3682 | 0 | PlaceHolderVar *phv = (PlaceHolderVar *) node; |
3683 | 0 | PlaceHolderVar *newnode; |
3684 | |
|
3685 | 0 | FLATCOPY(newnode, phv, PlaceHolderVar); |
3686 | 0 | MUTATE(newnode->phexpr, phv->phexpr, Expr *); |
3687 | | /* Assume we need not copy the relids bitmapsets */ |
3688 | 0 | return (Node *) newnode; |
3689 | 0 | } |
3690 | 0 | break; |
3691 | 0 | case T_InferenceElem: |
3692 | 0 | { |
3693 | 0 | InferenceElem *inferenceelemdexpr = (InferenceElem *) node; |
3694 | 0 | InferenceElem *newnode; |
3695 | |
|
3696 | 0 | FLATCOPY(newnode, inferenceelemdexpr, InferenceElem); |
3697 | 0 | MUTATE(newnode->expr, newnode->expr, Node *); |
3698 | 0 | return (Node *) newnode; |
3699 | 0 | } |
3700 | 0 | break; |
3701 | 0 | case T_AppendRelInfo: |
3702 | 0 | { |
3703 | 0 | AppendRelInfo *appinfo = (AppendRelInfo *) node; |
3704 | 0 | AppendRelInfo *newnode; |
3705 | |
|
3706 | 0 | FLATCOPY(newnode, appinfo, AppendRelInfo); |
3707 | 0 | MUTATE(newnode->translated_vars, appinfo->translated_vars, List *); |
3708 | | /* Assume nothing need be done with parent_colnos[] */ |
3709 | 0 | return (Node *) newnode; |
3710 | 0 | } |
3711 | 0 | break; |
3712 | 0 | case T_PlaceHolderInfo: |
3713 | 0 | { |
3714 | 0 | PlaceHolderInfo *phinfo = (PlaceHolderInfo *) node; |
3715 | 0 | PlaceHolderInfo *newnode; |
3716 | |
|
3717 | 0 | FLATCOPY(newnode, phinfo, PlaceHolderInfo); |
3718 | 0 | MUTATE(newnode->ph_var, phinfo->ph_var, PlaceHolderVar *); |
3719 | | /* Assume we need not copy the relids bitmapsets */ |
3720 | 0 | return (Node *) newnode; |
3721 | 0 | } |
3722 | 0 | break; |
3723 | 0 | case T_RangeTblFunction: |
3724 | 0 | { |
3725 | 0 | RangeTblFunction *rtfunc = (RangeTblFunction *) node; |
3726 | 0 | RangeTblFunction *newnode; |
3727 | |
|
3728 | 0 | FLATCOPY(newnode, rtfunc, RangeTblFunction); |
3729 | 0 | MUTATE(newnode->funcexpr, rtfunc->funcexpr, Node *); |
3730 | | /* Assume we need not copy the coldef info lists */ |
3731 | 0 | return (Node *) newnode; |
3732 | 0 | } |
3733 | 0 | break; |
3734 | 0 | case T_TableSampleClause: |
3735 | 0 | { |
3736 | 0 | TableSampleClause *tsc = (TableSampleClause *) node; |
3737 | 0 | TableSampleClause *newnode; |
3738 | |
|
3739 | 0 | FLATCOPY(newnode, tsc, TableSampleClause); |
3740 | 0 | MUTATE(newnode->args, tsc->args, List *); |
3741 | 0 | MUTATE(newnode->repeatable, tsc->repeatable, Expr *); |
3742 | 0 | return (Node *) newnode; |
3743 | 0 | } |
3744 | 0 | break; |
3745 | 0 | case T_TableFunc: |
3746 | 0 | { |
3747 | 0 | TableFunc *tf = (TableFunc *) node; |
3748 | 0 | TableFunc *newnode; |
3749 | |
|
3750 | 0 | FLATCOPY(newnode, tf, TableFunc); |
3751 | 0 | MUTATE(newnode->ns_uris, tf->ns_uris, List *); |
3752 | 0 | MUTATE(newnode->docexpr, tf->docexpr, Node *); |
3753 | 0 | MUTATE(newnode->rowexpr, tf->rowexpr, Node *); |
3754 | 0 | MUTATE(newnode->colexprs, tf->colexprs, List *); |
3755 | 0 | MUTATE(newnode->coldefexprs, tf->coldefexprs, List *); |
3756 | 0 | MUTATE(newnode->colvalexprs, tf->colvalexprs, List *); |
3757 | 0 | MUTATE(newnode->passingvalexprs, tf->passingvalexprs, List *); |
3758 | 0 | return (Node *) newnode; |
3759 | 0 | } |
3760 | 0 | break; |
3761 | 0 | default: |
3762 | 0 | elog(ERROR, "unrecognized node type: %d", |
3763 | 0 | (int) nodeTag(node)); |
3764 | 0 | break; |
3765 | 0 | } |
3766 | | /* can't get here, but keep compiler happy */ |
3767 | 0 | return NULL; |
3768 | 0 | } |
3769 | | |
3770 | | |
3771 | | /* |
3772 | | * query_tree_mutator --- initiate modification of a Query's expressions |
3773 | | * |
3774 | | * This routine exists just to reduce the number of places that need to know |
3775 | | * where all the expression subtrees of a Query are. Note it can be used |
3776 | | * for starting a walk at top level of a Query regardless of whether the |
3777 | | * mutator intends to descend into subqueries. It is also useful for |
3778 | | * descending into subqueries within a mutator. |
3779 | | * |
3780 | | * Some callers want to suppress mutating of certain items in the Query, |
3781 | | * typically because they need to process them specially, or don't actually |
3782 | | * want to recurse into subqueries. This is supported by the flags argument, |
3783 | | * which is the bitwise OR of flag values to suppress mutating of |
3784 | | * indicated items. (More flag bits may be added as needed.) |
3785 | | * |
3786 | | * Normally the top-level Query node itself is copied, but some callers want |
3787 | | * it to be modified in-place; they must pass QTW_DONT_COPY_QUERY in flags. |
3788 | | * All modified substructure is safely copied in any case. |
3789 | | */ |
3790 | | pg_attribute_no_sanitize_function() |
3791 | | Query * |
3792 | | query_tree_mutator_impl(Query *query, |
3793 | | tree_mutator_callback mutator, |
3794 | | void *context, |
3795 | | int flags) |
3796 | 0 | { |
3797 | 0 | Assert(query != NULL && IsA(query, Query)); |
3798 | |
|
3799 | 0 | if (!(flags & QTW_DONT_COPY_QUERY)) |
3800 | 0 | { |
3801 | 0 | Query *newquery; |
3802 | |
|
3803 | 0 | FLATCOPY(newquery, query, Query); |
3804 | 0 | query = newquery; |
3805 | 0 | } |
3806 | |
|
3807 | 0 | MUTATE(query->targetList, query->targetList, List *); |
3808 | 0 | MUTATE(query->withCheckOptions, query->withCheckOptions, List *); |
3809 | 0 | MUTATE(query->onConflict, query->onConflict, OnConflictExpr *); |
3810 | 0 | MUTATE(query->mergeActionList, query->mergeActionList, List *); |
3811 | 0 | MUTATE(query->mergeJoinCondition, query->mergeJoinCondition, Node *); |
3812 | 0 | MUTATE(query->returningList, query->returningList, List *); |
3813 | 0 | MUTATE(query->jointree, query->jointree, FromExpr *); |
3814 | 0 | MUTATE(query->setOperations, query->setOperations, Node *); |
3815 | 0 | MUTATE(query->havingQual, query->havingQual, Node *); |
3816 | 0 | MUTATE(query->limitOffset, query->limitOffset, Node *); |
3817 | 0 | MUTATE(query->limitCount, query->limitCount, Node *); |
3818 | | |
3819 | | /* |
3820 | | * Most callers aren't interested in SortGroupClause nodes since those |
3821 | | * don't contain actual expressions. However they do contain OIDs, which |
3822 | | * may be of interest to some mutators. |
3823 | | */ |
3824 | |
|
3825 | 0 | if ((flags & QTW_EXAMINE_SORTGROUP)) |
3826 | 0 | { |
3827 | 0 | MUTATE(query->groupClause, query->groupClause, List *); |
3828 | 0 | MUTATE(query->windowClause, query->windowClause, List *); |
3829 | 0 | MUTATE(query->sortClause, query->sortClause, List *); |
3830 | 0 | MUTATE(query->distinctClause, query->distinctClause, List *); |
3831 | 0 | } |
3832 | 0 | else |
3833 | 0 | { |
3834 | | /* |
3835 | | * But we need to mutate the expressions under WindowClause nodes even |
3836 | | * if we're not interested in SortGroupClause nodes. |
3837 | | */ |
3838 | 0 | List *resultlist; |
3839 | 0 | ListCell *temp; |
3840 | |
|
3841 | 0 | resultlist = NIL; |
3842 | 0 | foreach(temp, query->windowClause) |
3843 | 0 | { |
3844 | 0 | WindowClause *wc = lfirst_node(WindowClause, temp); |
3845 | 0 | WindowClause *newnode; |
3846 | |
|
3847 | 0 | FLATCOPY(newnode, wc, WindowClause); |
3848 | 0 | MUTATE(newnode->startOffset, wc->startOffset, Node *); |
3849 | 0 | MUTATE(newnode->endOffset, wc->endOffset, Node *); |
3850 | |
|
3851 | 0 | resultlist = lappend(resultlist, (Node *) newnode); |
3852 | 0 | } |
3853 | 0 | query->windowClause = resultlist; |
3854 | 0 | } |
3855 | | |
3856 | | /* |
3857 | | * groupingSets and rowMarks are not mutated: |
3858 | | * |
3859 | | * groupingSets contain only ressortgroup refs (integers) which are |
3860 | | * meaningless without the groupClause or tlist. Accordingly, any mutator |
3861 | | * that needs to care about them needs to handle them itself in its Query |
3862 | | * processing. |
3863 | | * |
3864 | | * rowMarks contains only rangetable indexes (and flags etc.) and |
3865 | | * therefore should be handled at Query level similarly. |
3866 | | */ |
3867 | |
|
3868 | 0 | if (!(flags & QTW_IGNORE_CTE_SUBQUERIES)) |
3869 | 0 | MUTATE(query->cteList, query->cteList, List *); |
3870 | 0 | else /* else copy CTE list as-is */ |
3871 | 0 | query->cteList = copyObject(query->cteList); |
3872 | 0 | query->rtable = range_table_mutator(query->rtable, |
3873 | 0 | mutator, context, flags); |
3874 | 0 | return query; |
3875 | 0 | } |
3876 | | |
3877 | | /* |
3878 | | * range_table_mutator is just the part of query_tree_mutator that processes |
3879 | | * a query's rangetable. This is split out since it can be useful on |
3880 | | * its own. |
3881 | | */ |
3882 | | pg_attribute_no_sanitize_function() |
3883 | | List * |
3884 | | range_table_mutator_impl(List *rtable, |
3885 | | tree_mutator_callback mutator, |
3886 | | void *context, |
3887 | | int flags) |
3888 | 0 | { |
3889 | 0 | List *newrt = NIL; |
3890 | 0 | ListCell *rt; |
3891 | |
|
3892 | 0 | foreach(rt, rtable) |
3893 | 0 | { |
3894 | 0 | RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt); |
3895 | 0 | RangeTblEntry *newrte; |
3896 | |
|
3897 | 0 | FLATCOPY(newrte, rte, RangeTblEntry); |
3898 | 0 | switch (rte->rtekind) |
3899 | 0 | { |
3900 | 0 | case RTE_RELATION: |
3901 | 0 | MUTATE(newrte->tablesample, rte->tablesample, |
3902 | 0 | TableSampleClause *); |
3903 | | /* we don't bother to copy eref, aliases, etc; OK? */ |
3904 | 0 | break; |
3905 | 0 | case RTE_SUBQUERY: |
3906 | 0 | if (!(flags & QTW_IGNORE_RT_SUBQUERIES)) |
3907 | 0 | MUTATE(newrte->subquery, rte->subquery, Query *); |
3908 | 0 | else |
3909 | 0 | { |
3910 | | /* else, copy RT subqueries as-is */ |
3911 | 0 | newrte->subquery = copyObject(rte->subquery); |
3912 | 0 | } |
3913 | 0 | break; |
3914 | 0 | case RTE_JOIN: |
3915 | 0 | if (!(flags & QTW_IGNORE_JOINALIASES)) |
3916 | 0 | MUTATE(newrte->joinaliasvars, rte->joinaliasvars, List *); |
3917 | 0 | else |
3918 | 0 | { |
3919 | | /* else, copy join aliases as-is */ |
3920 | 0 | newrte->joinaliasvars = copyObject(rte->joinaliasvars); |
3921 | 0 | } |
3922 | 0 | break; |
3923 | 0 | case RTE_FUNCTION: |
3924 | 0 | MUTATE(newrte->functions, rte->functions, List *); |
3925 | 0 | break; |
3926 | 0 | case RTE_TABLEFUNC: |
3927 | 0 | MUTATE(newrte->tablefunc, rte->tablefunc, TableFunc *); |
3928 | 0 | break; |
3929 | 0 | case RTE_VALUES: |
3930 | 0 | MUTATE(newrte->values_lists, rte->values_lists, List *); |
3931 | 0 | break; |
3932 | 0 | case RTE_CTE: |
3933 | 0 | case RTE_NAMEDTUPLESTORE: |
3934 | 0 | case RTE_RESULT: |
3935 | | /* nothing to do */ |
3936 | 0 | break; |
3937 | 0 | case RTE_GROUP: |
3938 | 0 | if (!(flags & QTW_IGNORE_GROUPEXPRS)) |
3939 | 0 | MUTATE(newrte->groupexprs, rte->groupexprs, List *); |
3940 | 0 | else |
3941 | 0 | { |
3942 | | /* else, copy grouping exprs as-is */ |
3943 | 0 | newrte->groupexprs = copyObject(rte->groupexprs); |
3944 | 0 | } |
3945 | 0 | break; |
3946 | 0 | } |
3947 | 0 | MUTATE(newrte->securityQuals, rte->securityQuals, List *); |
3948 | 0 | newrt = lappend(newrt, newrte); |
3949 | 0 | } |
3950 | 0 | return newrt; |
3951 | 0 | } |
3952 | | |
3953 | | /* |
3954 | | * query_or_expression_tree_walker --- hybrid form |
3955 | | * |
3956 | | * This routine will invoke query_tree_walker if called on a Query node, |
3957 | | * else will invoke the walker directly. This is a useful way of starting |
3958 | | * the recursion when the walker's normal change of state is not appropriate |
3959 | | * for the outermost Query node. |
3960 | | */ |
3961 | | pg_attribute_no_sanitize_function() |
3962 | | bool |
3963 | | query_or_expression_tree_walker_impl(Node *node, |
3964 | | tree_walker_callback walker, |
3965 | | void *context, |
3966 | | int flags) |
3967 | 0 | { |
3968 | 0 | if (node && IsA(node, Query)) |
3969 | 0 | return query_tree_walker((Query *) node, |
3970 | 0 | walker, |
3971 | 0 | context, |
3972 | 0 | flags); |
3973 | 0 | else |
3974 | 0 | return WALK(node); |
3975 | 0 | } |
3976 | | |
3977 | | /* |
3978 | | * query_or_expression_tree_mutator --- hybrid form |
3979 | | * |
3980 | | * This routine will invoke query_tree_mutator if called on a Query node, |
3981 | | * else will invoke the mutator directly. This is a useful way of starting |
3982 | | * the recursion when the mutator's normal change of state is not appropriate |
3983 | | * for the outermost Query node. |
3984 | | */ |
3985 | | pg_attribute_no_sanitize_function() |
3986 | | Node * |
3987 | | query_or_expression_tree_mutator_impl(Node *node, |
3988 | | tree_mutator_callback mutator, |
3989 | | void *context, |
3990 | | int flags) |
3991 | 0 | { |
3992 | 0 | if (node && IsA(node, Query)) |
3993 | 0 | return (Node *) query_tree_mutator((Query *) node, |
3994 | 0 | mutator, |
3995 | 0 | context, |
3996 | 0 | flags); |
3997 | 0 | else |
3998 | 0 | return mutator(node, context); |
3999 | 0 | } |
4000 | | |
4001 | | |
4002 | | /* |
4003 | | * raw_expression_tree_walker --- walk raw parse trees |
4004 | | * |
4005 | | * This has exactly the same API as expression_tree_walker, but instead of |
4006 | | * walking post-analysis parse trees, it knows how to walk the node types |
4007 | | * found in raw grammar output. (There is not currently any need for a |
4008 | | * combined walker, so we keep them separate in the name of efficiency.) |
4009 | | * Unlike expression_tree_walker, there is no special rule about query |
4010 | | * boundaries: we descend to everything that's possibly interesting. |
4011 | | * |
4012 | | * Currently, the node type coverage here extends only to DML statements |
4013 | | * (SELECT/INSERT/UPDATE/DELETE/MERGE) and nodes that can appear in them, |
4014 | | * because this is used mainly during analysis of CTEs, and only DML |
4015 | | * statements can appear in CTEs. |
4016 | | */ |
4017 | | pg_attribute_no_sanitize_function() |
4018 | | bool |
4019 | | raw_expression_tree_walker_impl(Node *node, |
4020 | | tree_walker_callback walker, |
4021 | | void *context) |
4022 | 0 | { |
4023 | 0 | ListCell *temp; |
4024 | | |
4025 | | /* |
4026 | | * The walker has already visited the current node, and so we need only |
4027 | | * recurse into any sub-nodes it has. |
4028 | | */ |
4029 | 0 | if (node == NULL) |
4030 | 0 | return false; |
4031 | | |
4032 | | /* Guard against stack overflow due to overly complex expressions */ |
4033 | 0 | check_stack_depth(); |
4034 | |
|
4035 | 0 | switch (nodeTag(node)) |
4036 | 0 | { |
4037 | 0 | case T_JsonFormat: |
4038 | 0 | case T_SetToDefault: |
4039 | 0 | case T_CurrentOfExpr: |
4040 | 0 | case T_SQLValueFunction: |
4041 | 0 | case T_Integer: |
4042 | 0 | case T_Float: |
4043 | 0 | case T_Boolean: |
4044 | 0 | case T_String: |
4045 | 0 | case T_BitString: |
4046 | 0 | case T_ParamRef: |
4047 | 0 | case T_A_Const: |
4048 | 0 | case T_A_Star: |
4049 | 0 | case T_MergeSupportFunc: |
4050 | 0 | case T_ReturningOption: |
4051 | | /* primitive node types with no subnodes */ |
4052 | 0 | break; |
4053 | 0 | case T_Alias: |
4054 | | /* we assume the colnames list isn't interesting */ |
4055 | 0 | break; |
4056 | 0 | case T_RangeVar: |
4057 | 0 | return WALK(((RangeVar *) node)->alias); |
4058 | 0 | case T_GroupingFunc: |
4059 | 0 | return WALK(((GroupingFunc *) node)->args); |
4060 | 0 | case T_SubLink: |
4061 | 0 | { |
4062 | 0 | SubLink *sublink = (SubLink *) node; |
4063 | |
|
4064 | 0 | if (WALK(sublink->testexpr)) |
4065 | 0 | return true; |
4066 | | /* we assume the operName is not interesting */ |
4067 | 0 | if (WALK(sublink->subselect)) |
4068 | 0 | return true; |
4069 | 0 | } |
4070 | 0 | break; |
4071 | 0 | case T_CaseExpr: |
4072 | 0 | { |
4073 | 0 | CaseExpr *caseexpr = (CaseExpr *) node; |
4074 | |
|
4075 | 0 | if (WALK(caseexpr->arg)) |
4076 | 0 | return true; |
4077 | | /* we assume walker doesn't care about CaseWhens, either */ |
4078 | 0 | foreach(temp, caseexpr->args) |
4079 | 0 | { |
4080 | 0 | CaseWhen *when = lfirst_node(CaseWhen, temp); |
4081 | |
|
4082 | 0 | if (WALK(when->expr)) |
4083 | 0 | return true; |
4084 | 0 | if (WALK(when->result)) |
4085 | 0 | return true; |
4086 | 0 | } |
4087 | 0 | if (WALK(caseexpr->defresult)) |
4088 | 0 | return true; |
4089 | 0 | } |
4090 | 0 | break; |
4091 | 0 | case T_RowExpr: |
4092 | | /* Assume colnames isn't interesting */ |
4093 | 0 | return WALK(((RowExpr *) node)->args); |
4094 | 0 | case T_CoalesceExpr: |
4095 | 0 | return WALK(((CoalesceExpr *) node)->args); |
4096 | 0 | case T_MinMaxExpr: |
4097 | 0 | return WALK(((MinMaxExpr *) node)->args); |
4098 | 0 | case T_XmlExpr: |
4099 | 0 | { |
4100 | 0 | XmlExpr *xexpr = (XmlExpr *) node; |
4101 | |
|
4102 | 0 | if (WALK(xexpr->named_args)) |
4103 | 0 | return true; |
4104 | | /* we assume walker doesn't care about arg_names */ |
4105 | 0 | if (WALK(xexpr->args)) |
4106 | 0 | return true; |
4107 | 0 | } |
4108 | 0 | break; |
4109 | 0 | case T_JsonReturning: |
4110 | 0 | return WALK(((JsonReturning *) node)->format); |
4111 | 0 | case T_JsonValueExpr: |
4112 | 0 | { |
4113 | 0 | JsonValueExpr *jve = (JsonValueExpr *) node; |
4114 | |
|
4115 | 0 | if (WALK(jve->raw_expr)) |
4116 | 0 | return true; |
4117 | 0 | if (WALK(jve->formatted_expr)) |
4118 | 0 | return true; |
4119 | 0 | if (WALK(jve->format)) |
4120 | 0 | return true; |
4121 | 0 | } |
4122 | 0 | break; |
4123 | 0 | case T_JsonParseExpr: |
4124 | 0 | { |
4125 | 0 | JsonParseExpr *jpe = (JsonParseExpr *) node; |
4126 | |
|
4127 | 0 | if (WALK(jpe->expr)) |
4128 | 0 | return true; |
4129 | 0 | if (WALK(jpe->output)) |
4130 | 0 | return true; |
4131 | 0 | } |
4132 | 0 | break; |
4133 | 0 | case T_JsonScalarExpr: |
4134 | 0 | { |
4135 | 0 | JsonScalarExpr *jse = (JsonScalarExpr *) node; |
4136 | |
|
4137 | 0 | if (WALK(jse->expr)) |
4138 | 0 | return true; |
4139 | 0 | if (WALK(jse->output)) |
4140 | 0 | return true; |
4141 | 0 | } |
4142 | 0 | break; |
4143 | 0 | case T_JsonSerializeExpr: |
4144 | 0 | { |
4145 | 0 | JsonSerializeExpr *jse = (JsonSerializeExpr *) node; |
4146 | |
|
4147 | 0 | if (WALK(jse->expr)) |
4148 | 0 | return true; |
4149 | 0 | if (WALK(jse->output)) |
4150 | 0 | return true; |
4151 | 0 | } |
4152 | 0 | break; |
4153 | 0 | case T_JsonConstructorExpr: |
4154 | 0 | { |
4155 | 0 | JsonConstructorExpr *ctor = (JsonConstructorExpr *) node; |
4156 | |
|
4157 | 0 | if (WALK(ctor->args)) |
4158 | 0 | return true; |
4159 | 0 | if (WALK(ctor->func)) |
4160 | 0 | return true; |
4161 | 0 | if (WALK(ctor->coercion)) |
4162 | 0 | return true; |
4163 | 0 | if (WALK(ctor->returning)) |
4164 | 0 | return true; |
4165 | 0 | } |
4166 | 0 | break; |
4167 | 0 | case T_JsonIsPredicate: |
4168 | 0 | return WALK(((JsonIsPredicate *) node)->expr); |
4169 | 0 | case T_JsonArgument: |
4170 | 0 | return WALK(((JsonArgument *) node)->val); |
4171 | 0 | case T_JsonFuncExpr: |
4172 | 0 | { |
4173 | 0 | JsonFuncExpr *jfe = (JsonFuncExpr *) node; |
4174 | |
|
4175 | 0 | if (WALK(jfe->context_item)) |
4176 | 0 | return true; |
4177 | 0 | if (WALK(jfe->pathspec)) |
4178 | 0 | return true; |
4179 | 0 | if (WALK(jfe->passing)) |
4180 | 0 | return true; |
4181 | 0 | if (WALK(jfe->output)) |
4182 | 0 | return true; |
4183 | 0 | if (WALK(jfe->on_empty)) |
4184 | 0 | return true; |
4185 | 0 | if (WALK(jfe->on_error)) |
4186 | 0 | return true; |
4187 | 0 | } |
4188 | 0 | break; |
4189 | 0 | case T_JsonBehavior: |
4190 | 0 | { |
4191 | 0 | JsonBehavior *jb = (JsonBehavior *) node; |
4192 | |
|
4193 | 0 | if (WALK(jb->expr)) |
4194 | 0 | return true; |
4195 | 0 | } |
4196 | 0 | break; |
4197 | 0 | case T_JsonTable: |
4198 | 0 | { |
4199 | 0 | JsonTable *jt = (JsonTable *) node; |
4200 | |
|
4201 | 0 | if (WALK(jt->context_item)) |
4202 | 0 | return true; |
4203 | 0 | if (WALK(jt->pathspec)) |
4204 | 0 | return true; |
4205 | 0 | if (WALK(jt->passing)) |
4206 | 0 | return true; |
4207 | 0 | if (WALK(jt->columns)) |
4208 | 0 | return true; |
4209 | 0 | if (WALK(jt->on_error)) |
4210 | 0 | return true; |
4211 | 0 | } |
4212 | 0 | break; |
4213 | 0 | case T_JsonTableColumn: |
4214 | 0 | { |
4215 | 0 | JsonTableColumn *jtc = (JsonTableColumn *) node; |
4216 | |
|
4217 | 0 | if (WALK(jtc->typeName)) |
4218 | 0 | return true; |
4219 | 0 | if (WALK(jtc->on_empty)) |
4220 | 0 | return true; |
4221 | 0 | if (WALK(jtc->on_error)) |
4222 | 0 | return true; |
4223 | 0 | if (WALK(jtc->columns)) |
4224 | 0 | return true; |
4225 | 0 | } |
4226 | 0 | break; |
4227 | 0 | case T_JsonTablePathSpec: |
4228 | 0 | return WALK(((JsonTablePathSpec *) node)->string); |
4229 | 0 | case T_NullTest: |
4230 | 0 | return WALK(((NullTest *) node)->arg); |
4231 | 0 | case T_BooleanTest: |
4232 | 0 | return WALK(((BooleanTest *) node)->arg); |
4233 | 0 | case T_JoinExpr: |
4234 | 0 | { |
4235 | 0 | JoinExpr *join = (JoinExpr *) node; |
4236 | |
|
4237 | 0 | if (WALK(join->larg)) |
4238 | 0 | return true; |
4239 | 0 | if (WALK(join->rarg)) |
4240 | 0 | return true; |
4241 | 0 | if (WALK(join->quals)) |
4242 | 0 | return true; |
4243 | 0 | if (WALK(join->alias)) |
4244 | 0 | return true; |
4245 | | /* using list is deemed uninteresting */ |
4246 | 0 | } |
4247 | 0 | break; |
4248 | 0 | case T_IntoClause: |
4249 | 0 | { |
4250 | 0 | IntoClause *into = (IntoClause *) node; |
4251 | |
|
4252 | 0 | if (WALK(into->rel)) |
4253 | 0 | return true; |
4254 | | /* colNames, options are deemed uninteresting */ |
4255 | | /* viewQuery should be null in raw parsetree, but check it */ |
4256 | 0 | if (WALK(into->viewQuery)) |
4257 | 0 | return true; |
4258 | 0 | } |
4259 | 0 | break; |
4260 | 0 | case T_List: |
4261 | 0 | foreach(temp, (List *) node) |
4262 | 0 | { |
4263 | 0 | if (WALK((Node *) lfirst(temp))) |
4264 | 0 | return true; |
4265 | 0 | } |
4266 | 0 | break; |
4267 | 0 | case T_InsertStmt: |
4268 | 0 | { |
4269 | 0 | InsertStmt *stmt = (InsertStmt *) node; |
4270 | |
|
4271 | 0 | if (WALK(stmt->relation)) |
4272 | 0 | return true; |
4273 | 0 | if (WALK(stmt->cols)) |
4274 | 0 | return true; |
4275 | 0 | if (WALK(stmt->selectStmt)) |
4276 | 0 | return true; |
4277 | 0 | if (WALK(stmt->onConflictClause)) |
4278 | 0 | return true; |
4279 | 0 | if (WALK(stmt->returningClause)) |
4280 | 0 | return true; |
4281 | 0 | if (WALK(stmt->withClause)) |
4282 | 0 | return true; |
4283 | 0 | } |
4284 | 0 | break; |
4285 | 0 | case T_DeleteStmt: |
4286 | 0 | { |
4287 | 0 | DeleteStmt *stmt = (DeleteStmt *) node; |
4288 | |
|
4289 | 0 | if (WALK(stmt->relation)) |
4290 | 0 | return true; |
4291 | 0 | if (WALK(stmt->usingClause)) |
4292 | 0 | return true; |
4293 | 0 | if (WALK(stmt->whereClause)) |
4294 | 0 | return true; |
4295 | 0 | if (WALK(stmt->returningClause)) |
4296 | 0 | return true; |
4297 | 0 | if (WALK(stmt->withClause)) |
4298 | 0 | return true; |
4299 | 0 | } |
4300 | 0 | break; |
4301 | 0 | case T_UpdateStmt: |
4302 | 0 | { |
4303 | 0 | UpdateStmt *stmt = (UpdateStmt *) node; |
4304 | |
|
4305 | 0 | if (WALK(stmt->relation)) |
4306 | 0 | return true; |
4307 | 0 | if (WALK(stmt->targetList)) |
4308 | 0 | return true; |
4309 | 0 | if (WALK(stmt->whereClause)) |
4310 | 0 | return true; |
4311 | 0 | if (WALK(stmt->fromClause)) |
4312 | 0 | return true; |
4313 | 0 | if (WALK(stmt->returningClause)) |
4314 | 0 | return true; |
4315 | 0 | if (WALK(stmt->withClause)) |
4316 | 0 | return true; |
4317 | 0 | } |
4318 | 0 | break; |
4319 | 0 | case T_MergeStmt: |
4320 | 0 | { |
4321 | 0 | MergeStmt *stmt = (MergeStmt *) node; |
4322 | |
|
4323 | 0 | if (WALK(stmt->relation)) |
4324 | 0 | return true; |
4325 | 0 | if (WALK(stmt->sourceRelation)) |
4326 | 0 | return true; |
4327 | 0 | if (WALK(stmt->joinCondition)) |
4328 | 0 | return true; |
4329 | 0 | if (WALK(stmt->mergeWhenClauses)) |
4330 | 0 | return true; |
4331 | 0 | if (WALK(stmt->returningClause)) |
4332 | 0 | return true; |
4333 | 0 | if (WALK(stmt->withClause)) |
4334 | 0 | return true; |
4335 | 0 | } |
4336 | 0 | break; |
4337 | 0 | case T_MergeWhenClause: |
4338 | 0 | { |
4339 | 0 | MergeWhenClause *mergeWhenClause = (MergeWhenClause *) node; |
4340 | |
|
4341 | 0 | if (WALK(mergeWhenClause->condition)) |
4342 | 0 | return true; |
4343 | 0 | if (WALK(mergeWhenClause->targetList)) |
4344 | 0 | return true; |
4345 | 0 | if (WALK(mergeWhenClause->values)) |
4346 | 0 | return true; |
4347 | 0 | } |
4348 | 0 | break; |
4349 | 0 | case T_ReturningClause: |
4350 | 0 | { |
4351 | 0 | ReturningClause *returning = (ReturningClause *) node; |
4352 | |
|
4353 | 0 | if (WALK(returning->options)) |
4354 | 0 | return true; |
4355 | 0 | if (WALK(returning->exprs)) |
4356 | 0 | return true; |
4357 | 0 | } |
4358 | 0 | break; |
4359 | 0 | case T_SelectStmt: |
4360 | 0 | { |
4361 | 0 | SelectStmt *stmt = (SelectStmt *) node; |
4362 | |
|
4363 | 0 | if (WALK(stmt->distinctClause)) |
4364 | 0 | return true; |
4365 | 0 | if (WALK(stmt->intoClause)) |
4366 | 0 | return true; |
4367 | 0 | if (WALK(stmt->targetList)) |
4368 | 0 | return true; |
4369 | 0 | if (WALK(stmt->fromClause)) |
4370 | 0 | return true; |
4371 | 0 | if (WALK(stmt->whereClause)) |
4372 | 0 | return true; |
4373 | 0 | if (WALK(stmt->groupClause)) |
4374 | 0 | return true; |
4375 | 0 | if (WALK(stmt->havingClause)) |
4376 | 0 | return true; |
4377 | 0 | if (WALK(stmt->windowClause)) |
4378 | 0 | return true; |
4379 | 0 | if (WALK(stmt->valuesLists)) |
4380 | 0 | return true; |
4381 | 0 | if (WALK(stmt->sortClause)) |
4382 | 0 | return true; |
4383 | 0 | if (WALK(stmt->limitOffset)) |
4384 | 0 | return true; |
4385 | 0 | if (WALK(stmt->limitCount)) |
4386 | 0 | return true; |
4387 | 0 | if (WALK(stmt->lockingClause)) |
4388 | 0 | return true; |
4389 | 0 | if (WALK(stmt->withClause)) |
4390 | 0 | return true; |
4391 | 0 | if (WALK(stmt->larg)) |
4392 | 0 | return true; |
4393 | 0 | if (WALK(stmt->rarg)) |
4394 | 0 | return true; |
4395 | 0 | } |
4396 | 0 | break; |
4397 | 0 | case T_PLAssignStmt: |
4398 | 0 | { |
4399 | 0 | PLAssignStmt *stmt = (PLAssignStmt *) node; |
4400 | |
|
4401 | 0 | if (WALK(stmt->indirection)) |
4402 | 0 | return true; |
4403 | 0 | if (WALK(stmt->val)) |
4404 | 0 | return true; |
4405 | 0 | } |
4406 | 0 | break; |
4407 | 0 | case T_A_Expr: |
4408 | 0 | { |
4409 | 0 | A_Expr *expr = (A_Expr *) node; |
4410 | |
|
4411 | 0 | if (WALK(expr->lexpr)) |
4412 | 0 | return true; |
4413 | 0 | if (WALK(expr->rexpr)) |
4414 | 0 | return true; |
4415 | | /* operator name is deemed uninteresting */ |
4416 | 0 | } |
4417 | 0 | break; |
4418 | 0 | case T_BoolExpr: |
4419 | 0 | { |
4420 | 0 | BoolExpr *expr = (BoolExpr *) node; |
4421 | |
|
4422 | 0 | if (WALK(expr->args)) |
4423 | 0 | return true; |
4424 | 0 | } |
4425 | 0 | break; |
4426 | 0 | case T_ColumnRef: |
4427 | | /* we assume the fields contain nothing interesting */ |
4428 | 0 | break; |
4429 | 0 | case T_FuncCall: |
4430 | 0 | { |
4431 | 0 | FuncCall *fcall = (FuncCall *) node; |
4432 | |
|
4433 | 0 | if (WALK(fcall->args)) |
4434 | 0 | return true; |
4435 | 0 | if (WALK(fcall->agg_order)) |
4436 | 0 | return true; |
4437 | 0 | if (WALK(fcall->agg_filter)) |
4438 | 0 | return true; |
4439 | 0 | if (WALK(fcall->over)) |
4440 | 0 | return true; |
4441 | | /* function name is deemed uninteresting */ |
4442 | 0 | } |
4443 | 0 | break; |
4444 | 0 | case T_NamedArgExpr: |
4445 | 0 | return WALK(((NamedArgExpr *) node)->arg); |
4446 | 0 | case T_A_Indices: |
4447 | 0 | { |
4448 | 0 | A_Indices *indices = (A_Indices *) node; |
4449 | |
|
4450 | 0 | if (WALK(indices->lidx)) |
4451 | 0 | return true; |
4452 | 0 | if (WALK(indices->uidx)) |
4453 | 0 | return true; |
4454 | 0 | } |
4455 | 0 | break; |
4456 | 0 | case T_A_Indirection: |
4457 | 0 | { |
4458 | 0 | A_Indirection *indir = (A_Indirection *) node; |
4459 | |
|
4460 | 0 | if (WALK(indir->arg)) |
4461 | 0 | return true; |
4462 | 0 | if (WALK(indir->indirection)) |
4463 | 0 | return true; |
4464 | 0 | } |
4465 | 0 | break; |
4466 | 0 | case T_A_ArrayExpr: |
4467 | 0 | return WALK(((A_ArrayExpr *) node)->elements); |
4468 | 0 | case T_ResTarget: |
4469 | 0 | { |
4470 | 0 | ResTarget *rt = (ResTarget *) node; |
4471 | |
|
4472 | 0 | if (WALK(rt->indirection)) |
4473 | 0 | return true; |
4474 | 0 | if (WALK(rt->val)) |
4475 | 0 | return true; |
4476 | 0 | } |
4477 | 0 | break; |
4478 | 0 | case T_MultiAssignRef: |
4479 | 0 | return WALK(((MultiAssignRef *) node)->source); |
4480 | 0 | case T_TypeCast: |
4481 | 0 | { |
4482 | 0 | TypeCast *tc = (TypeCast *) node; |
4483 | |
|
4484 | 0 | if (WALK(tc->arg)) |
4485 | 0 | return true; |
4486 | 0 | if (WALK(tc->typeName)) |
4487 | 0 | return true; |
4488 | 0 | } |
4489 | 0 | break; |
4490 | 0 | case T_CollateClause: |
4491 | 0 | return WALK(((CollateClause *) node)->arg); |
4492 | 0 | case T_SortBy: |
4493 | 0 | return WALK(((SortBy *) node)->node); |
4494 | 0 | case T_WindowDef: |
4495 | 0 | { |
4496 | 0 | WindowDef *wd = (WindowDef *) node; |
4497 | |
|
4498 | 0 | if (WALK(wd->partitionClause)) |
4499 | 0 | return true; |
4500 | 0 | if (WALK(wd->orderClause)) |
4501 | 0 | return true; |
4502 | 0 | if (WALK(wd->startOffset)) |
4503 | 0 | return true; |
4504 | 0 | if (WALK(wd->endOffset)) |
4505 | 0 | return true; |
4506 | 0 | } |
4507 | 0 | break; |
4508 | 0 | case T_RangeSubselect: |
4509 | 0 | { |
4510 | 0 | RangeSubselect *rs = (RangeSubselect *) node; |
4511 | |
|
4512 | 0 | if (WALK(rs->subquery)) |
4513 | 0 | return true; |
4514 | 0 | if (WALK(rs->alias)) |
4515 | 0 | return true; |
4516 | 0 | } |
4517 | 0 | break; |
4518 | 0 | case T_RangeFunction: |
4519 | 0 | { |
4520 | 0 | RangeFunction *rf = (RangeFunction *) node; |
4521 | |
|
4522 | 0 | if (WALK(rf->functions)) |
4523 | 0 | return true; |
4524 | 0 | if (WALK(rf->alias)) |
4525 | 0 | return true; |
4526 | 0 | if (WALK(rf->coldeflist)) |
4527 | 0 | return true; |
4528 | 0 | } |
4529 | 0 | break; |
4530 | 0 | case T_RangeTableSample: |
4531 | 0 | { |
4532 | 0 | RangeTableSample *rts = (RangeTableSample *) node; |
4533 | |
|
4534 | 0 | if (WALK(rts->relation)) |
4535 | 0 | return true; |
4536 | | /* method name is deemed uninteresting */ |
4537 | 0 | if (WALK(rts->args)) |
4538 | 0 | return true; |
4539 | 0 | if (WALK(rts->repeatable)) |
4540 | 0 | return true; |
4541 | 0 | } |
4542 | 0 | break; |
4543 | 0 | case T_RangeTableFunc: |
4544 | 0 | { |
4545 | 0 | RangeTableFunc *rtf = (RangeTableFunc *) node; |
4546 | |
|
4547 | 0 | if (WALK(rtf->docexpr)) |
4548 | 0 | return true; |
4549 | 0 | if (WALK(rtf->rowexpr)) |
4550 | 0 | return true; |
4551 | 0 | if (WALK(rtf->namespaces)) |
4552 | 0 | return true; |
4553 | 0 | if (WALK(rtf->columns)) |
4554 | 0 | return true; |
4555 | 0 | if (WALK(rtf->alias)) |
4556 | 0 | return true; |
4557 | 0 | } |
4558 | 0 | break; |
4559 | 0 | case T_RangeTableFuncCol: |
4560 | 0 | { |
4561 | 0 | RangeTableFuncCol *rtfc = (RangeTableFuncCol *) node; |
4562 | |
|
4563 | 0 | if (WALK(rtfc->colexpr)) |
4564 | 0 | return true; |
4565 | 0 | if (WALK(rtfc->coldefexpr)) |
4566 | 0 | return true; |
4567 | 0 | } |
4568 | 0 | break; |
4569 | 0 | case T_TypeName: |
4570 | 0 | { |
4571 | 0 | TypeName *tn = (TypeName *) node; |
4572 | |
|
4573 | 0 | if (WALK(tn->typmods)) |
4574 | 0 | return true; |
4575 | 0 | if (WALK(tn->arrayBounds)) |
4576 | 0 | return true; |
4577 | | /* type name itself is deemed uninteresting */ |
4578 | 0 | } |
4579 | 0 | break; |
4580 | 0 | case T_ColumnDef: |
4581 | 0 | { |
4582 | 0 | ColumnDef *coldef = (ColumnDef *) node; |
4583 | |
|
4584 | 0 | if (WALK(coldef->typeName)) |
4585 | 0 | return true; |
4586 | 0 | if (WALK(coldef->raw_default)) |
4587 | 0 | return true; |
4588 | 0 | if (WALK(coldef->collClause)) |
4589 | 0 | return true; |
4590 | | /* for now, constraints are ignored */ |
4591 | 0 | } |
4592 | 0 | break; |
4593 | 0 | case T_IndexElem: |
4594 | 0 | { |
4595 | 0 | IndexElem *indelem = (IndexElem *) node; |
4596 | |
|
4597 | 0 | if (WALK(indelem->expr)) |
4598 | 0 | return true; |
4599 | | /* collation and opclass names are deemed uninteresting */ |
4600 | 0 | } |
4601 | 0 | break; |
4602 | 0 | case T_GroupingSet: |
4603 | 0 | return WALK(((GroupingSet *) node)->content); |
4604 | 0 | case T_LockingClause: |
4605 | 0 | return WALK(((LockingClause *) node)->lockedRels); |
4606 | 0 | case T_XmlSerialize: |
4607 | 0 | { |
4608 | 0 | XmlSerialize *xs = (XmlSerialize *) node; |
4609 | |
|
4610 | 0 | if (WALK(xs->expr)) |
4611 | 0 | return true; |
4612 | 0 | if (WALK(xs->typeName)) |
4613 | 0 | return true; |
4614 | 0 | } |
4615 | 0 | break; |
4616 | 0 | case T_WithClause: |
4617 | 0 | return WALK(((WithClause *) node)->ctes); |
4618 | 0 | case T_InferClause: |
4619 | 0 | { |
4620 | 0 | InferClause *stmt = (InferClause *) node; |
4621 | |
|
4622 | 0 | if (WALK(stmt->indexElems)) |
4623 | 0 | return true; |
4624 | 0 | if (WALK(stmt->whereClause)) |
4625 | 0 | return true; |
4626 | 0 | } |
4627 | 0 | break; |
4628 | 0 | case T_OnConflictClause: |
4629 | 0 | { |
4630 | 0 | OnConflictClause *stmt = (OnConflictClause *) node; |
4631 | |
|
4632 | 0 | if (WALK(stmt->infer)) |
4633 | 0 | return true; |
4634 | 0 | if (WALK(stmt->targetList)) |
4635 | 0 | return true; |
4636 | 0 | if (WALK(stmt->whereClause)) |
4637 | 0 | return true; |
4638 | 0 | } |
4639 | 0 | break; |
4640 | 0 | case T_CommonTableExpr: |
4641 | | /* search_clause and cycle_clause are not interesting here */ |
4642 | 0 | return WALK(((CommonTableExpr *) node)->ctequery); |
4643 | 0 | case T_JsonOutput: |
4644 | 0 | { |
4645 | 0 | JsonOutput *out = (JsonOutput *) node; |
4646 | |
|
4647 | 0 | if (WALK(out->typeName)) |
4648 | 0 | return true; |
4649 | 0 | if (WALK(out->returning)) |
4650 | 0 | return true; |
4651 | 0 | } |
4652 | 0 | break; |
4653 | 0 | case T_JsonKeyValue: |
4654 | 0 | { |
4655 | 0 | JsonKeyValue *jkv = (JsonKeyValue *) node; |
4656 | |
|
4657 | 0 | if (WALK(jkv->key)) |
4658 | 0 | return true; |
4659 | 0 | if (WALK(jkv->value)) |
4660 | 0 | return true; |
4661 | 0 | } |
4662 | 0 | break; |
4663 | 0 | case T_JsonObjectConstructor: |
4664 | 0 | { |
4665 | 0 | JsonObjectConstructor *joc = (JsonObjectConstructor *) node; |
4666 | |
|
4667 | 0 | if (WALK(joc->output)) |
4668 | 0 | return true; |
4669 | 0 | if (WALK(joc->exprs)) |
4670 | 0 | return true; |
4671 | 0 | } |
4672 | 0 | break; |
4673 | 0 | case T_JsonArrayConstructor: |
4674 | 0 | { |
4675 | 0 | JsonArrayConstructor *jac = (JsonArrayConstructor *) node; |
4676 | |
|
4677 | 0 | if (WALK(jac->output)) |
4678 | 0 | return true; |
4679 | 0 | if (WALK(jac->exprs)) |
4680 | 0 | return true; |
4681 | 0 | } |
4682 | 0 | break; |
4683 | 0 | case T_JsonAggConstructor: |
4684 | 0 | { |
4685 | 0 | JsonAggConstructor *ctor = (JsonAggConstructor *) node; |
4686 | |
|
4687 | 0 | if (WALK(ctor->output)) |
4688 | 0 | return true; |
4689 | 0 | if (WALK(ctor->agg_order)) |
4690 | 0 | return true; |
4691 | 0 | if (WALK(ctor->agg_filter)) |
4692 | 0 | return true; |
4693 | 0 | if (WALK(ctor->over)) |
4694 | 0 | return true; |
4695 | 0 | } |
4696 | 0 | break; |
4697 | 0 | case T_JsonObjectAgg: |
4698 | 0 | { |
4699 | 0 | JsonObjectAgg *joa = (JsonObjectAgg *) node; |
4700 | |
|
4701 | 0 | if (WALK(joa->constructor)) |
4702 | 0 | return true; |
4703 | 0 | if (WALK(joa->arg)) |
4704 | 0 | return true; |
4705 | 0 | } |
4706 | 0 | break; |
4707 | 0 | case T_JsonArrayAgg: |
4708 | 0 | { |
4709 | 0 | JsonArrayAgg *jaa = (JsonArrayAgg *) node; |
4710 | |
|
4711 | 0 | if (WALK(jaa->constructor)) |
4712 | 0 | return true; |
4713 | 0 | if (WALK(jaa->arg)) |
4714 | 0 | return true; |
4715 | 0 | } |
4716 | 0 | break; |
4717 | 0 | case T_JsonArrayQueryConstructor: |
4718 | 0 | { |
4719 | 0 | JsonArrayQueryConstructor *jaqc = (JsonArrayQueryConstructor *) node; |
4720 | |
|
4721 | 0 | if (WALK(jaqc->output)) |
4722 | 0 | return true; |
4723 | 0 | if (WALK(jaqc->query)) |
4724 | 0 | return true; |
4725 | 0 | } |
4726 | 0 | break; |
4727 | 0 | default: |
4728 | 0 | elog(ERROR, "unrecognized node type: %d", |
4729 | 0 | (int) nodeTag(node)); |
4730 | 0 | break; |
4731 | 0 | } |
4732 | 0 | return false; |
4733 | 0 | } |
4734 | | |
4735 | | /* |
4736 | | * planstate_tree_walker --- walk plan state trees |
4737 | | * |
4738 | | * The walker has already visited the current node, and so we need only |
4739 | | * recurse into any sub-nodes it has. |
4740 | | */ |
4741 | | pg_attribute_no_sanitize_function() |
4742 | | bool |
4743 | | planstate_tree_walker_impl(PlanState *planstate, |
4744 | | planstate_tree_walker_callback walker, |
4745 | | void *context) |
4746 | 0 | { |
4747 | 0 | Plan *plan = planstate->plan; |
4748 | 0 | ListCell *lc; |
4749 | | |
4750 | | /* We don't need implicit coercions to Node here */ |
4751 | 0 | #define PSWALK(n) walker(n, context) |
4752 | | |
4753 | | /* Guard against stack overflow due to overly complex plan trees */ |
4754 | 0 | check_stack_depth(); |
4755 | | |
4756 | | /* initPlan-s */ |
4757 | 0 | if (planstate_walk_subplans(planstate->initPlan, walker, context)) |
4758 | 0 | return true; |
4759 | | |
4760 | | /* lefttree */ |
4761 | 0 | if (outerPlanState(planstate)) |
4762 | 0 | { |
4763 | 0 | if (PSWALK(outerPlanState(planstate))) |
4764 | 0 | return true; |
4765 | 0 | } |
4766 | | |
4767 | | /* righttree */ |
4768 | 0 | if (innerPlanState(planstate)) |
4769 | 0 | { |
4770 | 0 | if (PSWALK(innerPlanState(planstate))) |
4771 | 0 | return true; |
4772 | 0 | } |
4773 | | |
4774 | | /* special child plans */ |
4775 | 0 | switch (nodeTag(plan)) |
4776 | 0 | { |
4777 | 0 | case T_Append: |
4778 | 0 | if (planstate_walk_members(((AppendState *) planstate)->appendplans, |
4779 | 0 | ((AppendState *) planstate)->as_nplans, |
4780 | 0 | walker, context)) |
4781 | 0 | return true; |
4782 | 0 | break; |
4783 | 0 | case T_MergeAppend: |
4784 | 0 | if (planstate_walk_members(((MergeAppendState *) planstate)->mergeplans, |
4785 | 0 | ((MergeAppendState *) planstate)->ms_nplans, |
4786 | 0 | walker, context)) |
4787 | 0 | return true; |
4788 | 0 | break; |
4789 | 0 | case T_BitmapAnd: |
4790 | 0 | if (planstate_walk_members(((BitmapAndState *) planstate)->bitmapplans, |
4791 | 0 | ((BitmapAndState *) planstate)->nplans, |
4792 | 0 | walker, context)) |
4793 | 0 | return true; |
4794 | 0 | break; |
4795 | 0 | case T_BitmapOr: |
4796 | 0 | if (planstate_walk_members(((BitmapOrState *) planstate)->bitmapplans, |
4797 | 0 | ((BitmapOrState *) planstate)->nplans, |
4798 | 0 | walker, context)) |
4799 | 0 | return true; |
4800 | 0 | break; |
4801 | 0 | case T_SubqueryScan: |
4802 | 0 | if (PSWALK(((SubqueryScanState *) planstate)->subplan)) |
4803 | 0 | return true; |
4804 | 0 | break; |
4805 | 0 | case T_CustomScan: |
4806 | 0 | foreach(lc, ((CustomScanState *) planstate)->custom_ps) |
4807 | 0 | { |
4808 | 0 | if (PSWALK(lfirst(lc))) |
4809 | 0 | return true; |
4810 | 0 | } |
4811 | 0 | break; |
4812 | 0 | default: |
4813 | 0 | break; |
4814 | 0 | } |
4815 | | |
4816 | | /* subPlan-s */ |
4817 | 0 | if (planstate_walk_subplans(planstate->subPlan, walker, context)) |
4818 | 0 | return true; |
4819 | | |
4820 | 0 | return false; |
4821 | 0 | } |
4822 | | |
4823 | | /* |
4824 | | * Walk a list of SubPlans (or initPlans, which also use SubPlan nodes). |
4825 | | */ |
4826 | | pg_attribute_no_sanitize_function() |
4827 | | static bool |
4828 | | planstate_walk_subplans(List *plans, |
4829 | | planstate_tree_walker_callback walker, |
4830 | | void *context) |
4831 | 0 | { |
4832 | 0 | ListCell *lc; |
4833 | |
|
4834 | 0 | foreach(lc, plans) |
4835 | 0 | { |
4836 | 0 | SubPlanState *sps = lfirst_node(SubPlanState, lc); |
4837 | |
|
4838 | 0 | if (PSWALK(sps->planstate)) |
4839 | 0 | return true; |
4840 | 0 | } |
4841 | | |
4842 | 0 | return false; |
4843 | 0 | } |
4844 | | |
4845 | | /* |
4846 | | * Walk the constituent plans of a ModifyTable, Append, MergeAppend, |
4847 | | * BitmapAnd, or BitmapOr node. |
4848 | | */ |
4849 | | pg_attribute_no_sanitize_function() |
4850 | | static bool |
4851 | | planstate_walk_members(PlanState **planstates, int nplans, |
4852 | | planstate_tree_walker_callback walker, |
4853 | | void *context) |
4854 | 0 | { |
4855 | 0 | for (int j = 0; j < nplans; j++) |
4856 | 0 | { |
4857 | 0 | if (PSWALK(planstates[j])) |
4858 | 0 | return true; |
4859 | 0 | } |
4860 | | |
4861 | 0 | return false; |
4862 | 0 | } |