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