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