Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * parse_target.c
4 : * handle target lists
5 : *
6 : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/parser/parse_target.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "catalog/namespace.h"
18 : #include "catalog/pg_type.h"
19 : #include "funcapi.h"
20 : #include "miscadmin.h"
21 : #include "nodes/makefuncs.h"
22 : #include "nodes/nodeFuncs.h"
23 : #include "parser/parse_coerce.h"
24 : #include "parser/parse_expr.h"
25 : #include "parser/parse_relation.h"
26 : #include "parser/parse_target.h"
27 : #include "parser/parse_type.h"
28 : #include "parser/parsetree.h"
29 : #include "utils/builtins.h"
30 : #include "utils/lsyscache.h"
31 : #include "utils/rel.h"
32 :
33 : static void markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
34 : Var *var, int levelsup);
35 : static Node *transformAssignmentSubscripts(ParseState *pstate,
36 : Node *basenode,
37 : const char *targetName,
38 : Oid targetTypeId,
39 : int32 targetTypMod,
40 : Oid targetCollation,
41 : List *subscripts,
42 : List *indirection,
43 : ListCell *next_indirection,
44 : Node *rhs,
45 : CoercionContext ccontext,
46 : int location);
47 : static List *ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
48 : bool make_target_entry);
49 : static List *ExpandAllTables(ParseState *pstate, int location);
50 : static List *ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind,
51 : bool make_target_entry, ParseExprKind exprKind);
52 : static List *ExpandSingleTable(ParseState *pstate, ParseNamespaceItem *nsitem,
53 : int sublevels_up, int location,
54 : bool make_target_entry);
55 : static List *ExpandRowReference(ParseState *pstate, Node *expr,
56 : bool make_target_entry);
57 : static int FigureColnameInternal(Node *node, char **name);
58 :
59 :
60 : /*
61 : * transformTargetEntry()
62 : * Transform any ordinary "expression-type" node into a targetlist entry.
63 : * This is exported so that parse_clause.c can generate targetlist entries
64 : * for ORDER/GROUP BY items that are not already in the targetlist.
65 : *
66 : * node the (untransformed) parse tree for the value expression.
67 : * expr the transformed expression, or NULL if caller didn't do it yet.
68 : * exprKind expression kind (EXPR_KIND_SELECT_TARGET, etc)
69 : * colname the column name to be assigned, or NULL if none yet set.
70 : * resjunk true if the target should be marked resjunk, ie, it is not
71 : * wanted in the final projected tuple.
72 : */
73 : TargetEntry *
74 1114254 : transformTargetEntry(ParseState *pstate,
75 : Node *node,
76 : Node *expr,
77 : ParseExprKind exprKind,
78 : char *colname,
79 : bool resjunk)
80 : {
81 : /* Transform the node if caller didn't do it already */
82 1114254 : if (expr == NULL)
83 : {
84 : /*
85 : * If it's a SetToDefault node and we should allow that, pass it
86 : * through unmodified. (transformExpr will throw the appropriate
87 : * error if we're disallowing it.)
88 : */
89 1087246 : if (exprKind == EXPR_KIND_UPDATE_SOURCE && IsA(node, SetToDefault))
90 176 : expr = node;
91 : else
92 1087070 : expr = transformExpr(pstate, node, exprKind);
93 : }
94 :
95 1109364 : if (colname == NULL && !resjunk)
96 : {
97 : /*
98 : * Generate a suitable column name for a column without any explicit
99 : * 'AS ColumnName' clause.
100 : */
101 824796 : colname = FigureColname(node);
102 : }
103 :
104 2218728 : return makeTargetEntry((Expr *) expr,
105 1109364 : (AttrNumber) pstate->p_next_resno++,
106 : colname,
107 : resjunk);
108 : }
109 :
110 :
111 : /*
112 : * transformTargetList()
113 : * Turns a list of ResTarget's into a list of TargetEntry's.
114 : *
115 : * This code acts mostly the same for SELECT, UPDATE, or RETURNING lists;
116 : * the main thing is to transform the given expressions (the "val" fields).
117 : * The exprKind parameter distinguishes these cases when necessary.
118 : */
119 : List *
120 475334 : transformTargetList(ParseState *pstate, List *targetlist,
121 : ParseExprKind exprKind)
122 : {
123 475334 : List *p_target = NIL;
124 : bool expand_star;
125 : ListCell *o_target;
126 :
127 : /* Shouldn't have any leftover multiassign items at start */
128 : Assert(pstate->p_multiassign_exprs == NIL);
129 :
130 : /* Expand "something.*" in SELECT and RETURNING, but not UPDATE */
131 475334 : expand_star = (exprKind != EXPR_KIND_UPDATE_SOURCE);
132 :
133 1618530 : foreach(o_target, targetlist)
134 : {
135 1148092 : ResTarget *res = (ResTarget *) lfirst(o_target);
136 :
137 : /*
138 : * Check for "something.*". Depending on the complexity of the
139 : * "something", the star could appear as the last field in ColumnRef,
140 : * or as the last indirection item in A_Indirection.
141 : */
142 1148092 : if (expand_star)
143 : {
144 1127316 : if (IsA(res->val, ColumnRef))
145 : {
146 631140 : ColumnRef *cref = (ColumnRef *) res->val;
147 :
148 631140 : if (IsA(llast(cref->fields), A_Star))
149 : {
150 : /* It is something.*, expand into multiple items */
151 59382 : p_target = list_concat(p_target,
152 59388 : ExpandColumnRefStar(pstate,
153 : cref,
154 : true));
155 59382 : continue;
156 : }
157 : }
158 496176 : else if (IsA(res->val, A_Indirection))
159 : {
160 3676 : A_Indirection *ind = (A_Indirection *) res->val;
161 :
162 3676 : if (IsA(llast(ind->indirection), A_Star))
163 : {
164 : /* It is something.*, expand into multiple items */
165 1458 : p_target = list_concat(p_target,
166 1458 : ExpandIndirectionStar(pstate,
167 : ind,
168 : true,
169 : exprKind));
170 1458 : continue;
171 : }
172 : }
173 : }
174 :
175 : /*
176 : * Not "something.*", or we want to treat that as a plain whole-row
177 : * variable, so transform as a single expression
178 : */
179 1082356 : p_target = lappend(p_target,
180 1087246 : transformTargetEntry(pstate,
181 : res->val,
182 : NULL,
183 : exprKind,
184 : res->name,
185 : false));
186 : }
187 :
188 : /*
189 : * If any multiassign resjunk items were created, attach them to the end
190 : * of the targetlist. This should only happen in an UPDATE tlist. We
191 : * don't need to worry about numbering of these items; transformUpdateStmt
192 : * will set their resnos.
193 : */
194 470438 : if (pstate->p_multiassign_exprs)
195 : {
196 : Assert(exprKind == EXPR_KIND_UPDATE_SOURCE);
197 138 : p_target = list_concat(p_target, pstate->p_multiassign_exprs);
198 138 : pstate->p_multiassign_exprs = NIL;
199 : }
200 :
201 470438 : return p_target;
202 : }
203 :
204 :
205 : /*
206 : * transformExpressionList()
207 : *
208 : * This is the identical transformation to transformTargetList, except that
209 : * the input list elements are bare expressions without ResTarget decoration,
210 : * and the output elements are likewise just expressions without TargetEntry
211 : * decoration. Also, we don't expect any multiassign constructs within the
212 : * list, so there's nothing to do for that. We use this for ROW() and
213 : * VALUES() constructs.
214 : *
215 : * exprKind is not enough to tell us whether to allow SetToDefault, so
216 : * an additional flag is needed for that.
217 : */
218 : List *
219 90362 : transformExpressionList(ParseState *pstate, List *exprlist,
220 : ParseExprKind exprKind, bool allowDefault)
221 : {
222 90362 : List *result = NIL;
223 : ListCell *lc;
224 :
225 268806 : foreach(lc, exprlist)
226 : {
227 178488 : Node *e = (Node *) lfirst(lc);
228 :
229 : /*
230 : * Check for "something.*". Depending on the complexity of the
231 : * "something", the star could appear as the last field in ColumnRef,
232 : * or as the last indirection item in A_Indirection.
233 : */
234 178488 : if (IsA(e, ColumnRef))
235 : {
236 8618 : ColumnRef *cref = (ColumnRef *) e;
237 :
238 8618 : if (IsA(llast(cref->fields), A_Star))
239 : {
240 : /* It is something.*, expand into multiple items */
241 312 : result = list_concat(result,
242 312 : ExpandColumnRefStar(pstate, cref,
243 : false));
244 312 : continue;
245 : }
246 : }
247 169870 : else if (IsA(e, A_Indirection))
248 : {
249 24 : A_Indirection *ind = (A_Indirection *) e;
250 :
251 24 : if (IsA(llast(ind->indirection), A_Star))
252 : {
253 : /* It is something.*, expand into multiple items */
254 0 : result = list_concat(result,
255 0 : ExpandIndirectionStar(pstate, ind,
256 : false, exprKind));
257 0 : continue;
258 : }
259 : }
260 :
261 : /*
262 : * Not "something.*", so transform as a single expression. If it's a
263 : * SetToDefault node and we should allow that, pass it through
264 : * unmodified. (transformExpr will throw the appropriate error if
265 : * we're disallowing it.)
266 : */
267 178176 : if (allowDefault && IsA(e, SetToDefault))
268 : /* do nothing */ ;
269 : else
270 176852 : e = transformExpr(pstate, e, exprKind);
271 :
272 178132 : result = lappend(result, e);
273 : }
274 :
275 90318 : return result;
276 : }
277 :
278 :
279 : /*
280 : * resolveTargetListUnknowns()
281 : * Convert any unknown-type targetlist entries to type TEXT.
282 : *
283 : * We do this after we've exhausted all other ways of identifying the output
284 : * column types of a query.
285 : */
286 : void
287 417596 : resolveTargetListUnknowns(ParseState *pstate, List *targetlist)
288 : {
289 : ListCell *l;
290 :
291 1604982 : foreach(l, targetlist)
292 : {
293 1187386 : TargetEntry *tle = (TargetEntry *) lfirst(l);
294 1187386 : Oid restype = exprType((Node *) tle->expr);
295 :
296 1187386 : if (restype == UNKNOWNOID)
297 : {
298 8154 : tle->expr = (Expr *) coerce_type(pstate, (Node *) tle->expr,
299 : restype, TEXTOID, -1,
300 : COERCION_IMPLICIT,
301 : COERCE_IMPLICIT_CAST,
302 : -1);
303 : }
304 : }
305 417596 : }
306 :
307 :
308 : /*
309 : * markTargetListOrigins()
310 : * Mark targetlist columns that are simple Vars with the source
311 : * table's OID and column number.
312 : *
313 : * Currently, this is done only for SELECT targetlists and RETURNING lists,
314 : * since we only need the info if we are going to send it to the frontend.
315 : */
316 : void
317 448522 : markTargetListOrigins(ParseState *pstate, List *targetlist)
318 : {
319 : ListCell *l;
320 :
321 1711580 : foreach(l, targetlist)
322 : {
323 1263058 : TargetEntry *tle = (TargetEntry *) lfirst(l);
324 :
325 1263058 : markTargetListOrigin(pstate, tle, (Var *) tle->expr, 0);
326 : }
327 448522 : }
328 :
329 : /*
330 : * markTargetListOrigin()
331 : * If 'var' is a Var of a plain relation, mark 'tle' with its origin
332 : *
333 : * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
334 : *
335 : * Note that we do not drill down into views, but report the view as the
336 : * column owner. There's also no need to drill down into joins: if we see
337 : * a join alias Var, it must be a merged JOIN USING column (or possibly a
338 : * whole-row Var); that is not a direct reference to any plain table column,
339 : * so we don't report it.
340 : */
341 : static void
342 1263058 : markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
343 : Var *var, int levelsup)
344 : {
345 : int netlevelsup;
346 : RangeTblEntry *rte;
347 : AttrNumber attnum;
348 :
349 1263058 : if (var == NULL || !IsA(var, Var))
350 500348 : return;
351 762710 : netlevelsup = var->varlevelsup + levelsup;
352 762710 : rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup);
353 762710 : attnum = var->varattno;
354 :
355 762710 : switch (rte->rtekind)
356 : {
357 635804 : case RTE_RELATION:
358 : /* It's a table or view, report it */
359 635804 : tle->resorigtbl = rte->relid;
360 635804 : tle->resorigcol = attnum;
361 635804 : break;
362 16072 : case RTE_SUBQUERY:
363 : /* Subselect-in-FROM: copy up from the subselect */
364 16072 : if (attnum != InvalidAttrNumber)
365 : {
366 16012 : TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
367 : attnum);
368 :
369 16012 : if (ste == NULL || ste->resjunk)
370 0 : elog(ERROR, "subquery %s does not have attribute %d",
371 : rte->eref->aliasname, attnum);
372 16012 : tle->resorigtbl = ste->resorigtbl;
373 16012 : tle->resorigcol = ste->resorigcol;
374 : }
375 16072 : break;
376 101626 : case RTE_JOIN:
377 : case RTE_FUNCTION:
378 : case RTE_VALUES:
379 : case RTE_TABLEFUNC:
380 : case RTE_NAMEDTUPLESTORE:
381 : case RTE_RESULT:
382 : /* not a simple relation, leave it unmarked */
383 101626 : break;
384 9208 : case RTE_CTE:
385 :
386 : /*
387 : * CTE reference: copy up from the subquery, if possible. If the
388 : * RTE is a recursive self-reference then we can't do anything
389 : * because we haven't finished analyzing it yet. However, it's no
390 : * big loss because we must be down inside the recursive term of a
391 : * recursive CTE, and so any markings on the current targetlist
392 : * are not going to affect the results anyway.
393 : */
394 9208 : if (attnum != InvalidAttrNumber && !rte->self_reference)
395 : {
396 8602 : CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup);
397 : TargetEntry *ste;
398 8602 : List *tl = GetCTETargetList(cte);
399 8602 : int extra_cols = 0;
400 :
401 : /*
402 : * RTE for CTE will already have the search and cycle columns
403 : * added, but the subquery won't, so skip looking those up.
404 : */
405 8602 : if (cte->search_clause)
406 294 : extra_cols += 1;
407 8602 : if (cte->cycle_clause)
408 288 : extra_cols += 2;
409 9112 : if (extra_cols &&
410 510 : attnum > list_length(tl) &&
411 186 : attnum <= list_length(tl) + extra_cols)
412 186 : break;
413 :
414 8416 : ste = get_tle_by_resno(tl, attnum);
415 8416 : if (ste == NULL || ste->resjunk)
416 0 : elog(ERROR, "CTE %s does not have attribute %d",
417 : rte->eref->aliasname, attnum);
418 8416 : tle->resorigtbl = ste->resorigtbl;
419 8416 : tle->resorigcol = ste->resorigcol;
420 : }
421 9022 : break;
422 0 : case RTE_GROUP:
423 : /* We couldn't get here: the RTE_GROUP RTE has not been added */
424 0 : break;
425 : }
426 : }
427 :
428 :
429 : /*
430 : * transformAssignedExpr()
431 : * This is used in INSERT and UPDATE statements only. It prepares an
432 : * expression for assignment to a column of the target table.
433 : * This includes coercing the given value to the target column's type
434 : * (if necessary), and dealing with any subfield names or subscripts
435 : * attached to the target column itself. The input expression has
436 : * already been through transformExpr().
437 : *
438 : * pstate parse state
439 : * expr expression to be modified
440 : * exprKind indicates which type of statement we're dealing with
441 : * colname target column name (ie, name of attribute to be assigned to)
442 : * attrno target attribute number
443 : * indirection subscripts/field names for target column, if any
444 : * location error cursor position for the target column, or -1
445 : *
446 : * Returns the modified expression.
447 : *
448 : * Note: location points at the target column name (SET target or INSERT
449 : * column name list entry), and must therefore be -1 in an INSERT that
450 : * omits the column name list. So we should usually prefer to use
451 : * exprLocation(expr) for errors that can happen in a default INSERT.
452 : */
453 : Expr *
454 179526 : transformAssignedExpr(ParseState *pstate,
455 : Expr *expr,
456 : ParseExprKind exprKind,
457 : const char *colname,
458 : int attrno,
459 : List *indirection,
460 : int location)
461 : {
462 179526 : Relation rd = pstate->p_target_relation;
463 : Oid type_id; /* type of value provided */
464 : Oid attrtype; /* type of target column */
465 : int32 attrtypmod;
466 : Oid attrcollation; /* collation of target column */
467 : ParseExprKind sv_expr_kind;
468 :
469 : /*
470 : * Save and restore identity of expression type we're parsing. We must
471 : * set p_expr_kind here because we can parse subscripts without going
472 : * through transformExpr().
473 : */
474 : Assert(exprKind != EXPR_KIND_NONE);
475 179526 : sv_expr_kind = pstate->p_expr_kind;
476 179526 : pstate->p_expr_kind = exprKind;
477 :
478 : Assert(rd != NULL);
479 179526 : if (attrno <= 0)
480 0 : ereport(ERROR,
481 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
482 : errmsg("cannot assign to system column \"%s\"",
483 : colname),
484 : parser_errposition(pstate, location)));
485 179526 : attrtype = attnumTypeId(rd, attrno);
486 179526 : attrtypmod = TupleDescAttr(rd->rd_att, attrno - 1)->atttypmod;
487 179526 : attrcollation = TupleDescAttr(rd->rd_att, attrno - 1)->attcollation;
488 :
489 : /*
490 : * If the expression is a DEFAULT placeholder, insert the attribute's
491 : * type/typmod/collation into it so that exprType etc will report the
492 : * right things. (We expect that the eventually substituted default
493 : * expression will in fact have this type and typmod. The collation
494 : * likely doesn't matter, but let's set it correctly anyway.) Also,
495 : * reject trying to update a subfield or array element with DEFAULT, since
496 : * there can't be any default for portions of a column.
497 : */
498 179526 : if (expr && IsA(expr, SetToDefault))
499 : {
500 1470 : SetToDefault *def = (SetToDefault *) expr;
501 :
502 1470 : def->typeId = attrtype;
503 1470 : def->typeMod = attrtypmod;
504 1470 : def->collation = attrcollation;
505 1470 : if (indirection)
506 : {
507 24 : if (IsA(linitial(indirection), A_Indices))
508 12 : ereport(ERROR,
509 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
510 : errmsg("cannot set an array element to DEFAULT"),
511 : parser_errposition(pstate, location)));
512 : else
513 12 : ereport(ERROR,
514 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
515 : errmsg("cannot set a subfield to DEFAULT"),
516 : parser_errposition(pstate, location)));
517 : }
518 : }
519 :
520 : /* Now we can use exprType() safely. */
521 179502 : type_id = exprType((Node *) expr);
522 :
523 : /*
524 : * If there is indirection on the target column, prepare an array or
525 : * subfield assignment expression. This will generate a new column value
526 : * that the source value has been inserted into, which can then be placed
527 : * in the new tuple constructed by INSERT or UPDATE.
528 : */
529 179502 : if (indirection)
530 : {
531 : Node *colVar;
532 :
533 1842 : if (pstate->p_is_insert)
534 : {
535 : /*
536 : * The command is INSERT INTO table (col.something) ... so there
537 : * is not really a source value to work with. Insert a NULL
538 : * constant as the source value.
539 : */
540 1050 : colVar = (Node *) makeNullConst(attrtype, attrtypmod,
541 : attrcollation);
542 : }
543 : else
544 : {
545 : /*
546 : * Build a Var for the column to be updated.
547 : */
548 : Var *var;
549 :
550 792 : var = makeVar(pstate->p_target_nsitem->p_rtindex, attrno,
551 : attrtype, attrtypmod, attrcollation, 0);
552 792 : var->location = location;
553 :
554 792 : colVar = (Node *) var;
555 : }
556 :
557 : expr = (Expr *)
558 1842 : transformAssignmentIndirection(pstate,
559 : colVar,
560 : colname,
561 : false,
562 : attrtype,
563 : attrtypmod,
564 : attrcollation,
565 : indirection,
566 : list_head(indirection),
567 : (Node *) expr,
568 : COERCION_ASSIGNMENT,
569 : location);
570 : }
571 : else
572 : {
573 : /*
574 : * For normal non-qualified target column, do type checking and
575 : * coercion.
576 : */
577 177660 : Node *orig_expr = (Node *) expr;
578 :
579 : expr = (Expr *)
580 177660 : coerce_to_target_type(pstate,
581 : orig_expr, type_id,
582 : attrtype, attrtypmod,
583 : COERCION_ASSIGNMENT,
584 : COERCE_IMPLICIT_CAST,
585 : -1);
586 176640 : if (expr == NULL)
587 142 : ereport(ERROR,
588 : (errcode(ERRCODE_DATATYPE_MISMATCH),
589 : errmsg("column \"%s\" is of type %s"
590 : " but expression is of type %s",
591 : colname,
592 : format_type_be(attrtype),
593 : format_type_be(type_id)),
594 : errhint("You will need to rewrite or cast the expression."),
595 : parser_errposition(pstate, exprLocation(orig_expr))));
596 : }
597 :
598 178322 : pstate->p_expr_kind = sv_expr_kind;
599 :
600 178322 : return expr;
601 : }
602 :
603 :
604 : /*
605 : * updateTargetListEntry()
606 : * This is used in UPDATE statements (and ON CONFLICT DO UPDATE)
607 : * only. It prepares an UPDATE TargetEntry for assignment to a
608 : * column of the target table. This includes coercing the given
609 : * value to the target column's type (if necessary), and dealing with
610 : * any subfield names or subscripts attached to the target column
611 : * itself.
612 : *
613 : * pstate parse state
614 : * tle target list entry to be modified
615 : * colname target column name (ie, name of attribute to be assigned to)
616 : * attrno target attribute number
617 : * indirection subscripts/field names for target column, if any
618 : * location error cursor position (should point at column name), or -1
619 : */
620 : void
621 20704 : updateTargetListEntry(ParseState *pstate,
622 : TargetEntry *tle,
623 : char *colname,
624 : int attrno,
625 : List *indirection,
626 : int location)
627 : {
628 : /* Fix up expression as needed */
629 20704 : tle->expr = transformAssignedExpr(pstate,
630 : tle->expr,
631 : EXPR_KIND_UPDATE_TARGET,
632 : colname,
633 : attrno,
634 : indirection,
635 : location);
636 :
637 : /*
638 : * Set the resno to identify the target column --- the rewriter and
639 : * planner depend on this. We also set the resname to identify the target
640 : * column, but this is only for debugging purposes; it should not be
641 : * relied on. (In particular, it might be out of date in a stored rule.)
642 : */
643 20692 : tle->resno = (AttrNumber) attrno;
644 20692 : tle->resname = colname;
645 20692 : }
646 :
647 :
648 : /*
649 : * Process indirection (field selection or subscripting) of the target
650 : * column in INSERT/UPDATE/assignment. This routine recurses for multiple
651 : * levels of indirection --- but note that several adjacent A_Indices nodes
652 : * in the indirection list are treated as a single multidimensional subscript
653 : * operation.
654 : *
655 : * In the initial call, basenode is a Var for the target column in UPDATE,
656 : * or a null Const of the target's type in INSERT, or a Param for the target
657 : * variable in PL/pgSQL assignment. In recursive calls, basenode is NULL,
658 : * indicating that a substitute node should be consed up if needed.
659 : *
660 : * targetName is the name of the field or subfield we're assigning to, and
661 : * targetIsSubscripting is true if we're subscripting it. These are just for
662 : * error reporting.
663 : *
664 : * targetTypeId, targetTypMod, targetCollation indicate the datatype and
665 : * collation of the object to be assigned to (initially the target column,
666 : * later some subobject).
667 : *
668 : * indirection is the list of indirection nodes, and indirection_cell is the
669 : * start of the sublist remaining to process. When it's NULL, we're done
670 : * recursing and can just coerce and return the RHS.
671 : *
672 : * rhs is the already-transformed value to be assigned; note it has not been
673 : * coerced to any particular type.
674 : *
675 : * ccontext is the coercion level to use while coercing the rhs. For
676 : * normal statements it'll be COERCION_ASSIGNMENT, but PL/pgSQL uses
677 : * a special value.
678 : *
679 : * location is the cursor error position for any errors. (Note: this points
680 : * to the head of the target clause, eg "foo" in "foo.bar[baz]". Later we
681 : * might want to decorate indirection cells with their own location info,
682 : * in which case the location argument could probably be dropped.)
683 : */
684 : Node *
685 4564 : transformAssignmentIndirection(ParseState *pstate,
686 : Node *basenode,
687 : const char *targetName,
688 : bool targetIsSubscripting,
689 : Oid targetTypeId,
690 : int32 targetTypMod,
691 : Oid targetCollation,
692 : List *indirection,
693 : ListCell *indirection_cell,
694 : Node *rhs,
695 : CoercionContext ccontext,
696 : int location)
697 : {
698 : Node *result;
699 4564 : List *subscripts = NIL;
700 : ListCell *i;
701 :
702 4564 : if (indirection_cell && !basenode)
703 : {
704 : /*
705 : * Set up a substitution. We abuse CaseTestExpr for this. It's safe
706 : * to do so because the only nodes that will be above the CaseTestExpr
707 : * in the finished expression will be FieldStore and SubscriptingRef
708 : * nodes. (There could be other stuff in the tree, but it will be
709 : * within other child fields of those node types.)
710 : */
711 674 : CaseTestExpr *ctest = makeNode(CaseTestExpr);
712 :
713 674 : ctest->typeId = targetTypeId;
714 674 : ctest->typeMod = targetTypMod;
715 674 : ctest->collation = targetCollation;
716 674 : basenode = (Node *) ctest;
717 : }
718 :
719 : /*
720 : * We have to split any field-selection operations apart from
721 : * subscripting. Adjacent A_Indices nodes have to be treated as a single
722 : * multidimensional subscript operation.
723 : */
724 6652 : for_each_cell(i, indirection, indirection_cell)
725 : {
726 3276 : Node *n = lfirst(i);
727 :
728 3276 : if (IsA(n, A_Indices))
729 2088 : subscripts = lappend(subscripts, n);
730 1188 : else if (IsA(n, A_Star))
731 : {
732 0 : ereport(ERROR,
733 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
734 : errmsg("row expansion via \"*\" is not supported here"),
735 : parser_errposition(pstate, location)));
736 : }
737 : else
738 : {
739 : FieldStore *fstore;
740 : Oid baseTypeId;
741 : int32 baseTypeMod;
742 : Oid typrelid;
743 : AttrNumber attnum;
744 : Oid fieldTypeId;
745 : int32 fieldTypMod;
746 : Oid fieldCollation;
747 :
748 : Assert(IsA(n, String));
749 :
750 : /* process subscripts before this field selection */
751 1188 : if (subscripts)
752 : {
753 : /* recurse, and then return because we're done */
754 344 : return transformAssignmentSubscripts(pstate,
755 : basenode,
756 : targetName,
757 : targetTypeId,
758 : targetTypMod,
759 : targetCollation,
760 : subscripts,
761 : indirection,
762 : i,
763 : rhs,
764 : ccontext,
765 : location);
766 : }
767 :
768 : /* No subscripts, so can process field selection here */
769 :
770 : /*
771 : * Look up the composite type, accounting for possibility that
772 : * what we are given is a domain over composite.
773 : */
774 844 : baseTypeMod = targetTypMod;
775 844 : baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
776 :
777 844 : typrelid = typeidTypeRelid(baseTypeId);
778 844 : if (!typrelid)
779 2 : ereport(ERROR,
780 : (errcode(ERRCODE_DATATYPE_MISMATCH),
781 : errmsg("cannot assign to field \"%s\" of column \"%s\" because its type %s is not a composite type",
782 : strVal(n), targetName,
783 : format_type_be(targetTypeId)),
784 : parser_errposition(pstate, location)));
785 :
786 842 : attnum = get_attnum(typrelid, strVal(n));
787 842 : if (attnum == InvalidAttrNumber)
788 4 : ereport(ERROR,
789 : (errcode(ERRCODE_UNDEFINED_COLUMN),
790 : errmsg("cannot assign to field \"%s\" of column \"%s\" because there is no such column in data type %s",
791 : strVal(n), targetName,
792 : format_type_be(targetTypeId)),
793 : parser_errposition(pstate, location)));
794 838 : if (attnum < 0)
795 0 : ereport(ERROR,
796 : (errcode(ERRCODE_UNDEFINED_COLUMN),
797 : errmsg("cannot assign to system column \"%s\"",
798 : strVal(n)),
799 : parser_errposition(pstate, location)));
800 :
801 838 : get_atttypetypmodcoll(typrelid, attnum,
802 : &fieldTypeId, &fieldTypMod, &fieldCollation);
803 :
804 : /* recurse to create appropriate RHS for field assign */
805 838 : rhs = transformAssignmentIndirection(pstate,
806 : NULL,
807 838 : strVal(n),
808 : false,
809 : fieldTypeId,
810 : fieldTypMod,
811 : fieldCollation,
812 : indirection,
813 : lnext(indirection, i),
814 : rhs,
815 : ccontext,
816 : location);
817 :
818 : /* and build a FieldStore node */
819 832 : fstore = makeNode(FieldStore);
820 832 : fstore->arg = (Expr *) basenode;
821 832 : fstore->newvals = list_make1(rhs);
822 832 : fstore->fieldnums = list_make1_int(attnum);
823 832 : fstore->resulttype = baseTypeId;
824 :
825 : /*
826 : * If target is a domain, apply constraints. Notice that this
827 : * isn't totally right: the expression tree we build would check
828 : * the domain's constraints on a composite value with only this
829 : * one field populated or updated, possibly leading to an unwanted
830 : * failure. The rewriter will merge together any subfield
831 : * assignments to the same table column, resulting in the domain's
832 : * constraints being checked only once after we've assigned to all
833 : * the fields that the INSERT or UPDATE means to.
834 : */
835 832 : if (baseTypeId != targetTypeId)
836 432 : return coerce_to_domain((Node *) fstore,
837 : baseTypeId, baseTypeMod,
838 : targetTypeId,
839 : COERCION_IMPLICIT,
840 : COERCE_IMPLICIT_CAST,
841 : location,
842 : false);
843 :
844 400 : return (Node *) fstore;
845 : }
846 : }
847 :
848 : /* process trailing subscripts, if any */
849 3376 : if (subscripts)
850 : {
851 : /* recurse, and then return because we're done */
852 1436 : return transformAssignmentSubscripts(pstate,
853 : basenode,
854 : targetName,
855 : targetTypeId,
856 : targetTypMod,
857 : targetCollation,
858 : subscripts,
859 : indirection,
860 : NULL,
861 : rhs,
862 : ccontext,
863 : location);
864 : }
865 :
866 : /* base case: just coerce RHS to match target type ID */
867 :
868 1940 : result = coerce_to_target_type(pstate,
869 : rhs, exprType(rhs),
870 : targetTypeId, targetTypMod,
871 : ccontext,
872 : COERCE_IMPLICIT_CAST,
873 : -1);
874 1940 : if (result == NULL)
875 : {
876 18 : if (targetIsSubscripting)
877 12 : ereport(ERROR,
878 : (errcode(ERRCODE_DATATYPE_MISMATCH),
879 : errmsg("subscripted assignment to \"%s\" requires type %s"
880 : " but expression is of type %s",
881 : targetName,
882 : format_type_be(targetTypeId),
883 : format_type_be(exprType(rhs))),
884 : errhint("You will need to rewrite or cast the expression."),
885 : parser_errposition(pstate, location)));
886 : else
887 6 : ereport(ERROR,
888 : (errcode(ERRCODE_DATATYPE_MISMATCH),
889 : errmsg("subfield \"%s\" is of type %s"
890 : " but expression is of type %s",
891 : targetName,
892 : format_type_be(targetTypeId),
893 : format_type_be(exprType(rhs))),
894 : errhint("You will need to rewrite or cast the expression."),
895 : parser_errposition(pstate, location)));
896 : }
897 :
898 1922 : return result;
899 : }
900 :
901 : /*
902 : * helper for transformAssignmentIndirection: process container assignment
903 : */
904 : static Node *
905 1780 : transformAssignmentSubscripts(ParseState *pstate,
906 : Node *basenode,
907 : const char *targetName,
908 : Oid targetTypeId,
909 : int32 targetTypMod,
910 : Oid targetCollation,
911 : List *subscripts,
912 : List *indirection,
913 : ListCell *next_indirection,
914 : Node *rhs,
915 : CoercionContext ccontext,
916 : int location)
917 : {
918 : Node *result;
919 : SubscriptingRef *sbsref;
920 : Oid containerType;
921 : int32 containerTypMod;
922 : Oid typeNeeded;
923 : int32 typmodNeeded;
924 : Oid collationNeeded;
925 :
926 : Assert(subscripts != NIL);
927 :
928 : /* Identify the actual container type involved */
929 1780 : containerType = targetTypeId;
930 1780 : containerTypMod = targetTypMod;
931 1780 : transformContainerType(&containerType, &containerTypMod);
932 :
933 : /* Process subscripts and identify required type for RHS */
934 1780 : sbsref = transformContainerSubscripts(pstate,
935 : basenode,
936 : containerType,
937 : containerTypMod,
938 : subscripts,
939 : true);
940 :
941 1776 : typeNeeded = sbsref->refrestype;
942 1776 : typmodNeeded = sbsref->reftypmod;
943 :
944 : /*
945 : * Container normally has same collation as its elements, but there's an
946 : * exception: we might be subscripting a domain over a container type. In
947 : * that case use collation of the base type. (This is shaky for arbitrary
948 : * subscripting semantics, but it doesn't matter all that much since we
949 : * only use this to label the collation of a possible CaseTestExpr.)
950 : */
951 1776 : if (containerType == targetTypeId)
952 1474 : collationNeeded = targetCollation;
953 : else
954 302 : collationNeeded = get_typcollation(containerType);
955 :
956 : /* recurse to create appropriate RHS for container assign */
957 1776 : rhs = transformAssignmentIndirection(pstate,
958 : NULL,
959 : targetName,
960 : true,
961 : typeNeeded,
962 : typmodNeeded,
963 : collationNeeded,
964 : indirection,
965 : next_indirection,
966 : rhs,
967 : ccontext,
968 : location);
969 :
970 : /*
971 : * Insert the already-properly-coerced RHS into the SubscriptingRef. Then
972 : * set refrestype and reftypmod back to the container type's values.
973 : */
974 1762 : sbsref->refassgnexpr = (Expr *) rhs;
975 1762 : sbsref->refrestype = containerType;
976 1762 : sbsref->reftypmod = containerTypMod;
977 :
978 1762 : result = (Node *) sbsref;
979 :
980 : /*
981 : * If target was a domain over container, need to coerce up to the domain.
982 : * As in transformAssignmentIndirection, this coercion is premature if the
983 : * query assigns to multiple elements of the container; but we'll fix that
984 : * during query rewrite.
985 : */
986 1762 : if (containerType != targetTypeId)
987 : {
988 302 : Oid resulttype = exprType(result);
989 :
990 302 : result = coerce_to_target_type(pstate,
991 : result, resulttype,
992 : targetTypeId, targetTypMod,
993 : ccontext,
994 : COERCE_IMPLICIT_CAST,
995 : -1);
996 : /* can fail if we had int2vector/oidvector, but not for true domains */
997 302 : if (result == NULL)
998 0 : ereport(ERROR,
999 : (errcode(ERRCODE_CANNOT_COERCE),
1000 : errmsg("cannot cast type %s to %s",
1001 : format_type_be(resulttype),
1002 : format_type_be(targetTypeId)),
1003 : parser_errposition(pstate, location)));
1004 : }
1005 :
1006 1762 : return result;
1007 : }
1008 :
1009 :
1010 : /*
1011 : * checkInsertTargets -
1012 : * generate a list of INSERT column targets if not supplied, or
1013 : * test supplied column names to make sure they are in target table.
1014 : * Also return an integer list of the columns' attribute numbers.
1015 : */
1016 : List *
1017 69122 : checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
1018 : {
1019 69122 : *attrnos = NIL;
1020 :
1021 69122 : if (cols == NIL)
1022 : {
1023 : /*
1024 : * Generate default column list for INSERT.
1025 : */
1026 54588 : int numcol = RelationGetNumberOfAttributes(pstate->p_target_relation);
1027 :
1028 : int i;
1029 :
1030 158232 : for (i = 0; i < numcol; i++)
1031 : {
1032 : ResTarget *col;
1033 : Form_pg_attribute attr;
1034 :
1035 103644 : attr = TupleDescAttr(pstate->p_target_relation->rd_att, i);
1036 :
1037 103644 : if (attr->attisdropped)
1038 276 : continue;
1039 :
1040 103368 : col = makeNode(ResTarget);
1041 103368 : col->name = pstrdup(NameStr(attr->attname));
1042 103368 : col->indirection = NIL;
1043 103368 : col->val = NULL;
1044 103368 : col->location = -1;
1045 103368 : cols = lappend(cols, col);
1046 103368 : *attrnos = lappend_int(*attrnos, i + 1);
1047 : }
1048 : }
1049 : else
1050 : {
1051 : /*
1052 : * Do initial validation of user-supplied INSERT column list.
1053 : */
1054 14534 : Bitmapset *wholecols = NULL;
1055 14534 : Bitmapset *partialcols = NULL;
1056 : ListCell *tl;
1057 :
1058 44980 : foreach(tl, cols)
1059 : {
1060 30494 : ResTarget *col = (ResTarget *) lfirst(tl);
1061 30494 : char *name = col->name;
1062 : int attrno;
1063 :
1064 : /* Lookup column name, ereport on failure */
1065 30494 : attrno = attnameAttNum(pstate->p_target_relation, name, false);
1066 30494 : if (attrno == InvalidAttrNumber)
1067 48 : ereport(ERROR,
1068 : (errcode(ERRCODE_UNDEFINED_COLUMN),
1069 : errmsg("column \"%s\" of relation \"%s\" does not exist",
1070 : name,
1071 : RelationGetRelationName(pstate->p_target_relation)),
1072 : parser_errposition(pstate, col->location)));
1073 :
1074 : /*
1075 : * Check for duplicates, but only of whole columns --- we allow
1076 : * INSERT INTO foo (col.subcol1, col.subcol2)
1077 : */
1078 30446 : if (col->indirection == NIL)
1079 : {
1080 : /* whole column; must not have any other assignment */
1081 59440 : if (bms_is_member(attrno, wholecols) ||
1082 29720 : bms_is_member(attrno, partialcols))
1083 0 : ereport(ERROR,
1084 : (errcode(ERRCODE_DUPLICATE_COLUMN),
1085 : errmsg("column \"%s\" specified more than once",
1086 : name),
1087 : parser_errposition(pstate, col->location)));
1088 29720 : wholecols = bms_add_member(wholecols, attrno);
1089 : }
1090 : else
1091 : {
1092 : /* partial column; must not have any whole assignment */
1093 726 : if (bms_is_member(attrno, wholecols))
1094 0 : ereport(ERROR,
1095 : (errcode(ERRCODE_DUPLICATE_COLUMN),
1096 : errmsg("column \"%s\" specified more than once",
1097 : name),
1098 : parser_errposition(pstate, col->location)));
1099 726 : partialcols = bms_add_member(partialcols, attrno);
1100 : }
1101 :
1102 30446 : *attrnos = lappend_int(*attrnos, attrno);
1103 : }
1104 : }
1105 :
1106 69074 : return cols;
1107 : }
1108 :
1109 : /*
1110 : * ExpandColumnRefStar()
1111 : * Transforms foo.* into a list of expressions or targetlist entries.
1112 : *
1113 : * This handles the case where '*' appears as the last or only item in a
1114 : * ColumnRef. The code is shared between the case of foo.* at the top level
1115 : * in a SELECT target list (where we want TargetEntry nodes in the result)
1116 : * and foo.* in a ROW() or VALUES() construct (where we want just bare
1117 : * expressions).
1118 : *
1119 : * The referenced columns are marked as requiring SELECT access.
1120 : */
1121 : static List *
1122 59700 : ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
1123 : bool make_target_entry)
1124 : {
1125 59700 : List *fields = cref->fields;
1126 59700 : int numnames = list_length(fields);
1127 :
1128 59700 : if (numnames == 1)
1129 : {
1130 : /*
1131 : * Target item is a bare '*', expand all tables
1132 : *
1133 : * (e.g., SELECT * FROM emp, dept)
1134 : *
1135 : * Since the grammar only accepts bare '*' at top level of SELECT, we
1136 : * need not handle the make_target_entry==false case here.
1137 : */
1138 : Assert(make_target_entry);
1139 55816 : return ExpandAllTables(pstate, cref->location);
1140 : }
1141 : else
1142 : {
1143 : /*
1144 : * Target item is relation.*, expand that table
1145 : *
1146 : * (e.g., SELECT emp.*, dname FROM emp, dept)
1147 : *
1148 : * Note: this code is a lot like transformColumnRef; it's tempting to
1149 : * call that instead and then replace the resulting whole-row Var with
1150 : * a list of Vars. However, that would leave us with the relation's
1151 : * selectedCols bitmap showing the whole row as needing select
1152 : * permission, as well as the individual columns. That would be
1153 : * incorrect (since columns added later shouldn't need select
1154 : * permissions). We could try to remove the whole-row permission bit
1155 : * after the fact, but duplicating code is less messy.
1156 : */
1157 3884 : char *nspname = NULL;
1158 3884 : char *relname = NULL;
1159 3884 : ParseNamespaceItem *nsitem = NULL;
1160 : int levels_up;
1161 : enum
1162 : {
1163 : CRSERR_NO_RTE,
1164 : CRSERR_WRONG_DB,
1165 : CRSERR_TOO_MANY
1166 3884 : } crserr = CRSERR_NO_RTE;
1167 :
1168 : /*
1169 : * Give the PreParseColumnRefHook, if any, first shot. If it returns
1170 : * non-null then we should use that expression.
1171 : */
1172 3884 : if (pstate->p_pre_columnref_hook != NULL)
1173 : {
1174 : Node *node;
1175 :
1176 64 : node = pstate->p_pre_columnref_hook(pstate, cref);
1177 64 : if (node != NULL)
1178 0 : return ExpandRowReference(pstate, node, make_target_entry);
1179 : }
1180 :
1181 3884 : switch (numnames)
1182 : {
1183 3884 : case 2:
1184 3884 : relname = strVal(linitial(fields));
1185 3884 : nsitem = refnameNamespaceItem(pstate, nspname, relname,
1186 : cref->location,
1187 : &levels_up);
1188 3884 : break;
1189 0 : case 3:
1190 0 : nspname = strVal(linitial(fields));
1191 0 : relname = strVal(lsecond(fields));
1192 0 : nsitem = refnameNamespaceItem(pstate, nspname, relname,
1193 : cref->location,
1194 : &levels_up);
1195 0 : break;
1196 0 : case 4:
1197 : {
1198 0 : char *catname = strVal(linitial(fields));
1199 :
1200 : /*
1201 : * We check the catalog name and then ignore it.
1202 : */
1203 0 : if (strcmp(catname, get_database_name(MyDatabaseId)) != 0)
1204 : {
1205 0 : crserr = CRSERR_WRONG_DB;
1206 0 : break;
1207 : }
1208 0 : nspname = strVal(lsecond(fields));
1209 0 : relname = strVal(lthird(fields));
1210 0 : nsitem = refnameNamespaceItem(pstate, nspname, relname,
1211 : cref->location,
1212 : &levels_up);
1213 0 : break;
1214 : }
1215 0 : default:
1216 0 : crserr = CRSERR_TOO_MANY;
1217 0 : break;
1218 : }
1219 :
1220 : /*
1221 : * Now give the PostParseColumnRefHook, if any, a chance. We cheat a
1222 : * bit by passing the RangeTblEntry, not a Var, as the planned
1223 : * translation. (A single Var wouldn't be strictly correct anyway.
1224 : * This convention allows hooks that really care to know what is
1225 : * happening. It might be better to pass the nsitem, but we'd have to
1226 : * promote that struct to a full-fledged Node type so that callees
1227 : * could identify its type.)
1228 : */
1229 3884 : if (pstate->p_post_columnref_hook != NULL)
1230 : {
1231 : Node *node;
1232 :
1233 178 : node = pstate->p_post_columnref_hook(pstate, cref,
1234 : (Node *) (nsitem ? nsitem->p_rte : NULL));
1235 178 : if (node != NULL)
1236 : {
1237 88 : if (nsitem != NULL)
1238 0 : ereport(ERROR,
1239 : (errcode(ERRCODE_AMBIGUOUS_COLUMN),
1240 : errmsg("column reference \"%s\" is ambiguous",
1241 : NameListToString(cref->fields)),
1242 : parser_errposition(pstate, cref->location)));
1243 88 : return ExpandRowReference(pstate, node, make_target_entry);
1244 : }
1245 : }
1246 :
1247 : /*
1248 : * Throw error if no translation found.
1249 : */
1250 3796 : if (nsitem == NULL)
1251 : {
1252 6 : switch (crserr)
1253 : {
1254 6 : case CRSERR_NO_RTE:
1255 6 : errorMissingRTE(pstate, makeRangeVar(nspname, relname,
1256 : cref->location));
1257 : break;
1258 0 : case CRSERR_WRONG_DB:
1259 0 : ereport(ERROR,
1260 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1261 : errmsg("cross-database references are not implemented: %s",
1262 : NameListToString(cref->fields)),
1263 : parser_errposition(pstate, cref->location)));
1264 : break;
1265 0 : case CRSERR_TOO_MANY:
1266 0 : ereport(ERROR,
1267 : (errcode(ERRCODE_SYNTAX_ERROR),
1268 : errmsg("improper qualified name (too many dotted names): %s",
1269 : NameListToString(cref->fields)),
1270 : parser_errposition(pstate, cref->location)));
1271 : break;
1272 : }
1273 : }
1274 :
1275 : /*
1276 : * OK, expand the nsitem into fields.
1277 : */
1278 3790 : return ExpandSingleTable(pstate, nsitem, levels_up, cref->location,
1279 : make_target_entry);
1280 : }
1281 : }
1282 :
1283 : /*
1284 : * ExpandAllTables()
1285 : * Transforms '*' (in the target list) into a list of targetlist entries.
1286 : *
1287 : * tlist entries are generated for each relation visible for unqualified
1288 : * column name access. We do not consider qualified-name-only entries because
1289 : * that would include input tables of aliasless JOINs, NEW/OLD pseudo-entries,
1290 : * etc.
1291 : *
1292 : * The referenced relations/columns are marked as requiring SELECT access.
1293 : */
1294 : static List *
1295 55816 : ExpandAllTables(ParseState *pstate, int location)
1296 : {
1297 55816 : List *target = NIL;
1298 55816 : bool found_table = false;
1299 : ListCell *l;
1300 :
1301 122194 : foreach(l, pstate->p_namespace)
1302 : {
1303 66378 : ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
1304 :
1305 : /* Ignore table-only items */
1306 66378 : if (!nsitem->p_cols_visible)
1307 9048 : continue;
1308 : /* Should not have any lateral-only items when parsing targetlist */
1309 : Assert(!nsitem->p_lateral_only);
1310 : /* Remember we found a p_cols_visible item */
1311 57330 : found_table = true;
1312 :
1313 57330 : target = list_concat(target,
1314 57330 : expandNSItemAttrs(pstate,
1315 : nsitem,
1316 : 0,
1317 : true,
1318 : location));
1319 : }
1320 :
1321 : /*
1322 : * Check for "SELECT *;". We do it this way, rather than checking for
1323 : * target == NIL, because we want to allow SELECT * FROM a zero_column
1324 : * table.
1325 : */
1326 55816 : if (!found_table)
1327 0 : ereport(ERROR,
1328 : (errcode(ERRCODE_SYNTAX_ERROR),
1329 : errmsg("SELECT * with no tables specified is not valid"),
1330 : parser_errposition(pstate, location)));
1331 :
1332 55816 : return target;
1333 : }
1334 :
1335 : /*
1336 : * ExpandIndirectionStar()
1337 : * Transforms foo.* into a list of expressions or targetlist entries.
1338 : *
1339 : * This handles the case where '*' appears as the last item in A_Indirection.
1340 : * The code is shared between the case of foo.* at the top level in a SELECT
1341 : * target list (where we want TargetEntry nodes in the result) and foo.* in
1342 : * a ROW() or VALUES() construct (where we want just bare expressions).
1343 : * For robustness, we use a separate "make_target_entry" flag to control
1344 : * this rather than relying on exprKind.
1345 : */
1346 : static List *
1347 1458 : ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind,
1348 : bool make_target_entry, ParseExprKind exprKind)
1349 : {
1350 : Node *expr;
1351 :
1352 : /* Strip off the '*' to create a reference to the rowtype object */
1353 1458 : ind = copyObject(ind);
1354 1458 : ind->indirection = list_truncate(ind->indirection,
1355 1458 : list_length(ind->indirection) - 1);
1356 :
1357 : /* And transform that */
1358 1458 : expr = transformExpr(pstate, (Node *) ind, exprKind);
1359 :
1360 : /* Expand the rowtype expression into individual fields */
1361 1458 : return ExpandRowReference(pstate, expr, make_target_entry);
1362 : }
1363 :
1364 : /*
1365 : * ExpandSingleTable()
1366 : * Transforms foo.* into a list of expressions or targetlist entries.
1367 : *
1368 : * This handles the case where foo has been determined to be a simple
1369 : * reference to an RTE, so we can just generate Vars for the expressions.
1370 : *
1371 : * The referenced columns are marked as requiring SELECT access.
1372 : */
1373 : static List *
1374 3790 : ExpandSingleTable(ParseState *pstate, ParseNamespaceItem *nsitem,
1375 : int sublevels_up, int location, bool make_target_entry)
1376 : {
1377 3790 : if (make_target_entry)
1378 : {
1379 : /* expandNSItemAttrs handles permissions marking */
1380 3564 : return expandNSItemAttrs(pstate, nsitem, sublevels_up, true, location);
1381 : }
1382 : else
1383 : {
1384 226 : RangeTblEntry *rte = nsitem->p_rte;
1385 226 : RTEPermissionInfo *perminfo = nsitem->p_perminfo;
1386 : List *vars;
1387 : ListCell *l;
1388 :
1389 226 : vars = expandNSItemVars(pstate, nsitem, sublevels_up, location, NULL);
1390 :
1391 : /*
1392 : * Require read access to the table. This is normally redundant with
1393 : * the markVarForSelectPriv calls below, but not if the table has zero
1394 : * columns. We need not do anything if the nsitem is for a join: its
1395 : * component tables will have been marked ACL_SELECT when they were
1396 : * added to the rangetable. (This step changes things only for the
1397 : * target relation of UPDATE/DELETE, which cannot be under a join.)
1398 : */
1399 226 : if (rte->rtekind == RTE_RELATION)
1400 : {
1401 : Assert(perminfo != NULL);
1402 134 : perminfo->requiredPerms |= ACL_SELECT;
1403 : }
1404 :
1405 : /* Require read access to each column */
1406 974 : foreach(l, vars)
1407 : {
1408 748 : Var *var = (Var *) lfirst(l);
1409 :
1410 748 : markVarForSelectPriv(pstate, var);
1411 : }
1412 :
1413 226 : return vars;
1414 : }
1415 : }
1416 :
1417 : /*
1418 : * ExpandRowReference()
1419 : * Transforms foo.* into a list of expressions or targetlist entries.
1420 : *
1421 : * This handles the case where foo is an arbitrary expression of composite
1422 : * type.
1423 : */
1424 : static List *
1425 1546 : ExpandRowReference(ParseState *pstate, Node *expr,
1426 : bool make_target_entry)
1427 : {
1428 1546 : List *result = NIL;
1429 : TupleDesc tupleDesc;
1430 : int numAttrs;
1431 : int i;
1432 :
1433 : /*
1434 : * If the rowtype expression is a whole-row Var, we can expand the fields
1435 : * as simple Vars. Note: if the RTE is a relation, this case leaves us
1436 : * with its RTEPermissionInfo's selectedCols bitmap showing the whole row
1437 : * as needing select permission, as well as the individual columns.
1438 : * However, we can only get here for weird notations like (table.*).*, so
1439 : * it's not worth trying to clean up --- arguably, the permissions marking
1440 : * is correct anyway for such cases.
1441 : */
1442 1546 : if (IsA(expr, Var) &&
1443 78 : ((Var *) expr)->varattno == InvalidAttrNumber)
1444 : {
1445 0 : Var *var = (Var *) expr;
1446 : ParseNamespaceItem *nsitem;
1447 :
1448 0 : nsitem = GetNSItemByRangeTablePosn(pstate, var->varno, var->varlevelsup);
1449 0 : return ExpandSingleTable(pstate, nsitem, var->varlevelsup, var->location, make_target_entry);
1450 : }
1451 :
1452 : /*
1453 : * Otherwise we have to do it the hard way. Our current implementation is
1454 : * to generate multiple copies of the expression and do FieldSelects.
1455 : * (This can be pretty inefficient if the expression involves nontrivial
1456 : * computation :-(.)
1457 : *
1458 : * Verify it's a composite type, and get the tupdesc.
1459 : * get_expr_result_tupdesc() handles this conveniently.
1460 : *
1461 : * If it's a Var of type RECORD, we have to work even harder: we have to
1462 : * find what the Var refers to, and pass that to get_expr_result_tupdesc.
1463 : * That task is handled by expandRecordVariable().
1464 : */
1465 1546 : if (IsA(expr, Var) &&
1466 78 : ((Var *) expr)->vartype == RECORDOID)
1467 6 : tupleDesc = expandRecordVariable(pstate, (Var *) expr, 0);
1468 : else
1469 1540 : tupleDesc = get_expr_result_tupdesc(expr, false);
1470 : Assert(tupleDesc);
1471 :
1472 : /* Generate a list of references to the individual fields */
1473 1546 : numAttrs = tupleDesc->natts;
1474 7466 : for (i = 0; i < numAttrs; i++)
1475 : {
1476 5920 : Form_pg_attribute att = TupleDescAttr(tupleDesc, i);
1477 : FieldSelect *fselect;
1478 :
1479 5920 : if (att->attisdropped)
1480 8 : continue;
1481 :
1482 5912 : fselect = makeNode(FieldSelect);
1483 5912 : fselect->arg = (Expr *) copyObject(expr);
1484 5912 : fselect->fieldnum = i + 1;
1485 5912 : fselect->resulttype = att->atttypid;
1486 5912 : fselect->resulttypmod = att->atttypmod;
1487 : /* save attribute's collation for parse_collate.c */
1488 5912 : fselect->resultcollid = att->attcollation;
1489 :
1490 5912 : if (make_target_entry)
1491 : {
1492 : /* add TargetEntry decoration */
1493 : TargetEntry *te;
1494 :
1495 11344 : te = makeTargetEntry((Expr *) fselect,
1496 5672 : (AttrNumber) pstate->p_next_resno++,
1497 5672 : pstrdup(NameStr(att->attname)),
1498 : false);
1499 5672 : result = lappend(result, te);
1500 : }
1501 : else
1502 240 : result = lappend(result, fselect);
1503 : }
1504 :
1505 1546 : return result;
1506 : }
1507 :
1508 : /*
1509 : * expandRecordVariable
1510 : * Get the tuple descriptor for a Var of type RECORD, if possible.
1511 : *
1512 : * Since no actual table or view column is allowed to have type RECORD, such
1513 : * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
1514 : * drill down to find the ultimate defining expression and attempt to infer
1515 : * the tupdesc from it. We ereport if we can't determine the tupdesc.
1516 : *
1517 : * levelsup is an extra offset to interpret the Var's varlevelsup correctly
1518 : * when recursing. Outside callers should pass zero.
1519 : */
1520 : TupleDesc
1521 2022 : expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
1522 : {
1523 : TupleDesc tupleDesc;
1524 : int netlevelsup;
1525 : RangeTblEntry *rte;
1526 : AttrNumber attnum;
1527 : Node *expr;
1528 :
1529 : /* Check my caller didn't mess up */
1530 : Assert(IsA(var, Var));
1531 : Assert(var->vartype == RECORDOID);
1532 :
1533 : /*
1534 : * Note: it's tempting to use GetNSItemByRangeTablePosn here so that we
1535 : * can use expandNSItemVars instead of expandRTE; but that does not work
1536 : * for some of the recursion cases below, where we have consed up a
1537 : * ParseState that lacks p_namespace data.
1538 : */
1539 2022 : netlevelsup = var->varlevelsup + levelsup;
1540 2022 : rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup);
1541 2022 : attnum = var->varattno;
1542 :
1543 2022 : if (attnum == InvalidAttrNumber)
1544 : {
1545 : /* Whole-row reference to an RTE, so expand the known fields */
1546 : List *names,
1547 : *vars;
1548 : ListCell *lname,
1549 : *lvar;
1550 : int i;
1551 :
1552 30 : expandRTE(rte, var->varno, 0, var->varreturningtype,
1553 : var->location, false, &names, &vars);
1554 :
1555 30 : tupleDesc = CreateTemplateTupleDesc(list_length(vars));
1556 30 : i = 1;
1557 90 : forboth(lname, names, lvar, vars)
1558 : {
1559 60 : char *label = strVal(lfirst(lname));
1560 60 : Node *varnode = (Node *) lfirst(lvar);
1561 :
1562 60 : TupleDescInitEntry(tupleDesc, i,
1563 : label,
1564 : exprType(varnode),
1565 : exprTypmod(varnode),
1566 : 0);
1567 60 : TupleDescInitEntryCollation(tupleDesc, i,
1568 : exprCollation(varnode));
1569 60 : i++;
1570 : }
1571 : Assert(lname == NULL && lvar == NULL); /* lists same length? */
1572 :
1573 30 : return tupleDesc;
1574 : }
1575 :
1576 1992 : expr = (Node *) var; /* default if we can't drill down */
1577 :
1578 1992 : switch (rte->rtekind)
1579 : {
1580 0 : case RTE_RELATION:
1581 : case RTE_VALUES:
1582 : case RTE_NAMEDTUPLESTORE:
1583 : case RTE_RESULT:
1584 :
1585 : /*
1586 : * This case should not occur: a column of a table, values list,
1587 : * or ENR shouldn't have type RECORD. Fall through and fail (most
1588 : * likely) at the bottom.
1589 : */
1590 0 : break;
1591 1914 : case RTE_SUBQUERY:
1592 : {
1593 : /* Subselect-in-FROM: examine sub-select's output expr */
1594 1914 : TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
1595 : attnum);
1596 :
1597 1914 : if (ste == NULL || ste->resjunk)
1598 0 : elog(ERROR, "subquery %s does not have attribute %d",
1599 : rte->eref->aliasname, attnum);
1600 1914 : expr = (Node *) ste->expr;
1601 1914 : if (IsA(expr, Var))
1602 : {
1603 : /*
1604 : * Recurse into the sub-select to see what its Var refers
1605 : * to. We have to build an additional level of ParseState
1606 : * to keep in step with varlevelsup in the subselect;
1607 : * furthermore, the subquery RTE might be from an outer
1608 : * query level, in which case the ParseState for the
1609 : * subselect must have that outer level as parent.
1610 : */
1611 36 : ParseState mypstate = {0};
1612 : Index levelsup;
1613 :
1614 : /* this loop must work, since GetRTEByRangeTablePosn did */
1615 54 : for (levelsup = 0; levelsup < netlevelsup; levelsup++)
1616 18 : pstate = pstate->parentParseState;
1617 36 : mypstate.parentParseState = pstate;
1618 36 : mypstate.p_rtable = rte->subquery->rtable;
1619 : /* don't bother filling the rest of the fake pstate */
1620 :
1621 36 : return expandRecordVariable(&mypstate, (Var *) expr, 0);
1622 : }
1623 : /* else fall through to inspect the expression */
1624 : }
1625 1878 : break;
1626 0 : case RTE_JOIN:
1627 : /* Join RTE --- recursively inspect the alias variable */
1628 : Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
1629 0 : expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
1630 : Assert(expr != NULL);
1631 : /* We intentionally don't strip implicit coercions here */
1632 0 : if (IsA(expr, Var))
1633 0 : return expandRecordVariable(pstate, (Var *) expr, netlevelsup);
1634 : /* else fall through to inspect the expression */
1635 0 : break;
1636 0 : case RTE_FUNCTION:
1637 :
1638 : /*
1639 : * We couldn't get here unless a function is declared with one of
1640 : * its result columns as RECORD, which is not allowed.
1641 : */
1642 0 : break;
1643 0 : case RTE_TABLEFUNC:
1644 :
1645 : /*
1646 : * Table function cannot have columns with RECORD type.
1647 : */
1648 0 : break;
1649 78 : case RTE_CTE:
1650 : /* CTE reference: examine subquery's output expr */
1651 78 : if (!rte->self_reference)
1652 : {
1653 78 : CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup);
1654 : TargetEntry *ste;
1655 :
1656 78 : ste = get_tle_by_resno(GetCTETargetList(cte), attnum);
1657 78 : if (ste == NULL || ste->resjunk)
1658 0 : elog(ERROR, "CTE %s does not have attribute %d",
1659 : rte->eref->aliasname, attnum);
1660 78 : expr = (Node *) ste->expr;
1661 78 : if (IsA(expr, Var))
1662 : {
1663 : /*
1664 : * Recurse into the CTE to see what its Var refers to. We
1665 : * have to build an additional level of ParseState to keep
1666 : * in step with varlevelsup in the CTE; furthermore it
1667 : * could be an outer CTE (compare SUBQUERY case above).
1668 : */
1669 42 : ParseState mypstate = {0};
1670 : Index levelsup;
1671 :
1672 : /* this loop must work, since GetCTEForRTE did */
1673 42 : for (levelsup = 0;
1674 78 : levelsup < rte->ctelevelsup + netlevelsup;
1675 36 : levelsup++)
1676 36 : pstate = pstate->parentParseState;
1677 42 : mypstate.parentParseState = pstate;
1678 42 : mypstate.p_rtable = ((Query *) cte->ctequery)->rtable;
1679 : /* don't bother filling the rest of the fake pstate */
1680 :
1681 42 : return expandRecordVariable(&mypstate, (Var *) expr, 0);
1682 : }
1683 : /* else fall through to inspect the expression */
1684 : }
1685 36 : break;
1686 0 : case RTE_GROUP:
1687 :
1688 : /*
1689 : * We couldn't get here: the RTE_GROUP RTE has not been added.
1690 : */
1691 0 : break;
1692 : }
1693 :
1694 : /*
1695 : * We now have an expression we can't expand any more, so see if
1696 : * get_expr_result_tupdesc() can do anything with it.
1697 : */
1698 1914 : return get_expr_result_tupdesc(expr, false);
1699 : }
1700 :
1701 :
1702 : /*
1703 : * FigureColname -
1704 : * if the name of the resulting column is not specified in the target
1705 : * list, we have to guess a suitable name. The SQL spec provides some
1706 : * guidance, but not much...
1707 : *
1708 : * Note that the argument is the *untransformed* parse tree for the target
1709 : * item. This is a shade easier to work with than the transformed tree.
1710 : */
1711 : char *
1712 872404 : FigureColname(Node *node)
1713 : {
1714 872404 : char *name = NULL;
1715 :
1716 872404 : (void) FigureColnameInternal(node, &name);
1717 872404 : if (name != NULL)
1718 794568 : return name;
1719 : /* default result if we can't guess anything */
1720 77836 : return "?column?";
1721 : }
1722 :
1723 : /*
1724 : * FigureIndexColname -
1725 : * choose the name for an expression column in an index
1726 : *
1727 : * This is actually just like FigureColname, except we return NULL if
1728 : * we can't pick a good name.
1729 : */
1730 : char *
1731 952 : FigureIndexColname(Node *node)
1732 : {
1733 952 : char *name = NULL;
1734 :
1735 952 : (void) FigureColnameInternal(node, &name);
1736 952 : return name;
1737 : }
1738 :
1739 : /*
1740 : * FigureColnameInternal -
1741 : * internal workhorse for FigureColname
1742 : *
1743 : * Return value indicates strength of confidence in result:
1744 : * 0 - no information
1745 : * 1 - second-best name choice
1746 : * 2 - good name choice
1747 : * The return value is actually only used internally.
1748 : * If the result isn't zero, *name is set to the chosen name.
1749 : */
1750 : static int
1751 939824 : FigureColnameInternal(Node *node, char **name)
1752 : {
1753 939824 : int strength = 0;
1754 :
1755 939824 : if (node == NULL)
1756 446 : return strength;
1757 :
1758 939378 : switch (nodeTag(node))
1759 : {
1760 560494 : case T_ColumnRef:
1761 : {
1762 560494 : char *fname = NULL;
1763 : ListCell *l;
1764 :
1765 : /* find last field name, if any, ignoring "*" */
1766 1384534 : foreach(l, ((ColumnRef *) node)->fields)
1767 : {
1768 824040 : Node *i = lfirst(l);
1769 :
1770 824040 : if (IsA(i, String))
1771 823920 : fname = strVal(i);
1772 : }
1773 560494 : if (fname)
1774 : {
1775 560494 : *name = fname;
1776 560494 : return 2;
1777 : }
1778 : }
1779 0 : break;
1780 1802 : case T_A_Indirection:
1781 : {
1782 1802 : A_Indirection *ind = (A_Indirection *) node;
1783 1802 : char *fname = NULL;
1784 : ListCell *l;
1785 :
1786 : /* find last field name, if any, ignoring "*" and subscripts */
1787 3894 : foreach(l, ind->indirection)
1788 : {
1789 2092 : Node *i = lfirst(l);
1790 :
1791 2092 : if (IsA(i, String))
1792 652 : fname = strVal(i);
1793 : }
1794 1802 : if (fname)
1795 : {
1796 630 : *name = fname;
1797 630 : return 2;
1798 : }
1799 1172 : return FigureColnameInternal(ind->arg, name);
1800 : }
1801 : break;
1802 206574 : case T_FuncCall:
1803 206574 : *name = strVal(llast(((FuncCall *) node)->funcname));
1804 206574 : return 2;
1805 32804 : case T_A_Expr:
1806 32804 : if (((A_Expr *) node)->kind == AEXPR_NULLIF)
1807 : {
1808 : /* make nullif() act like a regular function */
1809 46 : *name = "nullif";
1810 46 : return 2;
1811 : }
1812 32758 : break;
1813 52988 : case T_TypeCast:
1814 52988 : strength = FigureColnameInternal(((TypeCast *) node)->arg,
1815 : name);
1816 52988 : if (strength <= 1)
1817 : {
1818 12714 : if (((TypeCast *) node)->typeName != NULL)
1819 : {
1820 12714 : *name = strVal(llast(((TypeCast *) node)->typeName->names));
1821 12714 : return 1;
1822 : }
1823 : }
1824 40274 : break;
1825 130 : case T_CollateClause:
1826 130 : return FigureColnameInternal(((CollateClause *) node)->arg, name);
1827 296 : case T_GroupingFunc:
1828 : /* make GROUPING() act like a regular function */
1829 296 : *name = "grouping";
1830 296 : return 2;
1831 150 : case T_MergeSupportFunc:
1832 : /* make MERGE_ACTION() act like a regular function */
1833 150 : *name = "merge_action";
1834 150 : return 2;
1835 5582 : case T_SubLink:
1836 5582 : switch (((SubLink *) node)->subLinkType)
1837 : {
1838 106 : case EXISTS_SUBLINK:
1839 106 : *name = "exists";
1840 106 : return 2;
1841 84 : case ARRAY_SUBLINK:
1842 84 : *name = "array";
1843 84 : return 2;
1844 5344 : case EXPR_SUBLINK:
1845 : {
1846 : /* Get column name of the subquery's single target */
1847 5344 : SubLink *sublink = (SubLink *) node;
1848 5344 : Query *query = (Query *) sublink->subselect;
1849 :
1850 : /*
1851 : * The subquery has probably already been transformed,
1852 : * but let's be careful and check that. (The reason
1853 : * we can see a transformed subquery here is that
1854 : * transformSubLink is lazy and modifies the SubLink
1855 : * node in-place.)
1856 : */
1857 5344 : if (IsA(query, Query))
1858 : {
1859 5344 : TargetEntry *te = (TargetEntry *) linitial(query->targetList);
1860 :
1861 5344 : if (te->resname)
1862 : {
1863 5344 : *name = te->resname;
1864 5344 : return 2;
1865 : }
1866 : }
1867 : }
1868 0 : break;
1869 : /* As with other operator-like nodes, these have no names */
1870 48 : case MULTIEXPR_SUBLINK:
1871 : case ALL_SUBLINK:
1872 : case ANY_SUBLINK:
1873 : case ROWCOMPARE_SUBLINK:
1874 : case CTE_SUBLINK:
1875 48 : break;
1876 : }
1877 48 : break;
1878 12178 : case T_CaseExpr:
1879 12178 : strength = FigureColnameInternal((Node *) ((CaseExpr *) node)->defresult,
1880 : name);
1881 12178 : if (strength <= 1)
1882 : {
1883 4506 : *name = "case";
1884 4506 : return 1;
1885 : }
1886 7672 : break;
1887 762 : case T_A_ArrayExpr:
1888 : /* make ARRAY[] act like a function */
1889 762 : *name = "array";
1890 762 : return 2;
1891 528 : case T_RowExpr:
1892 : /* make ROW() act like a function */
1893 528 : *name = "row";
1894 528 : return 2;
1895 202 : case T_CoalesceExpr:
1896 : /* make coalesce() act like a regular function */
1897 202 : *name = "coalesce";
1898 202 : return 2;
1899 146 : case T_MinMaxExpr:
1900 : /* make greatest/least act like a regular function */
1901 146 : switch (((MinMaxExpr *) node)->op)
1902 : {
1903 60 : case IS_GREATEST:
1904 60 : *name = "greatest";
1905 60 : return 2;
1906 86 : case IS_LEAST:
1907 86 : *name = "least";
1908 86 : return 2;
1909 : }
1910 0 : break;
1911 376 : case T_SQLValueFunction:
1912 : /* make these act like a function or variable */
1913 376 : switch (((SQLValueFunction *) node)->op)
1914 : {
1915 18 : case SVFOP_CURRENT_DATE:
1916 18 : *name = "current_date";
1917 18 : return 2;
1918 12 : case SVFOP_CURRENT_TIME:
1919 : case SVFOP_CURRENT_TIME_N:
1920 12 : *name = "current_time";
1921 12 : return 2;
1922 22 : case SVFOP_CURRENT_TIMESTAMP:
1923 : case SVFOP_CURRENT_TIMESTAMP_N:
1924 22 : *name = "current_timestamp";
1925 22 : return 2;
1926 12 : case SVFOP_LOCALTIME:
1927 : case SVFOP_LOCALTIME_N:
1928 12 : *name = "localtime";
1929 12 : return 2;
1930 18 : case SVFOP_LOCALTIMESTAMP:
1931 : case SVFOP_LOCALTIMESTAMP_N:
1932 18 : *name = "localtimestamp";
1933 18 : return 2;
1934 42 : case SVFOP_CURRENT_ROLE:
1935 42 : *name = "current_role";
1936 42 : return 2;
1937 130 : case SVFOP_CURRENT_USER:
1938 130 : *name = "current_user";
1939 130 : return 2;
1940 6 : case SVFOP_USER:
1941 6 : *name = "user";
1942 6 : return 2;
1943 86 : case SVFOP_SESSION_USER:
1944 86 : *name = "session_user";
1945 86 : return 2;
1946 6 : case SVFOP_CURRENT_CATALOG:
1947 6 : *name = "current_catalog";
1948 6 : return 2;
1949 24 : case SVFOP_CURRENT_SCHEMA:
1950 24 : *name = "current_schema";
1951 24 : return 2;
1952 : }
1953 0 : break;
1954 450 : case T_XmlExpr:
1955 : /* make SQL/XML functions act like a regular function */
1956 450 : switch (((XmlExpr *) node)->op)
1957 : {
1958 48 : case IS_XMLCONCAT:
1959 48 : *name = "xmlconcat";
1960 48 : return 2;
1961 108 : case IS_XMLELEMENT:
1962 108 : *name = "xmlelement";
1963 108 : return 2;
1964 6 : case IS_XMLFOREST:
1965 6 : *name = "xmlforest";
1966 6 : return 2;
1967 138 : case IS_XMLPARSE:
1968 138 : *name = "xmlparse";
1969 138 : return 2;
1970 78 : case IS_XMLPI:
1971 78 : *name = "xmlpi";
1972 78 : return 2;
1973 60 : case IS_XMLROOT:
1974 60 : *name = "xmlroot";
1975 60 : return 2;
1976 0 : case IS_XMLSERIALIZE:
1977 0 : *name = "xmlserialize";
1978 0 : return 2;
1979 12 : case IS_DOCUMENT:
1980 : /* nothing */
1981 12 : break;
1982 : }
1983 12 : break;
1984 186 : case T_XmlSerialize:
1985 : /* make XMLSERIALIZE act like a regular function */
1986 186 : *name = "xmlserialize";
1987 186 : return 2;
1988 116 : case T_JsonParseExpr:
1989 : /* make JSON act like a regular function */
1990 116 : *name = "json";
1991 116 : return 2;
1992 112 : case T_JsonScalarExpr:
1993 : /* make JSON_SCALAR act like a regular function */
1994 112 : *name = "json_scalar";
1995 112 : return 2;
1996 92 : case T_JsonSerializeExpr:
1997 : /* make JSON_SERIALIZE act like a regular function */
1998 92 : *name = "json_serialize";
1999 92 : return 2;
2000 350 : case T_JsonObjectConstructor:
2001 : /* make JSON_OBJECT act like a regular function */
2002 350 : *name = "json_object";
2003 350 : return 2;
2004 188 : case T_JsonArrayConstructor:
2005 : case T_JsonArrayQueryConstructor:
2006 : /* make JSON_ARRAY act like a regular function */
2007 188 : *name = "json_array";
2008 188 : return 2;
2009 156 : case T_JsonObjectAgg:
2010 : /* make JSON_OBJECTAGG act like a regular function */
2011 156 : *name = "json_objectagg";
2012 156 : return 2;
2013 126 : case T_JsonArrayAgg:
2014 : /* make JSON_ARRAYAGG act like a regular function */
2015 126 : *name = "json_arrayagg";
2016 126 : return 2;
2017 1476 : case T_JsonFuncExpr:
2018 : /* make SQL/JSON functions act like a regular function */
2019 1476 : switch (((JsonFuncExpr *) node)->op)
2020 : {
2021 156 : case JSON_EXISTS_OP:
2022 156 : *name = "json_exists";
2023 156 : return 2;
2024 798 : case JSON_QUERY_OP:
2025 798 : *name = "json_query";
2026 798 : return 2;
2027 522 : case JSON_VALUE_OP:
2028 522 : *name = "json_value";
2029 522 : return 2;
2030 : /* JSON_TABLE_OP can't happen here. */
2031 0 : default:
2032 0 : elog(ERROR, "unrecognized JsonExpr op: %d",
2033 : (int) ((JsonFuncExpr *) node)->op);
2034 : }
2035 : break;
2036 61114 : default:
2037 61114 : break;
2038 : }
2039 :
2040 141878 : return strength;
2041 : }
|