/src/postgres/src/backend/nodes/makefuncs.c
Line | Count | Source |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * makefuncs.c |
4 | | * creator functions for various nodes. The functions here are for the |
5 | | * most frequently created nodes. |
6 | | * |
7 | | * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group |
8 | | * Portions Copyright (c) 1994, Regents of the University of California |
9 | | * |
10 | | * |
11 | | * IDENTIFICATION |
12 | | * src/backend/nodes/makefuncs.c |
13 | | * |
14 | | *------------------------------------------------------------------------- |
15 | | */ |
16 | | #include "postgres.h" |
17 | | |
18 | | #include "catalog/pg_class.h" |
19 | | #include "catalog/pg_type.h" |
20 | | #include "nodes/makefuncs.h" |
21 | | #include "nodes/nodeFuncs.h" |
22 | | #include "utils/lsyscache.h" |
23 | | |
24 | | |
25 | | /* |
26 | | * makeA_Expr - |
27 | | * makes an A_Expr node |
28 | | */ |
29 | | A_Expr * |
30 | | makeA_Expr(A_Expr_Kind kind, List *name, |
31 | | Node *lexpr, Node *rexpr, int location) |
32 | 12.1k | { |
33 | 12.1k | A_Expr *a = makeNode(A_Expr); |
34 | | |
35 | 12.1k | a->kind = kind; |
36 | 12.1k | a->name = name; |
37 | 12.1k | a->lexpr = lexpr; |
38 | 12.1k | a->rexpr = rexpr; |
39 | 12.1k | a->location = location; |
40 | 12.1k | return a; |
41 | 12.1k | } |
42 | | |
43 | | /* |
44 | | * makeSimpleA_Expr - |
45 | | * As above, given a simple (unqualified) operator name |
46 | | */ |
47 | | A_Expr * |
48 | | makeSimpleA_Expr(A_Expr_Kind kind, char *name, |
49 | | Node *lexpr, Node *rexpr, int location) |
50 | 146k | { |
51 | 146k | A_Expr *a = makeNode(A_Expr); |
52 | | |
53 | 146k | a->kind = kind; |
54 | 146k | a->name = list_make1(makeString(name)); |
55 | 146k | a->lexpr = lexpr; |
56 | 146k | a->rexpr = rexpr; |
57 | 146k | a->location = location; |
58 | 146k | return a; |
59 | 146k | } |
60 | | |
61 | | /* |
62 | | * makeVar - |
63 | | * creates a Var node |
64 | | */ |
65 | | Var * |
66 | | makeVar(int varno, |
67 | | AttrNumber varattno, |
68 | | Oid vartype, |
69 | | int32 vartypmod, |
70 | | Oid varcollid, |
71 | | Index varlevelsup) |
72 | 0 | { |
73 | 0 | Var *var = makeNode(Var); |
74 | |
|
75 | 0 | var->varno = varno; |
76 | 0 | var->varattno = varattno; |
77 | 0 | var->vartype = vartype; |
78 | 0 | var->vartypmod = vartypmod; |
79 | 0 | var->varcollid = varcollid; |
80 | 0 | var->varlevelsup = varlevelsup; |
81 | | |
82 | | /* |
83 | | * Only a few callers need to make Var nodes with varreturningtype |
84 | | * different from VAR_RETURNING_DEFAULT, non-null varnullingrels, or with |
85 | | * varnosyn/varattnosyn different from varno/varattno. We don't provide |
86 | | * separate arguments for them, but just initialize them to sensible |
87 | | * default values. This reduces code clutter and chance of error for most |
88 | | * callers. |
89 | | */ |
90 | 0 | var->varreturningtype = VAR_RETURNING_DEFAULT; |
91 | 0 | var->varnullingrels = NULL; |
92 | 0 | var->varnosyn = (Index) varno; |
93 | 0 | var->varattnosyn = varattno; |
94 | | |
95 | | /* Likewise, we just set location to "unknown" here */ |
96 | 0 | var->location = -1; |
97 | |
|
98 | 0 | return var; |
99 | 0 | } |
100 | | |
101 | | /* |
102 | | * makeVarFromTargetEntry - |
103 | | * convenience function to create a same-level Var node from a |
104 | | * TargetEntry |
105 | | */ |
106 | | Var * |
107 | | makeVarFromTargetEntry(int varno, |
108 | | TargetEntry *tle) |
109 | 0 | { |
110 | 0 | return makeVar(varno, |
111 | 0 | tle->resno, |
112 | 0 | exprType((Node *) tle->expr), |
113 | 0 | exprTypmod((Node *) tle->expr), |
114 | 0 | exprCollation((Node *) tle->expr), |
115 | 0 | 0); |
116 | 0 | } |
117 | | |
118 | | /* |
119 | | * makeWholeRowVar - |
120 | | * creates a Var node representing a whole row of the specified RTE |
121 | | * |
122 | | * A whole-row reference is a Var with varno set to the correct range |
123 | | * table entry, and varattno == 0 to signal that it references the whole |
124 | | * tuple. (Use of zero here is unclean, since it could easily be confused |
125 | | * with error cases, but it's not worth changing now.) The vartype indicates |
126 | | * a rowtype; either a named composite type, or a domain over a named |
127 | | * composite type (only possible if the RTE is a function returning that), |
128 | | * or RECORD. This function encapsulates the logic for determining the |
129 | | * correct rowtype OID to use. |
130 | | * |
131 | | * If allowScalar is true, then for the case where the RTE is a single function |
132 | | * returning a non-composite result type, we produce a normal Var referencing |
133 | | * the function's result directly, instead of the single-column composite |
134 | | * value that the whole-row notation might otherwise suggest. |
135 | | */ |
136 | | Var * |
137 | | makeWholeRowVar(RangeTblEntry *rte, |
138 | | int varno, |
139 | | Index varlevelsup, |
140 | | bool allowScalar) |
141 | 0 | { |
142 | 0 | Var *result; |
143 | 0 | Oid toid; |
144 | 0 | Node *fexpr; |
145 | |
|
146 | 0 | switch (rte->rtekind) |
147 | 0 | { |
148 | 0 | case RTE_RELATION: |
149 | | /* relation: the rowtype is a named composite type */ |
150 | 0 | toid = get_rel_type_id(rte->relid); |
151 | 0 | if (!OidIsValid(toid)) |
152 | 0 | ereport(ERROR, |
153 | 0 | (errcode(ERRCODE_WRONG_OBJECT_TYPE), |
154 | 0 | errmsg("relation \"%s\" does not have a composite type", |
155 | 0 | get_rel_name(rte->relid)))); |
156 | 0 | result = makeVar(varno, |
157 | 0 | InvalidAttrNumber, |
158 | 0 | toid, |
159 | 0 | -1, |
160 | 0 | InvalidOid, |
161 | 0 | varlevelsup); |
162 | 0 | break; |
163 | | |
164 | 0 | case RTE_SUBQUERY: |
165 | | |
166 | | /* |
167 | | * For a standard subquery, the Var should be of RECORD type. |
168 | | * However, if we're looking at a subquery that was expanded from |
169 | | * a view or SRF (only possible during planning), we must use the |
170 | | * appropriate rowtype, so that the resulting Var has the same |
171 | | * type that we would have produced from the original RTE. |
172 | | */ |
173 | 0 | if (OidIsValid(rte->relid)) |
174 | 0 | { |
175 | | /* Subquery was expanded from a view */ |
176 | 0 | toid = get_rel_type_id(rte->relid); |
177 | 0 | if (!OidIsValid(toid)) |
178 | 0 | ereport(ERROR, |
179 | 0 | (errcode(ERRCODE_WRONG_OBJECT_TYPE), |
180 | 0 | errmsg("relation \"%s\" does not have a composite type", |
181 | 0 | get_rel_name(rte->relid)))); |
182 | 0 | } |
183 | 0 | else if (rte->functions) |
184 | 0 | { |
185 | | /* |
186 | | * Subquery was expanded from a set-returning function. That |
187 | | * would not have happened if there's more than one function |
188 | | * or ordinality was requested. We also needn't worry about |
189 | | * the allowScalar case, since the planner doesn't use that. |
190 | | * Otherwise this must match the RTE_FUNCTION code below. |
191 | | */ |
192 | 0 | Assert(!allowScalar); |
193 | 0 | fexpr = ((RangeTblFunction *) linitial(rte->functions))->funcexpr; |
194 | 0 | toid = exprType(fexpr); |
195 | 0 | if (!type_is_rowtype(toid)) |
196 | 0 | toid = RECORDOID; |
197 | 0 | } |
198 | 0 | else |
199 | 0 | { |
200 | | /* Normal subquery-in-FROM */ |
201 | 0 | toid = RECORDOID; |
202 | 0 | } |
203 | 0 | result = makeVar(varno, |
204 | 0 | InvalidAttrNumber, |
205 | 0 | toid, |
206 | 0 | -1, |
207 | 0 | InvalidOid, |
208 | 0 | varlevelsup); |
209 | 0 | break; |
210 | | |
211 | 0 | case RTE_FUNCTION: |
212 | | |
213 | | /* |
214 | | * If there's more than one function, or ordinality is requested, |
215 | | * force a RECORD result, since there's certainly more than one |
216 | | * column involved and it can't be a known named type. |
217 | | */ |
218 | 0 | if (rte->funcordinality || list_length(rte->functions) != 1) |
219 | 0 | { |
220 | | /* always produces an anonymous RECORD result */ |
221 | 0 | result = makeVar(varno, |
222 | 0 | InvalidAttrNumber, |
223 | 0 | RECORDOID, |
224 | 0 | -1, |
225 | 0 | InvalidOid, |
226 | 0 | varlevelsup); |
227 | 0 | break; |
228 | 0 | } |
229 | | |
230 | 0 | fexpr = ((RangeTblFunction *) linitial(rte->functions))->funcexpr; |
231 | 0 | toid = exprType(fexpr); |
232 | 0 | if (type_is_rowtype(toid)) |
233 | 0 | { |
234 | | /* func returns composite; same as relation case */ |
235 | 0 | result = makeVar(varno, |
236 | 0 | InvalidAttrNumber, |
237 | 0 | toid, |
238 | 0 | -1, |
239 | 0 | InvalidOid, |
240 | 0 | varlevelsup); |
241 | 0 | } |
242 | 0 | else if (allowScalar) |
243 | 0 | { |
244 | | /* func returns scalar; just return its output as-is */ |
245 | 0 | result = makeVar(varno, |
246 | 0 | 1, |
247 | 0 | toid, |
248 | 0 | -1, |
249 | 0 | exprCollation(fexpr), |
250 | 0 | varlevelsup); |
251 | 0 | } |
252 | 0 | else |
253 | 0 | { |
254 | | /* func returns scalar, but we want a composite result */ |
255 | 0 | result = makeVar(varno, |
256 | 0 | InvalidAttrNumber, |
257 | 0 | RECORDOID, |
258 | 0 | -1, |
259 | 0 | InvalidOid, |
260 | 0 | varlevelsup); |
261 | 0 | } |
262 | 0 | break; |
263 | | |
264 | 0 | default: |
265 | | |
266 | | /* |
267 | | * RTE is a join, tablefunc, VALUES, CTE, etc. We represent these |
268 | | * cases as a whole-row Var of RECORD type. (Note that in most |
269 | | * cases the Var will be expanded to a RowExpr during planning, |
270 | | * but that is not our concern here.) |
271 | | */ |
272 | 0 | result = makeVar(varno, |
273 | 0 | InvalidAttrNumber, |
274 | 0 | RECORDOID, |
275 | 0 | -1, |
276 | 0 | InvalidOid, |
277 | 0 | varlevelsup); |
278 | 0 | break; |
279 | 0 | } |
280 | | |
281 | 0 | return result; |
282 | 0 | } |
283 | | |
284 | | /* |
285 | | * makeTargetEntry - |
286 | | * creates a TargetEntry node |
287 | | */ |
288 | | TargetEntry * |
289 | | makeTargetEntry(Expr *expr, |
290 | | AttrNumber resno, |
291 | | char *resname, |
292 | | bool resjunk) |
293 | 0 | { |
294 | 0 | TargetEntry *tle = makeNode(TargetEntry); |
295 | |
|
296 | 0 | tle->expr = expr; |
297 | 0 | tle->resno = resno; |
298 | 0 | tle->resname = resname; |
299 | | |
300 | | /* |
301 | | * We always set these fields to 0. If the caller wants to change them he |
302 | | * must do so explicitly. Few callers do that, so omitting these |
303 | | * arguments reduces the chance of error. |
304 | | */ |
305 | 0 | tle->ressortgroupref = 0; |
306 | 0 | tle->resorigtbl = InvalidOid; |
307 | 0 | tle->resorigcol = 0; |
308 | |
|
309 | 0 | tle->resjunk = resjunk; |
310 | |
|
311 | 0 | return tle; |
312 | 0 | } |
313 | | |
314 | | /* |
315 | | * flatCopyTargetEntry - |
316 | | * duplicate a TargetEntry, but don't copy substructure |
317 | | * |
318 | | * This is commonly used when we just want to modify the resno or substitute |
319 | | * a new expression. |
320 | | */ |
321 | | TargetEntry * |
322 | | flatCopyTargetEntry(TargetEntry *src_tle) |
323 | 0 | { |
324 | 0 | TargetEntry *tle = makeNode(TargetEntry); |
325 | |
|
326 | 0 | Assert(IsA(src_tle, TargetEntry)); |
327 | 0 | memcpy(tle, src_tle, sizeof(TargetEntry)); |
328 | 0 | return tle; |
329 | 0 | } |
330 | | |
331 | | /* |
332 | | * makeFromExpr - |
333 | | * creates a FromExpr node |
334 | | */ |
335 | | FromExpr * |
336 | | makeFromExpr(List *fromlist, Node *quals) |
337 | 0 | { |
338 | 0 | FromExpr *f = makeNode(FromExpr); |
339 | |
|
340 | 0 | f->fromlist = fromlist; |
341 | 0 | f->quals = quals; |
342 | 0 | return f; |
343 | 0 | } |
344 | | |
345 | | /* |
346 | | * makeConst - |
347 | | * creates a Const node |
348 | | */ |
349 | | Const * |
350 | | makeConst(Oid consttype, |
351 | | int32 consttypmod, |
352 | | Oid constcollid, |
353 | | int constlen, |
354 | | Datum constvalue, |
355 | | bool constisnull, |
356 | | bool constbyval) |
357 | 0 | { |
358 | 0 | Const *cnst = makeNode(Const); |
359 | | |
360 | | /* |
361 | | * If it's a varlena value, force it to be in non-expanded (non-toasted) |
362 | | * format; this avoids any possible dependency on external values and |
363 | | * improves consistency of representation, which is important for equal(). |
364 | | */ |
365 | 0 | if (!constisnull && constlen == -1) |
366 | 0 | constvalue = PointerGetDatum(PG_DETOAST_DATUM(constvalue)); |
367 | |
|
368 | 0 | cnst->consttype = consttype; |
369 | 0 | cnst->consttypmod = consttypmod; |
370 | 0 | cnst->constcollid = constcollid; |
371 | 0 | cnst->constlen = constlen; |
372 | 0 | cnst->constvalue = constvalue; |
373 | 0 | cnst->constisnull = constisnull; |
374 | 0 | cnst->constbyval = constbyval; |
375 | 0 | cnst->location = -1; /* "unknown" */ |
376 | |
|
377 | 0 | return cnst; |
378 | 0 | } |
379 | | |
380 | | /* |
381 | | * makeNullConst - |
382 | | * creates a Const node representing a NULL of the specified type/typmod |
383 | | * |
384 | | * This is a convenience routine that just saves a lookup of the type's |
385 | | * storage properties. |
386 | | */ |
387 | | Const * |
388 | | makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid) |
389 | 0 | { |
390 | 0 | int16 typLen; |
391 | 0 | bool typByVal; |
392 | |
|
393 | 0 | get_typlenbyval(consttype, &typLen, &typByVal); |
394 | 0 | return makeConst(consttype, |
395 | 0 | consttypmod, |
396 | 0 | constcollid, |
397 | 0 | (int) typLen, |
398 | 0 | (Datum) 0, |
399 | 0 | true, |
400 | 0 | typByVal); |
401 | 0 | } |
402 | | |
403 | | /* |
404 | | * makeBoolConst - |
405 | | * creates a Const node representing a boolean value (can be NULL too) |
406 | | */ |
407 | | Node * |
408 | | makeBoolConst(bool value, bool isnull) |
409 | 0 | { |
410 | | /* note that pg_type.h hardwires size of bool as 1 ... duplicate it */ |
411 | 0 | return (Node *) makeConst(BOOLOID, -1, InvalidOid, 1, |
412 | 0 | BoolGetDatum(value), isnull, true); |
413 | 0 | } |
414 | | |
415 | | /* |
416 | | * makeBoolExpr - |
417 | | * creates a BoolExpr node |
418 | | */ |
419 | | Expr * |
420 | | makeBoolExpr(BoolExprType boolop, List *args, int location) |
421 | 2.19k | { |
422 | 2.19k | BoolExpr *b = makeNode(BoolExpr); |
423 | | |
424 | 2.19k | b->boolop = boolop; |
425 | 2.19k | b->args = args; |
426 | 2.19k | b->location = location; |
427 | | |
428 | 2.19k | return (Expr *) b; |
429 | 2.19k | } |
430 | | |
431 | | /* |
432 | | * makeAlias - |
433 | | * creates an Alias node |
434 | | * |
435 | | * NOTE: the given name is copied, but the colnames list (if any) isn't. |
436 | | */ |
437 | | Alias * |
438 | | makeAlias(const char *aliasname, List *colnames) |
439 | 0 | { |
440 | 0 | Alias *a = makeNode(Alias); |
441 | |
|
442 | 0 | a->aliasname = pstrdup(aliasname); |
443 | 0 | a->colnames = colnames; |
444 | |
|
445 | 0 | return a; |
446 | 0 | } |
447 | | |
448 | | /* |
449 | | * makeRelabelType - |
450 | | * creates a RelabelType node |
451 | | */ |
452 | | RelabelType * |
453 | | makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, Oid rcollid, |
454 | | CoercionForm rformat) |
455 | 0 | { |
456 | 0 | RelabelType *r = makeNode(RelabelType); |
457 | |
|
458 | 0 | r->arg = arg; |
459 | 0 | r->resulttype = rtype; |
460 | 0 | r->resulttypmod = rtypmod; |
461 | 0 | r->resultcollid = rcollid; |
462 | 0 | r->relabelformat = rformat; |
463 | 0 | r->location = -1; |
464 | |
|
465 | 0 | return r; |
466 | 0 | } |
467 | | |
468 | | /* |
469 | | * makeRangeVar - |
470 | | * creates a RangeVar node (rather oversimplified case) |
471 | | */ |
472 | | RangeVar * |
473 | | makeRangeVar(char *schemaname, char *relname, int location) |
474 | 0 | { |
475 | 0 | RangeVar *r = makeNode(RangeVar); |
476 | |
|
477 | 0 | r->catalogname = NULL; |
478 | 0 | r->schemaname = schemaname; |
479 | 0 | r->relname = relname; |
480 | 0 | r->inh = true; |
481 | 0 | r->relpersistence = RELPERSISTENCE_PERMANENT; |
482 | 0 | r->alias = NULL; |
483 | 0 | r->location = location; |
484 | |
|
485 | 0 | return r; |
486 | 0 | } |
487 | | |
488 | | /* |
489 | | * makeNotNullConstraint - |
490 | | * creates a Constraint node for NOT NULL constraints |
491 | | */ |
492 | | Constraint * |
493 | | makeNotNullConstraint(String *colname) |
494 | 0 | { |
495 | 0 | Constraint *notnull; |
496 | |
|
497 | 0 | notnull = makeNode(Constraint); |
498 | 0 | notnull->contype = CONSTR_NOTNULL; |
499 | 0 | notnull->conname = NULL; |
500 | 0 | notnull->is_no_inherit = false; |
501 | 0 | notnull->deferrable = false; |
502 | 0 | notnull->initdeferred = false; |
503 | 0 | notnull->location = -1; |
504 | 0 | notnull->keys = list_make1(colname); |
505 | 0 | notnull->is_enforced = true; |
506 | 0 | notnull->skip_validation = false; |
507 | 0 | notnull->initially_valid = true; |
508 | |
|
509 | 0 | return notnull; |
510 | 0 | } |
511 | | |
512 | | /* |
513 | | * makeTypeName - |
514 | | * build a TypeName node for an unqualified name. |
515 | | * |
516 | | * typmod is defaulted, but can be changed later by caller. |
517 | | */ |
518 | | TypeName * |
519 | | makeTypeName(char *typnam) |
520 | 2.48k | { |
521 | 2.48k | return makeTypeNameFromNameList(list_make1(makeString(typnam))); |
522 | 2.48k | } |
523 | | |
524 | | /* |
525 | | * makeTypeNameFromNameList - |
526 | | * build a TypeName node for a String list representing a qualified name. |
527 | | * |
528 | | * typmod is defaulted, but can be changed later by caller. |
529 | | */ |
530 | | TypeName * |
531 | | makeTypeNameFromNameList(List *names) |
532 | 7.72k | { |
533 | 7.72k | TypeName *n = makeNode(TypeName); |
534 | | |
535 | 7.72k | n->names = names; |
536 | 7.72k | n->typmods = NIL; |
537 | 7.72k | n->typemod = -1; |
538 | 7.72k | n->location = -1; |
539 | 7.72k | return n; |
540 | 7.72k | } |
541 | | |
542 | | /* |
543 | | * makeTypeNameFromOid - |
544 | | * build a TypeName node to represent a type already known by OID/typmod. |
545 | | */ |
546 | | TypeName * |
547 | | makeTypeNameFromOid(Oid typeOid, int32 typmod) |
548 | 0 | { |
549 | 0 | TypeName *n = makeNode(TypeName); |
550 | |
|
551 | 0 | n->typeOid = typeOid; |
552 | 0 | n->typemod = typmod; |
553 | 0 | n->location = -1; |
554 | 0 | return n; |
555 | 0 | } |
556 | | |
557 | | /* |
558 | | * makeColumnDef - |
559 | | * build a ColumnDef node to represent a simple column definition. |
560 | | * |
561 | | * Type and collation are specified by OID. |
562 | | * Other properties are all basic to start with. |
563 | | */ |
564 | | ColumnDef * |
565 | | makeColumnDef(const char *colname, Oid typeOid, int32 typmod, Oid collOid) |
566 | 0 | { |
567 | 0 | ColumnDef *n = makeNode(ColumnDef); |
568 | |
|
569 | 0 | n->colname = pstrdup(colname); |
570 | 0 | n->typeName = makeTypeNameFromOid(typeOid, typmod); |
571 | 0 | n->inhcount = 0; |
572 | 0 | n->is_local = true; |
573 | 0 | n->is_not_null = false; |
574 | 0 | n->is_from_type = false; |
575 | 0 | n->storage = 0; |
576 | 0 | n->raw_default = NULL; |
577 | 0 | n->cooked_default = NULL; |
578 | 0 | n->collClause = NULL; |
579 | 0 | n->collOid = collOid; |
580 | 0 | n->constraints = NIL; |
581 | 0 | n->fdwoptions = NIL; |
582 | 0 | n->location = -1; |
583 | |
|
584 | 0 | return n; |
585 | 0 | } |
586 | | |
587 | | /* |
588 | | * makeFuncExpr - |
589 | | * build an expression tree representing a function call. |
590 | | * |
591 | | * The argument expressions must have been transformed already. |
592 | | */ |
593 | | FuncExpr * |
594 | | makeFuncExpr(Oid funcid, Oid rettype, List *args, |
595 | | Oid funccollid, Oid inputcollid, CoercionForm fformat) |
596 | 0 | { |
597 | 0 | FuncExpr *funcexpr; |
598 | |
|
599 | 0 | funcexpr = makeNode(FuncExpr); |
600 | 0 | funcexpr->funcid = funcid; |
601 | 0 | funcexpr->funcresulttype = rettype; |
602 | 0 | funcexpr->funcretset = false; /* only allowed case here */ |
603 | 0 | funcexpr->funcvariadic = false; /* only allowed case here */ |
604 | 0 | funcexpr->funcformat = fformat; |
605 | 0 | funcexpr->funccollid = funccollid; |
606 | 0 | funcexpr->inputcollid = inputcollid; |
607 | 0 | funcexpr->args = args; |
608 | 0 | funcexpr->location = -1; |
609 | |
|
610 | 0 | return funcexpr; |
611 | 0 | } |
612 | | |
613 | | /* |
614 | | * makeStringConst - |
615 | | * build a A_Const node of type T_String for given string |
616 | | */ |
617 | | Node * |
618 | | makeStringConst(char *str, int location) |
619 | 5.89k | { |
620 | 5.89k | A_Const *n = makeNode(A_Const); |
621 | | |
622 | 5.89k | n->val.sval.type = T_String; |
623 | 5.89k | n->val.sval.sval = str; |
624 | 5.89k | n->location = location; |
625 | | |
626 | 5.89k | return (Node *) n; |
627 | 5.89k | } |
628 | | |
629 | | /* |
630 | | * makeDefElem - |
631 | | * build a DefElem node |
632 | | * |
633 | | * This is sufficient for the "typical" case with an unqualified option name |
634 | | * and no special action. |
635 | | */ |
636 | | DefElem * |
637 | | makeDefElem(char *name, Node *arg, int location) |
638 | 0 | { |
639 | 0 | DefElem *res = makeNode(DefElem); |
640 | |
|
641 | 0 | res->defnamespace = NULL; |
642 | 0 | res->defname = name; |
643 | 0 | res->arg = arg; |
644 | 0 | res->defaction = DEFELEM_UNSPEC; |
645 | 0 | res->location = location; |
646 | |
|
647 | 0 | return res; |
648 | 0 | } |
649 | | |
650 | | /* |
651 | | * makeDefElemExtended - |
652 | | * build a DefElem node with all fields available to be specified |
653 | | */ |
654 | | DefElem * |
655 | | makeDefElemExtended(char *nameSpace, char *name, Node *arg, |
656 | | DefElemAction defaction, int location) |
657 | 0 | { |
658 | 0 | DefElem *res = makeNode(DefElem); |
659 | |
|
660 | 0 | res->defnamespace = nameSpace; |
661 | 0 | res->defname = name; |
662 | 0 | res->arg = arg; |
663 | 0 | res->defaction = defaction; |
664 | 0 | res->location = location; |
665 | |
|
666 | 0 | return res; |
667 | 0 | } |
668 | | |
669 | | /* |
670 | | * makeFuncCall - |
671 | | * |
672 | | * Initialize a FuncCall struct with the information every caller must |
673 | | * supply. Any non-default parameters have to be inserted by the caller. |
674 | | */ |
675 | | FuncCall * |
676 | | makeFuncCall(List *name, List *args, CoercionForm funcformat, int location) |
677 | 3.68k | { |
678 | 3.68k | FuncCall *n = makeNode(FuncCall); |
679 | | |
680 | 3.68k | n->funcname = name; |
681 | 3.68k | n->args = args; |
682 | 3.68k | n->agg_order = NIL; |
683 | 3.68k | n->agg_filter = NULL; |
684 | 3.68k | n->over = NULL; |
685 | 3.68k | n->agg_within_group = false; |
686 | 3.68k | n->agg_star = false; |
687 | 3.68k | n->agg_distinct = false; |
688 | 3.68k | n->func_variadic = false; |
689 | 3.68k | n->funcformat = funcformat; |
690 | 3.68k | n->location = location; |
691 | 3.68k | return n; |
692 | 3.68k | } |
693 | | |
694 | | /* |
695 | | * make_opclause |
696 | | * Creates an operator clause given its operator info, left operand |
697 | | * and right operand (pass NULL to create single-operand clause), |
698 | | * and collation info. |
699 | | */ |
700 | | Expr * |
701 | | make_opclause(Oid opno, Oid opresulttype, bool opretset, |
702 | | Expr *leftop, Expr *rightop, |
703 | | Oid opcollid, Oid inputcollid) |
704 | 0 | { |
705 | 0 | OpExpr *expr = makeNode(OpExpr); |
706 | |
|
707 | 0 | expr->opno = opno; |
708 | 0 | expr->opfuncid = InvalidOid; |
709 | 0 | expr->opresulttype = opresulttype; |
710 | 0 | expr->opretset = opretset; |
711 | 0 | expr->opcollid = opcollid; |
712 | 0 | expr->inputcollid = inputcollid; |
713 | 0 | if (rightop) |
714 | 0 | expr->args = list_make2(leftop, rightop); |
715 | 0 | else |
716 | 0 | expr->args = list_make1(leftop); |
717 | 0 | expr->location = -1; |
718 | 0 | return (Expr *) expr; |
719 | 0 | } |
720 | | |
721 | | /* |
722 | | * make_andclause |
723 | | * |
724 | | * Creates an 'and' clause given a list of its subclauses. |
725 | | */ |
726 | | Expr * |
727 | | make_andclause(List *andclauses) |
728 | 0 | { |
729 | 0 | BoolExpr *expr = makeNode(BoolExpr); |
730 | |
|
731 | 0 | expr->boolop = AND_EXPR; |
732 | 0 | expr->args = andclauses; |
733 | 0 | expr->location = -1; |
734 | 0 | return (Expr *) expr; |
735 | 0 | } |
736 | | |
737 | | /* |
738 | | * make_orclause |
739 | | * |
740 | | * Creates an 'or' clause given a list of its subclauses. |
741 | | */ |
742 | | Expr * |
743 | | make_orclause(List *orclauses) |
744 | 0 | { |
745 | 0 | BoolExpr *expr = makeNode(BoolExpr); |
746 | |
|
747 | 0 | expr->boolop = OR_EXPR; |
748 | 0 | expr->args = orclauses; |
749 | 0 | expr->location = -1; |
750 | 0 | return (Expr *) expr; |
751 | 0 | } |
752 | | |
753 | | /* |
754 | | * make_notclause |
755 | | * |
756 | | * Create a 'not' clause given the expression to be negated. |
757 | | */ |
758 | | Expr * |
759 | | make_notclause(Expr *notclause) |
760 | 0 | { |
761 | 0 | BoolExpr *expr = makeNode(BoolExpr); |
762 | |
|
763 | 0 | expr->boolop = NOT_EXPR; |
764 | 0 | expr->args = list_make1(notclause); |
765 | 0 | expr->location = -1; |
766 | 0 | return (Expr *) expr; |
767 | 0 | } |
768 | | |
769 | | /* |
770 | | * make_and_qual |
771 | | * |
772 | | * Variant of make_andclause for ANDing two qual conditions together. |
773 | | * Qual conditions have the property that a NULL nodetree is interpreted |
774 | | * as 'true'. |
775 | | * |
776 | | * NB: this makes no attempt to preserve AND/OR flatness; so it should not |
777 | | * be used on a qual that has already been run through prepqual.c. |
778 | | */ |
779 | | Node * |
780 | | make_and_qual(Node *qual1, Node *qual2) |
781 | 0 | { |
782 | 0 | if (qual1 == NULL) |
783 | 0 | return qual2; |
784 | 0 | if (qual2 == NULL) |
785 | 0 | return qual1; |
786 | 0 | return (Node *) make_andclause(list_make2(qual1, qual2)); |
787 | 0 | } |
788 | | |
789 | | /* |
790 | | * The planner and executor usually represent qualification expressions |
791 | | * as lists of boolean expressions with implicit AND semantics. |
792 | | * |
793 | | * These functions convert between an AND-semantics expression list and the |
794 | | * ordinary representation of a boolean expression. |
795 | | * |
796 | | * Note that an empty list is considered equivalent to TRUE. |
797 | | */ |
798 | | Expr * |
799 | | make_ands_explicit(List *andclauses) |
800 | 0 | { |
801 | 0 | if (andclauses == NIL) |
802 | 0 | return (Expr *) makeBoolConst(true, false); |
803 | 0 | else if (list_length(andclauses) == 1) |
804 | 0 | return (Expr *) linitial(andclauses); |
805 | 0 | else |
806 | 0 | return make_andclause(andclauses); |
807 | 0 | } |
808 | | |
809 | | List * |
810 | | make_ands_implicit(Expr *clause) |
811 | 0 | { |
812 | | /* |
813 | | * NB: because the parser sets the qual field to NULL in a query that has |
814 | | * no WHERE clause, we must consider a NULL input clause as TRUE, even |
815 | | * though one might more reasonably think it FALSE. |
816 | | */ |
817 | 0 | if (clause == NULL) |
818 | 0 | return NIL; /* NULL -> NIL list == TRUE */ |
819 | 0 | else if (is_andclause(clause)) |
820 | 0 | return ((BoolExpr *) clause)->args; |
821 | 0 | else if (IsA(clause, Const) && |
822 | 0 | !((Const *) clause)->constisnull && |
823 | 0 | DatumGetBool(((Const *) clause)->constvalue)) |
824 | 0 | return NIL; /* constant TRUE input -> NIL list */ |
825 | 0 | else |
826 | 0 | return list_make1(clause); |
827 | 0 | } |
828 | | |
829 | | /* |
830 | | * makeIndexInfo |
831 | | * create an IndexInfo node |
832 | | */ |
833 | | IndexInfo * |
834 | | makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions, |
835 | | List *predicates, bool unique, bool nulls_not_distinct, |
836 | | bool isready, bool concurrent, bool summarizing, |
837 | | bool withoutoverlaps) |
838 | 0 | { |
839 | 0 | IndexInfo *n = makeNode(IndexInfo); |
840 | |
|
841 | 0 | n->ii_NumIndexAttrs = numattrs; |
842 | 0 | n->ii_NumIndexKeyAttrs = numkeyattrs; |
843 | 0 | Assert(n->ii_NumIndexKeyAttrs != 0); |
844 | 0 | Assert(n->ii_NumIndexKeyAttrs <= n->ii_NumIndexAttrs); |
845 | 0 | n->ii_Unique = unique; |
846 | 0 | n->ii_NullsNotDistinct = nulls_not_distinct; |
847 | 0 | n->ii_ReadyForInserts = isready; |
848 | 0 | n->ii_CheckedUnchanged = false; |
849 | 0 | n->ii_IndexUnchanged = false; |
850 | 0 | n->ii_Concurrent = concurrent; |
851 | 0 | n->ii_Summarizing = summarizing; |
852 | 0 | n->ii_WithoutOverlaps = withoutoverlaps; |
853 | | |
854 | | /* summarizing indexes cannot contain non-key attributes */ |
855 | 0 | Assert(!summarizing || (numkeyattrs == numattrs)); |
856 | | |
857 | | /* expressions */ |
858 | 0 | n->ii_Expressions = expressions; |
859 | 0 | n->ii_ExpressionsState = NIL; |
860 | | |
861 | | /* predicates */ |
862 | 0 | n->ii_Predicate = predicates; |
863 | 0 | n->ii_PredicateState = NULL; |
864 | | |
865 | | /* exclusion constraints */ |
866 | 0 | n->ii_ExclusionOps = NULL; |
867 | 0 | n->ii_ExclusionProcs = NULL; |
868 | 0 | n->ii_ExclusionStrats = NULL; |
869 | | |
870 | | /* speculative inserts */ |
871 | 0 | n->ii_UniqueOps = NULL; |
872 | 0 | n->ii_UniqueProcs = NULL; |
873 | 0 | n->ii_UniqueStrats = NULL; |
874 | | |
875 | | /* initialize index-build state to default */ |
876 | 0 | n->ii_BrokenHotChain = false; |
877 | 0 | n->ii_ParallelWorkers = 0; |
878 | | |
879 | | /* set up for possible use by index AM */ |
880 | 0 | n->ii_Am = amoid; |
881 | 0 | n->ii_AmCache = NULL; |
882 | 0 | n->ii_Context = CurrentMemoryContext; |
883 | |
|
884 | 0 | return n; |
885 | 0 | } |
886 | | |
887 | | /* |
888 | | * makeGroupingSet |
889 | | * |
890 | | */ |
891 | | GroupingSet * |
892 | | makeGroupingSet(GroupingSetKind kind, List *content, int location) |
893 | 0 | { |
894 | 0 | GroupingSet *n = makeNode(GroupingSet); |
895 | |
|
896 | 0 | n->kind = kind; |
897 | 0 | n->content = content; |
898 | 0 | n->location = location; |
899 | 0 | return n; |
900 | 0 | } |
901 | | |
902 | | /* |
903 | | * makeVacuumRelation - |
904 | | * create a VacuumRelation node |
905 | | */ |
906 | | VacuumRelation * |
907 | | makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols) |
908 | 0 | { |
909 | 0 | VacuumRelation *v = makeNode(VacuumRelation); |
910 | |
|
911 | 0 | v->relation = relation; |
912 | 0 | v->oid = oid; |
913 | 0 | v->va_cols = va_cols; |
914 | 0 | return v; |
915 | 0 | } |
916 | | |
917 | | /* |
918 | | * makeJsonFormat - |
919 | | * creates a JsonFormat node |
920 | | */ |
921 | | JsonFormat * |
922 | | makeJsonFormat(JsonFormatType type, JsonEncoding encoding, int location) |
923 | 1.92k | { |
924 | 1.92k | JsonFormat *jf = makeNode(JsonFormat); |
925 | | |
926 | 1.92k | jf->format_type = type; |
927 | 1.92k | jf->encoding = encoding; |
928 | 1.92k | jf->location = location; |
929 | | |
930 | 1.92k | return jf; |
931 | 1.92k | } |
932 | | |
933 | | /* |
934 | | * makeJsonValueExpr - |
935 | | * creates a JsonValueExpr node |
936 | | */ |
937 | | JsonValueExpr * |
938 | | makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr, |
939 | | JsonFormat *format) |
940 | 1.00k | { |
941 | 1.00k | JsonValueExpr *jve = makeNode(JsonValueExpr); |
942 | | |
943 | 1.00k | jve->raw_expr = raw_expr; |
944 | 1.00k | jve->formatted_expr = formatted_expr; |
945 | 1.00k | jve->format = format; |
946 | | |
947 | 1.00k | return jve; |
948 | 1.00k | } |
949 | | |
950 | | /* |
951 | | * makeJsonBehavior - |
952 | | * creates a JsonBehavior node |
953 | | */ |
954 | | JsonBehavior * |
955 | | makeJsonBehavior(JsonBehaviorType btype, Node *expr, int location) |
956 | 0 | { |
957 | 0 | JsonBehavior *behavior = makeNode(JsonBehavior); |
958 | |
|
959 | 0 | behavior->btype = btype; |
960 | 0 | behavior->expr = expr; |
961 | 0 | behavior->location = location; |
962 | |
|
963 | 0 | return behavior; |
964 | 0 | } |
965 | | |
966 | | /* |
967 | | * makeJsonTableDefaultPlan - |
968 | | * creates a JsonTablePlanSpec node to represent a "default" JSON_TABLE plan |
969 | | * with given join strategy |
970 | | */ |
971 | | Node * |
972 | | makeJsonTableDefaultPlan(JsonTablePlanJoinType join_type, int location) |
973 | 0 | { |
974 | 0 | JsonTablePlanSpec *n = makeNode(JsonTablePlanSpec); |
975 | |
|
976 | 0 | n->plan_type = JSTP_DEFAULT; |
977 | 0 | n->join_type = join_type; |
978 | 0 | n->location = location; |
979 | |
|
980 | 0 | return (Node *) n; |
981 | 0 | } |
982 | | |
983 | | /* |
984 | | * makeJsonTableSimplePlan - |
985 | | * creates a JsonTablePlanSpec node to represent a "simple" JSON_TABLE plan |
986 | | * for given PATH |
987 | | */ |
988 | | Node * |
989 | | makeJsonTableSimplePlan(char *pathname, int location) |
990 | 0 | { |
991 | 0 | JsonTablePlanSpec *n = makeNode(JsonTablePlanSpec); |
992 | |
|
993 | 0 | n->plan_type = JSTP_SIMPLE; |
994 | 0 | n->pathname = pathname; |
995 | 0 | n->location = location; |
996 | |
|
997 | 0 | return (Node *) n; |
998 | 0 | } |
999 | | |
1000 | | /* |
1001 | | * makeJsonTableJoinedPlan - |
1002 | | * creates a JsonTablePlanSpec node to represent join between the given |
1003 | | * pair of plans |
1004 | | */ |
1005 | | Node * |
1006 | | makeJsonTableJoinedPlan(JsonTablePlanJoinType type, Node *plan1, Node *plan2, |
1007 | | int location) |
1008 | 0 | { |
1009 | 0 | JsonTablePlanSpec *n = makeNode(JsonTablePlanSpec); |
1010 | |
|
1011 | 0 | n->plan_type = JSTP_JOINED; |
1012 | 0 | n->join_type = type; |
1013 | 0 | n->plan1 = castNode(JsonTablePlanSpec, plan1); |
1014 | 0 | n->plan2 = castNode(JsonTablePlanSpec, plan2); |
1015 | 0 | n->location = location; |
1016 | |
|
1017 | 0 | return (Node *) n; |
1018 | 0 | } |
1019 | | |
1020 | | /* |
1021 | | * makeJsonKeyValue - |
1022 | | * creates a JsonKeyValue node |
1023 | | */ |
1024 | | Node * |
1025 | | makeJsonKeyValue(Node *key, Node *value) |
1026 | 0 | { |
1027 | 0 | JsonKeyValue *n = makeNode(JsonKeyValue); |
1028 | |
|
1029 | 0 | n->key = (Expr *) key; |
1030 | 0 | n->value = castNode(JsonValueExpr, value); |
1031 | |
|
1032 | 0 | return (Node *) n; |
1033 | 0 | } |
1034 | | |
1035 | | /* |
1036 | | * makeJsonIsPredicate - |
1037 | | * creates a JsonIsPredicate node |
1038 | | */ |
1039 | | Node * |
1040 | | makeJsonIsPredicate(Node *expr, JsonFormat *format, JsonValueType item_type, |
1041 | | bool unique_keys, Oid exprBaseType, int location) |
1042 | 920 | { |
1043 | 920 | JsonIsPredicate *n = makeNode(JsonIsPredicate); |
1044 | | |
1045 | 920 | Assert(expr != NULL); |
1046 | | |
1047 | 920 | n->expr = expr; |
1048 | 920 | n->format = format; |
1049 | 920 | n->item_type = item_type; |
1050 | 920 | n->unique_keys = unique_keys; |
1051 | 920 | n->exprBaseType = exprBaseType; |
1052 | 920 | n->location = location; |
1053 | | |
1054 | 920 | return (Node *) n; |
1055 | 920 | } |
1056 | | |
1057 | | /* |
1058 | | * makeJsonTablePathSpec - |
1059 | | * Make JsonTablePathSpec node from given path string and name (if any) |
1060 | | */ |
1061 | | JsonTablePathSpec * |
1062 | | makeJsonTablePathSpec(char *string, char *name, int string_location, |
1063 | | int name_location) |
1064 | 0 | { |
1065 | 0 | JsonTablePathSpec *pathspec = makeNode(JsonTablePathSpec); |
1066 | |
|
1067 | 0 | Assert(string != NULL); |
1068 | 0 | pathspec->string = makeStringConst(string, string_location); |
1069 | 0 | if (name != NULL) |
1070 | 0 | pathspec->name = pstrdup(name); |
1071 | |
|
1072 | 0 | pathspec->name_location = name_location; |
1073 | 0 | pathspec->location = string_location; |
1074 | |
|
1075 | 0 | return pathspec; |
1076 | 0 | } |
1077 | | |
1078 | | /* |
1079 | | * makeJsonTablePath - |
1080 | | * Make JsonTablePath node for given path string and name |
1081 | | */ |
1082 | | JsonTablePath * |
1083 | | makeJsonTablePath(Const *pathvalue, char *pathname) |
1084 | 0 | { |
1085 | 0 | JsonTablePath *path = makeNode(JsonTablePath); |
1086 | |
|
1087 | 0 | Assert(IsA(pathvalue, Const)); |
1088 | 0 | path->value = pathvalue; |
1089 | 0 | path->name = pathname; |
1090 | |
|
1091 | 0 | return path; |
1092 | 0 | } |