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) 2003-2021, PgPool Global Development Group
8 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
10 *
11 *
12 * IDENTIFICATION
13 * src/backend/nodes/makefuncs.c
14 *
15 *-------------------------------------------------------------------------
16 */
17 #include "pool_parser.h"
18
19 #include "makefuncs.h"
20 #include "utils/palloc.h"
21 #include "pg_class.h"
22 #include <stdlib.h>
23 #include <string.h>
24
25
26 /*
27 * makeA_Expr -
28 * makes an A_Expr node
29 */
30 A_Expr *
makeA_Expr(A_Expr_Kind kind,List * name,Node * lexpr,Node * rexpr,int location)31 makeA_Expr(A_Expr_Kind kind, List *name,
32 Node *lexpr, Node *rexpr, int location)
33 {
34 A_Expr *a = makeNode(A_Expr);
35
36 a->kind = kind;
37 a->name = name;
38 a->lexpr = lexpr;
39 a->rexpr = rexpr;
40 a->location = location;
41 return a;
42 }
43
44 /*
45 * makeSimpleA_Expr -
46 * As above, given a simple (unqualified) operator name
47 */
48 A_Expr *
makeSimpleA_Expr(A_Expr_Kind kind,char * name,Node * lexpr,Node * rexpr,int location)49 makeSimpleA_Expr(A_Expr_Kind kind, char *name,
50 Node *lexpr, Node *rexpr, int location)
51 {
52 A_Expr *a = makeNode(A_Expr);
53
54 a->kind = kind;
55 a->name = list_make1(makeString((char *) name));
56 a->lexpr = lexpr;
57 a->rexpr = rexpr;
58 a->location = location;
59 return a;
60 }
61
62 /*
63 * makeVar -
64 * creates a Var node
65 */
66 Var *
makeVar(Index varno,AttrNumber varattno,Oid vartype,int32 vartypmod,Oid varcollid,Index varlevelsup)67 makeVar(Index varno,
68 AttrNumber varattno,
69 Oid vartype,
70 int32 vartypmod,
71 Oid varcollid,
72 Index varlevelsup)
73 {
74 Var *var = makeNode(Var);
75
76 var->varno = varno;
77 var->varattno = varattno;
78 var->vartype = vartype;
79 var->vartypmod = vartypmod;
80 var->varcollid = varcollid;
81 var->varlevelsup = varlevelsup;
82
83 /*
84 * Only a few callers need to make Var nodes with varnosyn/varattnosyn
85 * different from varno/varattno. We don't provide separate arguments for
86 * them, but just initialize them to the given varno/varattno. This
87 * reduces code clutter and chance of error for most callers.
88 */
89 var->varnosyn = varno;
90 var->varattnosyn = varattno;
91
92 /* Likewise, we just set location to "unknown" here */
93 var->location = -1;
94
95 return var;
96 }
97
98 #if 0
99 /*
100 * makeVarFromTargetEntry -
101 * convenience function to create a same-level Var node from a
102 * TargetEntry
103 */
104 Var *
105 makeVarFromTargetEntry(Index varno,
106 TargetEntry *tle)
107 {
108 return makeVar(varno,
109 tle->resno,
110 exprType((Node *) tle->expr),
111 exprTypmod((Node *) tle->expr),
112 exprCollation((Node *) tle->expr),
113 0);
114 }
115
116 /*
117 * makeWholeRowVar -
118 * creates a Var node representing a whole row of the specified RTE
119 *
120 * A whole-row reference is a Var with varno set to the correct range
121 * table entry, and varattno == 0 to signal that it references the whole
122 * tuple. (Use of zero here is unclean, since it could easily be confused
123 * with error cases, but it's not worth changing now.) The vartype indicates
124 * a rowtype; either a named composite type, or a domain over a named
125 * composite type (only possible if the RTE is a function returning that),
126 * or RECORD. This function encapsulates the logic for determining the
127 * correct rowtype OID to use.
128 *
129 * If allowScalar is true, then for the case where the RTE is a single function
130 * returning a non-composite result type, we produce a normal Var referencing
131 * the function's result directly, instead of the single-column composite
132 * value that the whole-row notation might otherwise suggest.
133 */
134 Var *
135 makeWholeRowVar(RangeTblEntry *rte,
136 Index varno,
137 Index varlevelsup,
138 bool allowScalar)
139 {
140 Var *result;
141 Oid toid;
142 Node *fexpr;
143
144 switch (rte->rtekind)
145 {
146 case RTE_RELATION:
147 /* relation: the rowtype is a named composite type */
148 toid = get_rel_type_id(rte->relid);
149 if (!OidIsValid(toid))
150 ereport(ERROR,
151 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
152 errmsg("relation \"%s\" does not have a composite type",
153 get_rel_name(rte->relid))));
154 result = makeVar(varno,
155 InvalidAttrNumber,
156 toid,
157 -1,
158 InvalidOid,
159 varlevelsup);
160 break;
161
162 case RTE_FUNCTION:
163
164 /*
165 * If there's more than one function, or ordinality is requested,
166 * force a RECORD result, since there's certainly more than one
167 * column involved and it can't be a known named type.
168 */
169 if (rte->funcordinality || list_length(rte->functions) != 1)
170 {
171 /* always produces an anonymous RECORD result */
172 result = makeVar(varno,
173 InvalidAttrNumber,
174 RECORDOID,
175 -1,
176 InvalidOid,
177 varlevelsup);
178 break;
179 }
180
181 fexpr = ((RangeTblFunction *) linitial(rte->functions))->funcexpr;
182 toid = exprType(fexpr);
183 if (type_is_rowtype(toid))
184 {
185 /* func returns composite; same as relation case */
186 result = makeVar(varno,
187 InvalidAttrNumber,
188 toid,
189 -1,
190 InvalidOid,
191 varlevelsup);
192 }
193 else if (allowScalar)
194 {
195 /* func returns scalar; just return its output as-is */
196 result = makeVar(varno,
197 1,
198 toid,
199 -1,
200 exprCollation(fexpr),
201 varlevelsup);
202 }
203 else
204 {
205 /* func returns scalar, but we want a composite result */
206 result = makeVar(varno,
207 InvalidAttrNumber,
208 RECORDOID,
209 -1,
210 InvalidOid,
211 varlevelsup);
212 }
213 break;
214
215 default:
216
217 /*
218 * RTE is a join, subselect, tablefunc, or VALUES. We represent
219 * this as a whole-row Var of RECORD type. (Note that in most
220 * cases the Var will be expanded to a RowExpr during planning,
221 * but that is not our concern here.)
222 */
223 result = makeVar(varno,
224 InvalidAttrNumber,
225 RECORDOID,
226 -1,
227 InvalidOid,
228 varlevelsup);
229 break;
230 }
231
232 return result;
233 }
234
235 #endif
236
237 /*
238 * makeTargetEntry -
239 * creates a TargetEntry node
240 */
241 TargetEntry *
makeTargetEntry(Expr * expr,AttrNumber resno,char * resname,bool resjunk)242 makeTargetEntry(Expr *expr,
243 AttrNumber resno,
244 char *resname,
245 bool resjunk)
246 {
247 TargetEntry *tle = makeNode(TargetEntry);
248
249 tle->expr = expr;
250 tle->resno = resno;
251 tle->resname = resname;
252
253 /*
254 * We always set these fields to 0. If the caller wants to change them he
255 * must do so explicitly. Few callers do that, so omitting these
256 * arguments reduces the chance of error.
257 */
258 tle->ressortgroupref = 0;
259 tle->resorigtbl = InvalidOid;
260 tle->resorigcol = 0;
261
262 tle->resjunk = resjunk;
263
264 return tle;
265 }
266
267 /*
268 * flatCopyTargetEntry -
269 * duplicate a TargetEntry, but don't copy substructure
270 *
271 * This is commonly used when we just want to modify the resno or substitute
272 * a new expression.
273 */
274 TargetEntry *
flatCopyTargetEntry(TargetEntry * src_tle)275 flatCopyTargetEntry(TargetEntry *src_tle)
276 {
277 TargetEntry *tle = makeNode(TargetEntry);
278
279 Assert(IsA(src_tle, TargetEntry));
280 memcpy(tle, src_tle, sizeof(TargetEntry));
281 return tle;
282 }
283
284 /*
285 * makeFromExpr -
286 * creates a FromExpr node
287 */
288 FromExpr *
makeFromExpr(List * fromlist,Node * quals)289 makeFromExpr(List *fromlist, Node *quals)
290 {
291 FromExpr *f = makeNode(FromExpr);
292
293 f->fromlist = fromlist;
294 f->quals = quals;
295 return f;
296 }
297
298 /*
299 * makeConst -
300 * creates a Const node
301 */
302 Const *
makeConst(Oid consttype,int32 consttypmod,Oid constcollid,int constlen,Datum constvalue,bool constisnull,bool constbyval)303 makeConst(Oid consttype,
304 int32 consttypmod,
305 Oid constcollid,
306 int constlen,
307 Datum constvalue,
308 bool constisnull,
309 bool constbyval)
310 {
311 Const *cnst = makeNode(Const);
312
313 cnst->consttype = consttype;
314 cnst->consttypmod = consttypmod;
315 cnst->constcollid = constcollid;
316 cnst->constlen = constlen;
317 cnst->constvalue = constvalue;
318 cnst->constisnull = constisnull;
319 cnst->constbyval = constbyval;
320 cnst->location = -1; /* "unknown" */
321
322 return cnst;
323 }
324
325 #if 0
326 /*
327 * makeNullConst -
328 * creates a Const node representing a NULL of the specified type/typmod
329 *
330 * This is a convenience routine that just saves a lookup of the type's
331 * storage properties.
332 */
333 Const *
334 makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
335 {
336 int16 typLen;
337 bool typByVal;
338
339 get_typlenbyval(consttype, &typLen, &typByVal);
340 return makeConst(consttype,
341 consttypmod,
342 constcollid,
343 (int) typLen,
344 (Datum) 0,
345 true,
346 typByVal);
347 }
348
349 /*
350 * makeBoolConst -
351 * creates a Const node representing a boolean value (can be NULL too)
352 */
353 Node *
354 makeBoolConst(bool value, bool isnull)
355 {
356 /* note that pg_type.h hardwires size of bool as 1 ... duplicate it */
357 return (Node *) makeConst(BOOLOID, -1, InvalidOid, 1,
358 BoolGetDatum(value), isnull, true);
359 }
360
361 #endif
362
363 /*
364 * makeBoolExpr -
365 * creates a BoolExpr node
366 */
367 Expr *
makeBoolExpr(BoolExprType boolop,List * args,int location)368 makeBoolExpr(BoolExprType boolop, List *args, int location)
369 {
370 BoolExpr *b = makeNode(BoolExpr);
371
372 b->boolop = boolop;
373 b->args = args;
374 b->location = location;
375
376 return (Expr *) b;
377 }
378
379 /*
380 * makeAlias -
381 * creates an Alias node
382 *
383 * NOTE: the given name is copied, but the colnames list (if any) isn't.
384 */
385 Alias *
makeAlias(const char * aliasname,List * colnames)386 makeAlias(const char *aliasname, List *colnames)
387 {
388 Alias *a = makeNode(Alias);
389
390 a->aliasname = pstrdup(aliasname);
391 a->colnames = colnames;
392
393 return a;
394 }
395
396 /*
397 * makeRelabelType -
398 * creates a RelabelType node
399 */
400 RelabelType *
makeRelabelType(Expr * arg,Oid rtype,int32 rtypmod,Oid rcollid,CoercionForm rformat)401 makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, Oid rcollid,
402 CoercionForm rformat)
403 {
404 RelabelType *r = makeNode(RelabelType);
405
406 r->arg = arg;
407 r->resulttype = rtype;
408 r->resulttypmod = rtypmod;
409 r->resultcollid = rcollid;
410 r->relabelformat = rformat;
411 r->location = -1;
412
413 return r;
414 }
415
416 /*
417 * makeRangeVar -
418 * creates a RangeVar node (rather oversimplified case)
419 */
420 RangeVar *
makeRangeVar(char * schemaname,char * relname,int location)421 makeRangeVar(char *schemaname, char *relname, int location)
422 {
423 RangeVar *r = makeNode(RangeVar);
424
425 r->catalogname = NULL;
426 r->schemaname = schemaname;
427 r->relname = relname;
428 r->inh = true;
429 r->relpersistence = RELPERSISTENCE_PERMANENT;
430 r->alias = NULL;
431 r->location = location;
432
433 return r;
434 }
435
436 /*
437 * makeTypeName -
438 * build a TypeName node for an unqualified name.
439 *
440 * typmod is defaulted, but can be changed later by caller.
441 */
442 TypeName *
makeTypeName(char * typnam)443 makeTypeName(char *typnam)
444 {
445 return makeTypeNameFromNameList(list_make1(makeString(typnam)));
446 }
447
448 /*
449 * makeTypeNameFromNameList -
450 * build a TypeName node for a String list representing a qualified name.
451 *
452 * typmod is defaulted, but can be changed later by caller.
453 */
454 TypeName *
makeTypeNameFromNameList(List * names)455 makeTypeNameFromNameList(List *names)
456 {
457 TypeName *n = makeNode(TypeName);
458
459 n->names = names;
460 n->typmods = NIL;
461 n->typemod = -1;
462 n->location = -1;
463 return n;
464 }
465
466 /*
467 * makeTypeNameFromOid -
468 * build a TypeName node to represent a type already known by OID/typmod.
469 */
470 TypeName *
makeTypeNameFromOid(Oid typeOid,int32 typmod)471 makeTypeNameFromOid(Oid typeOid, int32 typmod)
472 {
473 TypeName *n = makeNode(TypeName);
474
475 n->typeOid = typeOid;
476 n->typemod = typmod;
477 n->location = -1;
478 return n;
479 }
480
481 /*
482 * makeColumnDef -
483 * build a ColumnDef node to represent a simple column definition.
484 *
485 * Type and collation are specified by OID.
486 * Other properties are all basic to start with.
487 */
488 ColumnDef *
makeColumnDef(const char * colname,Oid typeOid,int32 typmod,Oid collOid)489 makeColumnDef(const char *colname, Oid typeOid, int32 typmod, Oid collOid)
490 {
491 ColumnDef *n = makeNode(ColumnDef);
492
493 n->colname = pstrdup(colname);
494 n->typeName = makeTypeNameFromOid(typeOid, typmod);
495 n->inhcount = 0;
496 n->is_local = true;
497 n->is_not_null = false;
498 n->is_from_type = false;
499 n->storage = 0;
500 n->raw_default = NULL;
501 n->cooked_default = NULL;
502 n->collClause = NULL;
503 n->collOid = collOid;
504 n->constraints = NIL;
505 n->fdwoptions = NIL;
506 n->location = -1;
507
508 return n;
509 }
510
511 /*
512 * makeFuncExpr -
513 * build an expression tree representing a function call.
514 *
515 * The argument expressions must have been transformed already.
516 */
517 FuncExpr *
makeFuncExpr(Oid funcid,Oid rettype,List * args,Oid funccollid,Oid inputcollid,CoercionForm fformat)518 makeFuncExpr(Oid funcid, Oid rettype, List *args,
519 Oid funccollid, Oid inputcollid, CoercionForm fformat)
520 {
521 FuncExpr *funcexpr;
522
523 funcexpr = makeNode(FuncExpr);
524 funcexpr->funcid = funcid;
525 funcexpr->funcresulttype = rettype;
526 funcexpr->funcretset = false; /* only allowed case here */
527 funcexpr->funcvariadic = false; /* only allowed case here */
528 funcexpr->funcformat = fformat;
529 funcexpr->funccollid = funccollid;
530 funcexpr->inputcollid = inputcollid;
531 funcexpr->args = args;
532 funcexpr->location = -1;
533
534 return funcexpr;
535 }
536
537 /*
538 * makeDefElem -
539 * build a DefElem node
540 *
541 * This is sufficient for the "typical" case with an unqualified option name
542 * and no special action.
543 */
544 DefElem *
makeDefElem(char * name,Node * arg,int location)545 makeDefElem(char *name, Node *arg, int location)
546 {
547 DefElem *res = makeNode(DefElem);
548
549 res->defnamespace = NULL;
550 res->defname = name;
551 res->arg = arg;
552 res->defaction = DEFELEM_UNSPEC;
553 res->location = location;
554
555 return res;
556 }
557
558 /*
559 * makeDefElemExtended -
560 * build a DefElem node with all fields available to be specified
561 */
562 DefElem *
makeDefElemExtended(char * nameSpace,char * name,Node * arg,DefElemAction defaction,int location)563 makeDefElemExtended(char *nameSpace, char *name, Node *arg,
564 DefElemAction defaction, int location)
565 {
566 DefElem *res = makeNode(DefElem);
567
568 res->defnamespace = nameSpace;
569 res->defname = name;
570 res->arg = arg;
571 res->defaction = defaction;
572 res->location = location;
573
574 return res;
575 }
576
577 /*
578 * makeFuncCall -
579 *
580 * Initialize a FuncCall struct with the information every caller must
581 * supply. Any non-default parameters have to be inserted by the caller.
582 */
583 FuncCall *
makeFuncCall(List * name,List * args,CoercionForm funcformat,int location)584 makeFuncCall(List *name, List *args, CoercionForm funcformat, int location)
585 {
586 FuncCall *n = makeNode(FuncCall);
587
588 n->funcname = name;
589 n->args = args;
590 n->agg_order = NIL;
591 n->agg_filter = NULL;
592 n->over = NULL;
593 n->agg_within_group = false;
594 n->agg_star = false;
595 n->agg_distinct = false;
596 n->func_variadic = false;
597 n->funcformat = funcformat;
598 n->location = location;
599 return n;
600 }
601
602 /*
603 * makeGroupingSet
604 *
605 */
606 GroupingSet *
makeGroupingSet(GroupingSetKind kind,List * content,int location)607 makeGroupingSet(GroupingSetKind kind, List *content, int location)
608 {
609 GroupingSet *n = makeNode(GroupingSet);
610
611 n->kind = kind;
612 n->content = content;
613 n->location = location;
614 return n;
615 }
616
617 /*
618 * makeVacuumRelation -
619 * create a VacuumRelation node
620 */
621 VacuumRelation *
makeVacuumRelation(RangeVar * relation,Oid oid,List * va_cols)622 makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols)
623 {
624 VacuumRelation *v = makeNode(VacuumRelation);
625
626 v->relation = relation;
627 v->oid = oid;
628 v->va_cols = va_cols;
629 return v;
630 }
631