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