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-2019, 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 "fmgr.h" |
21 | #include "nodes/makefuncs.h" |
22 | #include "nodes/nodeFuncs.h" |
23 | #include "utils/lsyscache.h" |
24 | |
25 | |
26 | /* |
27 | * makeA_Expr - |
28 | * makes an A_Expr node |
29 | */ |
30 | A_Expr * |
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 * |
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 * |
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 | * Since few if any routines ever create Var nodes with varnoold/varoattno |
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->varnoold = varno; |
90 | var->varoattno = varattno; |
91 | |
92 | /* Likewise, we just set location to "unknown" here */ |
93 | var->location = -1; |
94 | |
95 | return var; |
96 | } |
97 | |
98 | /* |
99 | * makeVarFromTargetEntry - |
100 | * convenience function to create a same-level Var node from a |
101 | * TargetEntry |
102 | */ |
103 | Var * |
104 | makeVarFromTargetEntry(Index varno, |
105 | TargetEntry *tle) |
106 | { |
107 | return makeVar(varno, |
108 | tle->resno, |
109 | exprType((Node *) tle->expr), |
110 | exprTypmod((Node *) tle->expr), |
111 | exprCollation((Node *) tle->expr), |
112 | 0); |
113 | } |
114 | |
115 | /* |
116 | * makeWholeRowVar - |
117 | * creates a Var node representing a whole row of the specified RTE |
118 | * |
119 | * A whole-row reference is a Var with varno set to the correct range |
120 | * table entry, and varattno == 0 to signal that it references the whole |
121 | * tuple. (Use of zero here is unclean, since it could easily be confused |
122 | * with error cases, but it's not worth changing now.) The vartype indicates |
123 | * a rowtype; either a named composite type, or a domain over a named |
124 | * composite type (only possible if the RTE is a function returning that), |
125 | * or RECORD. This function encapsulates the logic for determining the |
126 | * correct rowtype OID to use. |
127 | * |
128 | * If allowScalar is true, then for the case where the RTE is a single function |
129 | * returning a non-composite result type, we produce a normal Var referencing |
130 | * the function's result directly, instead of the single-column composite |
131 | * value that the whole-row notation might otherwise suggest. |
132 | */ |
133 | Var * |
134 | makeWholeRowVar(RangeTblEntry *rte, |
135 | Index varno, |
136 | Index varlevelsup, |
137 | bool allowScalar) |
138 | { |
139 | Var *result; |
140 | Oid toid; |
141 | Node *fexpr; |
142 | |
143 | switch (rte->rtekind) |
144 | { |
145 | case RTE_RELATION: |
146 | /* relation: the rowtype is a named composite type */ |
147 | toid = get_rel_type_id(rte->relid); |
148 | if (!OidIsValid(toid)) |
149 | elog(ERROR, "could not find type OID for relation %u" , |
150 | rte->relid); |
151 | result = makeVar(varno, |
152 | InvalidAttrNumber, |
153 | toid, |
154 | -1, |
155 | InvalidOid, |
156 | varlevelsup); |
157 | break; |
158 | |
159 | case RTE_FUNCTION: |
160 | |
161 | /* |
162 | * If there's more than one function, or ordinality is requested, |
163 | * force a RECORD result, since there's certainly more than one |
164 | * column involved and it can't be a known named type. |
165 | */ |
166 | if (rte->funcordinality || list_length(rte->functions) != 1) |
167 | { |
168 | /* always produces an anonymous RECORD result */ |
169 | result = makeVar(varno, |
170 | InvalidAttrNumber, |
171 | RECORDOID, |
172 | -1, |
173 | InvalidOid, |
174 | varlevelsup); |
175 | break; |
176 | } |
177 | |
178 | fexpr = ((RangeTblFunction *) linitial(rte->functions))->funcexpr; |
179 | toid = exprType(fexpr); |
180 | if (type_is_rowtype(toid)) |
181 | { |
182 | /* func returns composite; same as relation case */ |
183 | result = makeVar(varno, |
184 | InvalidAttrNumber, |
185 | toid, |
186 | -1, |
187 | InvalidOid, |
188 | varlevelsup); |
189 | } |
190 | else if (allowScalar) |
191 | { |
192 | /* func returns scalar; just return its output as-is */ |
193 | result = makeVar(varno, |
194 | 1, |
195 | toid, |
196 | -1, |
197 | exprCollation(fexpr), |
198 | varlevelsup); |
199 | } |
200 | else |
201 | { |
202 | /* func returns scalar, but we want a composite result */ |
203 | result = makeVar(varno, |
204 | InvalidAttrNumber, |
205 | RECORDOID, |
206 | -1, |
207 | InvalidOid, |
208 | varlevelsup); |
209 | } |
210 | break; |
211 | |
212 | default: |
213 | |
214 | /* |
215 | * RTE is a join, subselect, tablefunc, or VALUES. We represent |
216 | * this as a whole-row Var of RECORD type. (Note that in most |
217 | * cases the Var will be expanded to a RowExpr during planning, |
218 | * but that is not our concern here.) |
219 | */ |
220 | result = makeVar(varno, |
221 | InvalidAttrNumber, |
222 | RECORDOID, |
223 | -1, |
224 | InvalidOid, |
225 | varlevelsup); |
226 | break; |
227 | } |
228 | |
229 | return result; |
230 | } |
231 | |
232 | /* |
233 | * makeTargetEntry - |
234 | * creates a TargetEntry node |
235 | */ |
236 | TargetEntry * |
237 | makeTargetEntry(Expr *expr, |
238 | AttrNumber resno, |
239 | char *resname, |
240 | bool resjunk) |
241 | { |
242 | TargetEntry *tle = makeNode(TargetEntry); |
243 | |
244 | tle->expr = expr; |
245 | tle->resno = resno; |
246 | tle->resname = resname; |
247 | |
248 | /* |
249 | * We always set these fields to 0. If the caller wants to change them he |
250 | * must do so explicitly. Few callers do that, so omitting these |
251 | * arguments reduces the chance of error. |
252 | */ |
253 | tle->ressortgroupref = 0; |
254 | tle->resorigtbl = InvalidOid; |
255 | tle->resorigcol = 0; |
256 | |
257 | tle->resjunk = resjunk; |
258 | |
259 | return tle; |
260 | } |
261 | |
262 | /* |
263 | * flatCopyTargetEntry - |
264 | * duplicate a TargetEntry, but don't copy substructure |
265 | * |
266 | * This is commonly used when we just want to modify the resno or substitute |
267 | * a new expression. |
268 | */ |
269 | TargetEntry * |
270 | flatCopyTargetEntry(TargetEntry *src_tle) |
271 | { |
272 | TargetEntry *tle = makeNode(TargetEntry); |
273 | |
274 | Assert(IsA(src_tle, TargetEntry)); |
275 | memcpy(tle, src_tle, sizeof(TargetEntry)); |
276 | return tle; |
277 | } |
278 | |
279 | /* |
280 | * makeFromExpr - |
281 | * creates a FromExpr node |
282 | */ |
283 | FromExpr * |
284 | makeFromExpr(List *fromlist, Node *quals) |
285 | { |
286 | FromExpr *f = makeNode(FromExpr); |
287 | |
288 | f->fromlist = fromlist; |
289 | f->quals = quals; |
290 | return f; |
291 | } |
292 | |
293 | /* |
294 | * makeConst - |
295 | * creates a Const node |
296 | */ |
297 | Const * |
298 | makeConst(Oid consttype, |
299 | int32 consttypmod, |
300 | Oid constcollid, |
301 | int constlen, |
302 | Datum constvalue, |
303 | bool constisnull, |
304 | bool constbyval) |
305 | { |
306 | Const *cnst = makeNode(Const); |
307 | |
308 | /* |
309 | * If it's a varlena value, force it to be in non-expanded (non-toasted) |
310 | * format; this avoids any possible dependency on external values and |
311 | * improves consistency of representation, which is important for equal(). |
312 | */ |
313 | if (!constisnull && constlen == -1) |
314 | constvalue = PointerGetDatum(PG_DETOAST_DATUM(constvalue)); |
315 | |
316 | cnst->consttype = consttype; |
317 | cnst->consttypmod = consttypmod; |
318 | cnst->constcollid = constcollid; |
319 | cnst->constlen = constlen; |
320 | cnst->constvalue = constvalue; |
321 | cnst->constisnull = constisnull; |
322 | cnst->constbyval = constbyval; |
323 | cnst->location = -1; /* "unknown" */ |
324 | |
325 | return cnst; |
326 | } |
327 | |
328 | /* |
329 | * makeNullConst - |
330 | * creates a Const node representing a NULL of the specified type/typmod |
331 | * |
332 | * This is a convenience routine that just saves a lookup of the type's |
333 | * storage properties. |
334 | */ |
335 | Const * |
336 | makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid) |
337 | { |
338 | int16 typLen; |
339 | bool typByVal; |
340 | |
341 | get_typlenbyval(consttype, &typLen, &typByVal); |
342 | return makeConst(consttype, |
343 | consttypmod, |
344 | constcollid, |
345 | (int) typLen, |
346 | (Datum) 0, |
347 | true, |
348 | typByVal); |
349 | } |
350 | |
351 | /* |
352 | * makeBoolConst - |
353 | * creates a Const node representing a boolean value (can be NULL too) |
354 | */ |
355 | Node * |
356 | makeBoolConst(bool value, bool isnull) |
357 | { |
358 | /* note that pg_type.h hardwires size of bool as 1 ... duplicate it */ |
359 | return (Node *) makeConst(BOOLOID, -1, InvalidOid, 1, |
360 | BoolGetDatum(value), isnull, true); |
361 | } |
362 | |
363 | /* |
364 | * makeBoolExpr - |
365 | * creates a BoolExpr node |
366 | */ |
367 | Expr * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
584 | makeFuncCall(List *name, List *args, 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->agg_within_group = false; |
593 | n->agg_star = false; |
594 | n->agg_distinct = false; |
595 | n->func_variadic = false; |
596 | n->over = NULL; |
597 | n->location = location; |
598 | return n; |
599 | } |
600 | |
601 | /* |
602 | * make_opclause |
603 | * Creates an operator clause given its operator info, left operand |
604 | * and right operand (pass NULL to create single-operand clause), |
605 | * and collation info. |
606 | */ |
607 | Expr * |
608 | make_opclause(Oid opno, Oid opresulttype, bool opretset, |
609 | Expr *leftop, Expr *rightop, |
610 | Oid opcollid, Oid inputcollid) |
611 | { |
612 | OpExpr *expr = makeNode(OpExpr); |
613 | |
614 | expr->opno = opno; |
615 | expr->opfuncid = InvalidOid; |
616 | expr->opresulttype = opresulttype; |
617 | expr->opretset = opretset; |
618 | expr->opcollid = opcollid; |
619 | expr->inputcollid = inputcollid; |
620 | if (rightop) |
621 | expr->args = list_make2(leftop, rightop); |
622 | else |
623 | expr->args = list_make1(leftop); |
624 | expr->location = -1; |
625 | return (Expr *) expr; |
626 | } |
627 | |
628 | /* |
629 | * make_andclause |
630 | * |
631 | * Creates an 'and' clause given a list of its subclauses. |
632 | */ |
633 | Expr * |
634 | make_andclause(List *andclauses) |
635 | { |
636 | BoolExpr *expr = makeNode(BoolExpr); |
637 | |
638 | expr->boolop = AND_EXPR; |
639 | expr->args = andclauses; |
640 | expr->location = -1; |
641 | return (Expr *) expr; |
642 | } |
643 | |
644 | /* |
645 | * make_orclause |
646 | * |
647 | * Creates an 'or' clause given a list of its subclauses. |
648 | */ |
649 | Expr * |
650 | make_orclause(List *orclauses) |
651 | { |
652 | BoolExpr *expr = makeNode(BoolExpr); |
653 | |
654 | expr->boolop = OR_EXPR; |
655 | expr->args = orclauses; |
656 | expr->location = -1; |
657 | return (Expr *) expr; |
658 | } |
659 | |
660 | /* |
661 | * make_notclause |
662 | * |
663 | * Create a 'not' clause given the expression to be negated. |
664 | */ |
665 | Expr * |
666 | make_notclause(Expr *notclause) |
667 | { |
668 | BoolExpr *expr = makeNode(BoolExpr); |
669 | |
670 | expr->boolop = NOT_EXPR; |
671 | expr->args = list_make1(notclause); |
672 | expr->location = -1; |
673 | return (Expr *) expr; |
674 | } |
675 | |
676 | /* |
677 | * make_and_qual |
678 | * |
679 | * Variant of make_andclause for ANDing two qual conditions together. |
680 | * Qual conditions have the property that a NULL nodetree is interpreted |
681 | * as 'true'. |
682 | * |
683 | * NB: this makes no attempt to preserve AND/OR flatness; so it should not |
684 | * be used on a qual that has already been run through prepqual.c. |
685 | */ |
686 | Node * |
687 | make_and_qual(Node *qual1, Node *qual2) |
688 | { |
689 | if (qual1 == NULL) |
690 | return qual2; |
691 | if (qual2 == NULL) |
692 | return qual1; |
693 | return (Node *) make_andclause(list_make2(qual1, qual2)); |
694 | } |
695 | |
696 | /* |
697 | * The planner and executor usually represent qualification expressions |
698 | * as lists of boolean expressions with implicit AND semantics. |
699 | * |
700 | * These functions convert between an AND-semantics expression list and the |
701 | * ordinary representation of a boolean expression. |
702 | * |
703 | * Note that an empty list is considered equivalent to TRUE. |
704 | */ |
705 | Expr * |
706 | make_ands_explicit(List *andclauses) |
707 | { |
708 | if (andclauses == NIL) |
709 | return (Expr *) makeBoolConst(true, false); |
710 | else if (list_length(andclauses) == 1) |
711 | return (Expr *) linitial(andclauses); |
712 | else |
713 | return make_andclause(andclauses); |
714 | } |
715 | |
716 | List * |
717 | make_ands_implicit(Expr *clause) |
718 | { |
719 | /* |
720 | * NB: because the parser sets the qual field to NULL in a query that has |
721 | * no WHERE clause, we must consider a NULL input clause as TRUE, even |
722 | * though one might more reasonably think it FALSE. |
723 | */ |
724 | if (clause == NULL) |
725 | return NIL; /* NULL -> NIL list == TRUE */ |
726 | else if (is_andclause(clause)) |
727 | return ((BoolExpr *) clause)->args; |
728 | else if (IsA(clause, Const) && |
729 | !((Const *) clause)->constisnull && |
730 | DatumGetBool(((Const *) clause)->constvalue)) |
731 | return NIL; /* constant TRUE input -> NIL list */ |
732 | else |
733 | return list_make1(clause); |
734 | } |
735 | |
736 | /* |
737 | * makeIndexInfo |
738 | * create an IndexInfo node |
739 | */ |
740 | IndexInfo * |
741 | makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions, |
742 | List *predicates, bool unique, bool isready, bool concurrent) |
743 | { |
744 | IndexInfo *n = makeNode(IndexInfo); |
745 | |
746 | n->ii_NumIndexAttrs = numattrs; |
747 | n->ii_NumIndexKeyAttrs = numkeyattrs; |
748 | Assert(n->ii_NumIndexKeyAttrs != 0); |
749 | Assert(n->ii_NumIndexKeyAttrs <= n->ii_NumIndexAttrs); |
750 | n->ii_Unique = unique; |
751 | n->ii_ReadyForInserts = isready; |
752 | n->ii_Concurrent = concurrent; |
753 | |
754 | /* expressions */ |
755 | n->ii_Expressions = expressions; |
756 | n->ii_ExpressionsState = NIL; |
757 | |
758 | /* predicates */ |
759 | n->ii_Predicate = predicates; |
760 | n->ii_PredicateState = NULL; |
761 | |
762 | /* exclusion constraints */ |
763 | n->ii_ExclusionOps = NULL; |
764 | n->ii_ExclusionProcs = NULL; |
765 | n->ii_ExclusionStrats = NULL; |
766 | |
767 | /* speculative inserts */ |
768 | n->ii_UniqueOps = NULL; |
769 | n->ii_UniqueProcs = NULL; |
770 | n->ii_UniqueStrats = NULL; |
771 | |
772 | /* initialize index-build state to default */ |
773 | n->ii_BrokenHotChain = false; |
774 | n->ii_ParallelWorkers = 0; |
775 | |
776 | /* set up for possible use by index AM */ |
777 | n->ii_Am = amoid; |
778 | n->ii_AmCache = NULL; |
779 | n->ii_Context = CurrentMemoryContext; |
780 | |
781 | return n; |
782 | } |
783 | |
784 | /* |
785 | * makeGroupingSet |
786 | * |
787 | */ |
788 | GroupingSet * |
789 | makeGroupingSet(GroupingSetKind kind, List *content, int location) |
790 | { |
791 | GroupingSet *n = makeNode(GroupingSet); |
792 | |
793 | n->kind = kind; |
794 | n->content = content; |
795 | n->location = location; |
796 | return n; |
797 | } |
798 | |
799 | /* |
800 | * makeVacuumRelation - |
801 | * create a VacuumRelation node |
802 | */ |
803 | VacuumRelation * |
804 | makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols) |
805 | { |
806 | VacuumRelation *v = makeNode(VacuumRelation); |
807 | |
808 | v->relation = relation; |
809 | v->oid = oid; |
810 | v->va_cols = va_cols; |
811 | return v; |
812 | } |
813 | |