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