Coverage Report

Created: 2025-06-13 06:06

/src/postgres/src/backend/parser/parse_target.c
Line
Count
Source (jump to first uncovered line)
1
/*-------------------------------------------------------------------------
2
 *
3
 * parse_target.c
4
 *    handle target lists
5
 *
6
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7
 * Portions Copyright (c) 1994, Regents of the University of California
8
 *
9
 *
10
 * IDENTIFICATION
11
 *    src/backend/parser/parse_target.c
12
 *
13
 *-------------------------------------------------------------------------
14
 */
15
#include "postgres.h"
16
17
#include "catalog/namespace.h"
18
#include "catalog/pg_type.h"
19
#include "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
transformTargetEntry(ParseState *pstate,
76
           Node *node,
77
           Node *expr,
78
           ParseExprKind exprKind,
79
           char *colname,
80
           bool resjunk)
81
0
{
82
  /* Transform the node if caller didn't do it already */
83
0
  if (expr == NULL)
84
0
  {
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
0
    if (exprKind == EXPR_KIND_UPDATE_SOURCE && IsA(node, SetToDefault))
91
0
      expr = node;
92
0
    else
93
0
      expr = transformExpr(pstate, node, exprKind);
94
0
  }
95
96
0
  if (colname == NULL && !resjunk)
97
0
  {
98
    /*
99
     * Generate a suitable column name for a column without any explicit
100
     * 'AS ColumnName' clause.
101
     */
102
0
    colname = FigureColname(node);
103
0
  }
104
105
0
  return makeTargetEntry((Expr *) expr,
106
0
               (AttrNumber) pstate->p_next_resno++,
107
0
               colname,
108
0
               resjunk);
109
0
}
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
transformTargetList(ParseState *pstate, List *targetlist,
122
          ParseExprKind exprKind)
123
0
{
124
0
  List     *p_target = NIL;
125
0
  bool    expand_star;
126
0
  ListCell   *o_target;
127
128
  /* Shouldn't have any leftover multiassign items at start */
129
0
  Assert(pstate->p_multiassign_exprs == NIL);
130
131
  /* Expand "something.*" in SELECT and RETURNING, but not UPDATE */
132
0
  expand_star = (exprKind != EXPR_KIND_UPDATE_SOURCE);
133
134
0
  foreach(o_target, targetlist)
135
0
  {
136
0
    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
0
    if (expand_star)
144
0
    {
145
0
      if (IsA(res->val, ColumnRef))
146
0
      {
147
0
        ColumnRef  *cref = (ColumnRef *) res->val;
148
149
0
        if (IsA(llast(cref->fields), A_Star))
150
0
        {
151
          /* It is something.*, expand into multiple items */
152
0
          p_target = list_concat(p_target,
153
0
                       ExpandColumnRefStar(pstate,
154
0
                                 cref,
155
0
                                 true));
156
0
          continue;
157
0
        }
158
0
      }
159
0
      else if (IsA(res->val, A_Indirection))
160
0
      {
161
0
        A_Indirection *ind = (A_Indirection *) res->val;
162
163
0
        if (IsA(llast(ind->indirection), A_Star))
164
0
        {
165
          /* It is something.*, expand into multiple items */
166
0
          p_target = list_concat(p_target,
167
0
                       ExpandIndirectionStar(pstate,
168
0
                                 ind,
169
0
                                 true,
170
0
                                 exprKind));
171
0
          continue;
172
0
        }
173
0
      }
174
0
    }
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
0
    p_target = lappend(p_target,
181
0
               transformTargetEntry(pstate,
182
0
                        res->val,
183
0
                        NULL,
184
0
                        exprKind,
185
0
                        res->name,
186
0
                        false));
187
0
  }
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
0
  if (pstate->p_multiassign_exprs)
196
0
  {
197
0
    Assert(exprKind == EXPR_KIND_UPDATE_SOURCE);
198
0
    p_target = list_concat(p_target, pstate->p_multiassign_exprs);
199
0
    pstate->p_multiassign_exprs = NIL;
200
0
  }
201
202
0
  return p_target;
203
0
}
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
transformExpressionList(ParseState *pstate, List *exprlist,
221
            ParseExprKind exprKind, bool allowDefault)
222
0
{
223
0
  List     *result = NIL;
224
0
  ListCell   *lc;
225
226
0
  foreach(lc, exprlist)
227
0
  {
228
0
    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
0
    if (IsA(e, ColumnRef))
236
0
    {
237
0
      ColumnRef  *cref = (ColumnRef *) e;
238
239
0
      if (IsA(llast(cref->fields), A_Star))
240
0
      {
241
        /* It is something.*, expand into multiple items */
242
0
        result = list_concat(result,
243
0
                   ExpandColumnRefStar(pstate, cref,
244
0
                             false));
245
0
        continue;
246
0
      }
247
0
    }
248
0
    else if (IsA(e, A_Indirection))
249
0
    {
250
0
      A_Indirection *ind = (A_Indirection *) e;
251
252
0
      if (IsA(llast(ind->indirection), A_Star))
253
0
      {
254
        /* It is something.*, expand into multiple items */
255
0
        result = list_concat(result,
256
0
                   ExpandIndirectionStar(pstate, ind,
257
0
                               false, exprKind));
258
0
        continue;
259
0
      }
260
0
    }
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
0
    if (allowDefault && IsA(e, SetToDefault))
269
0
       /* do nothing */ ;
270
0
    else
271
0
      e = transformExpr(pstate, e, exprKind);
272
273
0
    result = lappend(result, e);
274
0
  }
275
276
0
  return result;
277
0
}
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
resolveTargetListUnknowns(ParseState *pstate, List *targetlist)
289
0
{
290
0
  ListCell   *l;
291
292
0
  foreach(l, targetlist)
293
0
  {
294
0
    TargetEntry *tle = (TargetEntry *) lfirst(l);
295
0
    Oid     restype = exprType((Node *) tle->expr);
296
297
0
    if (restype == UNKNOWNOID)
298
0
    {
299
0
      tle->expr = (Expr *) coerce_type(pstate, (Node *) tle->expr,
300
0
                       restype, TEXTOID, -1,
301
0
                       COERCION_IMPLICIT,
302
0
                       COERCE_IMPLICIT_CAST,
303
0
                       -1);
304
0
    }
305
0
  }
306
0
}
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
markTargetListOrigins(ParseState *pstate, List *targetlist)
319
0
{
320
0
  ListCell   *l;
321
322
0
  foreach(l, targetlist)
323
0
  {
324
0
    TargetEntry *tle = (TargetEntry *) lfirst(l);
325
326
0
    markTargetListOrigin(pstate, tle, (Var *) tle->expr, 0);
327
0
  }
328
0
}
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
markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
344
           Var *var, int levelsup)
345
0
{
346
0
  int     netlevelsup;
347
0
  RangeTblEntry *rte;
348
0
  AttrNumber  attnum;
349
350
0
  if (var == NULL || !IsA(var, Var))
351
0
    return;
352
0
  netlevelsup = var->varlevelsup + levelsup;
353
0
  rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup);
354
0
  attnum = var->varattno;
355
356
0
  switch (rte->rtekind)
357
0
  {
358
0
    case RTE_RELATION:
359
      /* It's a table or view, report it */
360
0
      tle->resorigtbl = rte->relid;
361
0
      tle->resorigcol = attnum;
362
0
      break;
363
0
    case RTE_SUBQUERY:
364
      /* Subselect-in-FROM: copy up from the subselect */
365
0
      if (attnum != InvalidAttrNumber)
366
0
      {
367
0
        TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
368
0
                          attnum);
369
370
0
        if (ste == NULL || ste->resjunk)
371
0
          elog(ERROR, "subquery %s does not have attribute %d",
372
0
             rte->eref->aliasname, attnum);
373
0
        tle->resorigtbl = ste->resorigtbl;
374
0
        tle->resorigcol = ste->resorigcol;
375
0
      }
376
0
      break;
377
0
    case RTE_JOIN:
378
0
    case RTE_FUNCTION:
379
0
    case RTE_VALUES:
380
0
    case RTE_TABLEFUNC:
381
0
    case RTE_NAMEDTUPLESTORE:
382
0
    case RTE_RESULT:
383
      /* not a simple relation, leave it unmarked */
384
0
      break;
385
0
    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
0
      if (attnum != InvalidAttrNumber && !rte->self_reference)
396
0
      {
397
0
        CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup);
398
0
        TargetEntry *ste;
399
0
        List     *tl = GetCTETargetList(cte);
400
0
        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
0
        if (cte->search_clause)
407
0
          extra_cols += 1;
408
0
        if (cte->cycle_clause)
409
0
          extra_cols += 2;
410
0
        if (extra_cols &&
411
0
          attnum > list_length(tl) &&
412
0
          attnum <= list_length(tl) + extra_cols)
413
0
          break;
414
415
0
        ste = get_tle_by_resno(tl, attnum);
416
0
        if (ste == NULL || ste->resjunk)
417
0
          elog(ERROR, "CTE %s does not have attribute %d",
418
0
             rte->eref->aliasname, attnum);
419
0
        tle->resorigtbl = ste->resorigtbl;
420
0
        tle->resorigcol = ste->resorigcol;
421
0
      }
422
0
      break;
423
0
    case RTE_GROUP:
424
      /* We couldn't get here: the RTE_GROUP RTE has not been added */
425
0
      break;
426
0
  }
427
0
}
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
transformAssignedExpr(ParseState *pstate,
456
            Expr *expr,
457
            ParseExprKind exprKind,
458
            const char *colname,
459
            int attrno,
460
            List *indirection,
461
            int location)
462
0
{
463
0
  Relation  rd = pstate->p_target_relation;
464
0
  Oid     type_id;    /* type of value provided */
465
0
  Oid     attrtype;   /* type of target column */
466
0
  int32   attrtypmod;
467
0
  Oid     attrcollation;  /* collation of target column */
468
0
  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
0
  Assert(exprKind != EXPR_KIND_NONE);
476
0
  sv_expr_kind = pstate->p_expr_kind;
477
0
  pstate->p_expr_kind = exprKind;
478
479
0
  Assert(rd != NULL);
480
0
  if (attrno <= 0)
481
0
    ereport(ERROR,
482
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
483
0
         errmsg("cannot assign to system column \"%s\"",
484
0
            colname),
485
0
         parser_errposition(pstate, location)));
486
0
  attrtype = attnumTypeId(rd, attrno);
487
0
  attrtypmod = TupleDescAttr(rd->rd_att, attrno - 1)->atttypmod;
488
0
  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
0
  if (expr && IsA(expr, SetToDefault))
500
0
  {
501
0
    SetToDefault *def = (SetToDefault *) expr;
502
503
0
    def->typeId = attrtype;
504
0
    def->typeMod = attrtypmod;
505
0
    def->collation = attrcollation;
506
0
    if (indirection)
507
0
    {
508
0
      if (IsA(linitial(indirection), A_Indices))
509
0
        ereport(ERROR,
510
0
            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
511
0
             errmsg("cannot set an array element to DEFAULT"),
512
0
             parser_errposition(pstate, location)));
513
0
      else
514
0
        ereport(ERROR,
515
0
            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
516
0
             errmsg("cannot set a subfield to DEFAULT"),
517
0
             parser_errposition(pstate, location)));
518
0
    }
519
0
  }
520
521
  /* Now we can use exprType() safely. */
522
0
  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
0
  if (indirection)
531
0
  {
532
0
    Node     *colVar;
533
534
0
    if (pstate->p_is_insert)
535
0
    {
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
0
      colVar = (Node *) makeNullConst(attrtype, attrtypmod,
542
0
                      attrcollation);
543
0
    }
544
0
    else
545
0
    {
546
      /*
547
       * Build a Var for the column to be updated.
548
       */
549
0
      Var      *var;
550
551
0
      var = makeVar(pstate->p_target_nsitem->p_rtindex, attrno,
552
0
              attrtype, attrtypmod, attrcollation, 0);
553
0
      var->location = location;
554
555
0
      colVar = (Node *) var;
556
0
    }
557
558
0
    expr = (Expr *)
559
0
      transformAssignmentIndirection(pstate,
560
0
                       colVar,
561
0
                       colname,
562
0
                       false,
563
0
                       attrtype,
564
0
                       attrtypmod,
565
0
                       attrcollation,
566
0
                       indirection,
567
0
                       list_head(indirection),
568
0
                       (Node *) expr,
569
0
                       COERCION_ASSIGNMENT,
570
0
                       location);
571
0
  }
572
0
  else
573
0
  {
574
    /*
575
     * For normal non-qualified target column, do type checking and
576
     * coercion.
577
     */
578
0
    Node     *orig_expr = (Node *) expr;
579
580
0
    expr = (Expr *)
581
0
      coerce_to_target_type(pstate,
582
0
                  orig_expr, type_id,
583
0
                  attrtype, attrtypmod,
584
0
                  COERCION_ASSIGNMENT,
585
0
                  COERCE_IMPLICIT_CAST,
586
0
                  -1);
587
0
    if (expr == NULL)
588
0
      ereport(ERROR,
589
0
          (errcode(ERRCODE_DATATYPE_MISMATCH),
590
0
           errmsg("column \"%s\" is of type %s"
591
0
              " but expression is of type %s",
592
0
              colname,
593
0
              format_type_be(attrtype),
594
0
              format_type_be(type_id)),
595
0
           errhint("You will need to rewrite or cast the expression."),
596
0
           parser_errposition(pstate, exprLocation(orig_expr))));
597
0
  }
598
599
0
  pstate->p_expr_kind = sv_expr_kind;
600
601
0
  return expr;
602
0
}
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
updateTargetListEntry(ParseState *pstate,
623
            TargetEntry *tle,
624
            char *colname,
625
            int attrno,
626
            List *indirection,
627
            int location)
628
0
{
629
  /* Fix up expression as needed */
630
0
  tle->expr = transformAssignedExpr(pstate,
631
0
                    tle->expr,
632
0
                    EXPR_KIND_UPDATE_TARGET,
633
0
                    colname,
634
0
                    attrno,
635
0
                    indirection,
636
0
                    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
0
  tle->resno = (AttrNumber) attrno;
645
0
  tle->resname = colname;
646
0
}
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
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
0
{
699
0
  Node     *result;
700
0
  List     *subscripts = NIL;
701
0
  ListCell   *i;
702
703
0
  if (indirection_cell && !basenode)
704
0
  {
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
0
    CaseTestExpr *ctest = makeNode(CaseTestExpr);
713
714
0
    ctest->typeId = targetTypeId;
715
0
    ctest->typeMod = targetTypMod;
716
0
    ctest->collation = targetCollation;
717
0
    basenode = (Node *) ctest;
718
0
  }
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
0
  for_each_cell(i, indirection, indirection_cell)
726
0
  {
727
0
    Node     *n = lfirst(i);
728
729
0
    if (IsA(n, A_Indices))
730
0
      subscripts = lappend(subscripts, n);
731
0
    else if (IsA(n, A_Star))
732
0
    {
733
0
      ereport(ERROR,
734
0
          (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
735
0
           errmsg("row expansion via \"*\" is not supported here"),
736
0
           parser_errposition(pstate, location)));
737
0
    }
738
0
    else
739
0
    {
740
0
      FieldStore *fstore;
741
0
      Oid     baseTypeId;
742
0
      int32   baseTypeMod;
743
0
      Oid     typrelid;
744
0
      AttrNumber  attnum;
745
0
      Oid     fieldTypeId;
746
0
      int32   fieldTypMod;
747
0
      Oid     fieldCollation;
748
749
0
      Assert(IsA(n, String));
750
751
      /* process subscripts before this field selection */
752
0
      if (subscripts)
753
0
      {
754
        /* recurse, and then return because we're done */
755
0
        return transformAssignmentSubscripts(pstate,
756
0
                           basenode,
757
0
                           targetName,
758
0
                           targetTypeId,
759
0
                           targetTypMod,
760
0
                           targetCollation,
761
0
                           subscripts,
762
0
                           indirection,
763
0
                           i,
764
0
                           rhs,
765
0
                           ccontext,
766
0
                           location);
767
0
      }
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
0
      baseTypeMod = targetTypMod;
776
0
      baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
777
778
0
      typrelid = typeidTypeRelid(baseTypeId);
779
0
      if (!typrelid)
780
0
        ereport(ERROR,
781
0
            (errcode(ERRCODE_DATATYPE_MISMATCH),
782
0
             errmsg("cannot assign to field \"%s\" of column \"%s\" because its type %s is not a composite type",
783
0
                strVal(n), targetName,
784
0
                format_type_be(targetTypeId)),
785
0
             parser_errposition(pstate, location)));
786
787
0
      attnum = get_attnum(typrelid, strVal(n));
788
0
      if (attnum == InvalidAttrNumber)
789
0
        ereport(ERROR,
790
0
            (errcode(ERRCODE_UNDEFINED_COLUMN),
791
0
             errmsg("cannot assign to field \"%s\" of column \"%s\" because there is no such column in data type %s",
792
0
                strVal(n), targetName,
793
0
                format_type_be(targetTypeId)),
794
0
             parser_errposition(pstate, location)));
795
0
      if (attnum < 0)
796
0
        ereport(ERROR,
797
0
            (errcode(ERRCODE_UNDEFINED_COLUMN),
798
0
             errmsg("cannot assign to system column \"%s\"",
799
0
                strVal(n)),
800
0
             parser_errposition(pstate, location)));
801
802
0
      get_atttypetypmodcoll(typrelid, attnum,
803
0
                  &fieldTypeId, &fieldTypMod, &fieldCollation);
804
805
      /* recurse to create appropriate RHS for field assign */
806
0
      rhs = transformAssignmentIndirection(pstate,
807
0
                         NULL,
808
0
                         strVal(n),
809
0
                         false,
810
0
                         fieldTypeId,
811
0
                         fieldTypMod,
812
0
                         fieldCollation,
813
0
                         indirection,
814
0
                         lnext(indirection, i),
815
0
                         rhs,
816
0
                         ccontext,
817
0
                         location);
818
819
      /* and build a FieldStore node */
820
0
      fstore = makeNode(FieldStore);
821
0
      fstore->arg = (Expr *) basenode;
822
0
      fstore->newvals = list_make1(rhs);
823
0
      fstore->fieldnums = list_make1_int(attnum);
824
0
      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
0
      if (baseTypeId != targetTypeId)
837
0
        return coerce_to_domain((Node *) fstore,
838
0
                    baseTypeId, baseTypeMod,
839
0
                    targetTypeId,
840
0
                    COERCION_IMPLICIT,
841
0
                    COERCE_IMPLICIT_CAST,
842
0
                    location,
843
0
                    false);
844
845
0
      return (Node *) fstore;
846
0
    }
847
0
  }
848
849
  /* process trailing subscripts, if any */
850
0
  if (subscripts)
851
0
  {
852
    /* recurse, and then return because we're done */
853
0
    return transformAssignmentSubscripts(pstate,
854
0
                       basenode,
855
0
                       targetName,
856
0
                       targetTypeId,
857
0
                       targetTypMod,
858
0
                       targetCollation,
859
0
                       subscripts,
860
0
                       indirection,
861
0
                       NULL,
862
0
                       rhs,
863
0
                       ccontext,
864
0
                       location);
865
0
  }
866
867
  /* base case: just coerce RHS to match target type ID */
868
869
0
  result = coerce_to_target_type(pstate,
870
0
                   rhs, exprType(rhs),
871
0
                   targetTypeId, targetTypMod,
872
0
                   ccontext,
873
0
                   COERCE_IMPLICIT_CAST,
874
0
                   -1);
875
0
  if (result == NULL)
876
0
  {
877
0
    if (targetIsSubscripting)
878
0
      ereport(ERROR,
879
0
          (errcode(ERRCODE_DATATYPE_MISMATCH),
880
0
           errmsg("subscripted assignment to \"%s\" requires type %s"
881
0
              " but expression is of type %s",
882
0
              targetName,
883
0
              format_type_be(targetTypeId),
884
0
              format_type_be(exprType(rhs))),
885
0
           errhint("You will need to rewrite or cast the expression."),
886
0
           parser_errposition(pstate, location)));
887
0
    else
888
0
      ereport(ERROR,
889
0
          (errcode(ERRCODE_DATATYPE_MISMATCH),
890
0
           errmsg("subfield \"%s\" is of type %s"
891
0
              " but expression is of type %s",
892
0
              targetName,
893
0
              format_type_be(targetTypeId),
894
0
              format_type_be(exprType(rhs))),
895
0
           errhint("You will need to rewrite or cast the expression."),
896
0
           parser_errposition(pstate, location)));
897
0
  }
898
899
0
  return result;
900
0
}
901
902
/*
903
 * helper for transformAssignmentIndirection: process container assignment
904
 */
905
static Node *
906
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
0
{
919
0
  Node     *result;
920
0
  SubscriptingRef *sbsref;
921
0
  Oid     containerType;
922
0
  int32   containerTypMod;
923
0
  Oid     typeNeeded;
924
0
  int32   typmodNeeded;
925
0
  Oid     collationNeeded;
926
927
0
  Assert(subscripts != NIL);
928
929
  /* Identify the actual container type involved */
930
0
  containerType = targetTypeId;
931
0
  containerTypMod = targetTypMod;
932
0
  transformContainerType(&containerType, &containerTypMod);
933
934
  /* Process subscripts and identify required type for RHS */
935
0
  sbsref = transformContainerSubscripts(pstate,
936
0
                      basenode,
937
0
                      containerType,
938
0
                      containerTypMod,
939
0
                      subscripts,
940
0
                      true);
941
942
0
  typeNeeded = sbsref->refrestype;
943
0
  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
0
  if (containerType == targetTypeId)
953
0
    collationNeeded = targetCollation;
954
0
  else
955
0
    collationNeeded = get_typcollation(containerType);
956
957
  /* recurse to create appropriate RHS for container assign */
958
0
  rhs = transformAssignmentIndirection(pstate,
959
0
                     NULL,
960
0
                     targetName,
961
0
                     true,
962
0
                     typeNeeded,
963
0
                     typmodNeeded,
964
0
                     collationNeeded,
965
0
                     indirection,
966
0
                     next_indirection,
967
0
                     rhs,
968
0
                     ccontext,
969
0
                     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
0
  sbsref->refassgnexpr = (Expr *) rhs;
976
0
  sbsref->refrestype = containerType;
977
0
  sbsref->reftypmod = containerTypMod;
978
979
0
  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
0
  if (containerType != targetTypeId)
988
0
  {
989
0
    Oid     resulttype = exprType(result);
990
991
0
    result = coerce_to_target_type(pstate,
992
0
                     result, resulttype,
993
0
                     targetTypeId, targetTypMod,
994
0
                     ccontext,
995
0
                     COERCE_IMPLICIT_CAST,
996
0
                     -1);
997
    /* can fail if we had int2vector/oidvector, but not for true domains */
998
0
    if (result == NULL)
999
0
      ereport(ERROR,
1000
0
          (errcode(ERRCODE_CANNOT_COERCE),
1001
0
           errmsg("cannot cast type %s to %s",
1002
0
              format_type_be(resulttype),
1003
0
              format_type_be(targetTypeId)),
1004
0
           parser_errposition(pstate, location)));
1005
0
  }
1006
1007
0
  return result;
1008
0
}
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
checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
1019
0
{
1020
0
  *attrnos = NIL;
1021
1022
0
  if (cols == NIL)
1023
0
  {
1024
    /*
1025
     * Generate default column list for INSERT.
1026
     */
1027
0
    int     numcol = RelationGetNumberOfAttributes(pstate->p_target_relation);
1028
1029
0
    int     i;
1030
1031
0
    for (i = 0; i < numcol; i++)
1032
0
    {
1033
0
      ResTarget  *col;
1034
0
      Form_pg_attribute attr;
1035
1036
0
      attr = TupleDescAttr(pstate->p_target_relation->rd_att, i);
1037
1038
0
      if (attr->attisdropped)
1039
0
        continue;
1040
1041
0
      col = makeNode(ResTarget);
1042
0
      col->name = pstrdup(NameStr(attr->attname));
1043
0
      col->indirection = NIL;
1044
0
      col->val = NULL;
1045
0
      col->location = -1;
1046
0
      cols = lappend(cols, col);
1047
0
      *attrnos = lappend_int(*attrnos, i + 1);
1048
0
    }
1049
0
  }
1050
0
  else
1051
0
  {
1052
    /*
1053
     * Do initial validation of user-supplied INSERT column list.
1054
     */
1055
0
    Bitmapset  *wholecols = NULL;
1056
0
    Bitmapset  *partialcols = NULL;
1057
0
    ListCell   *tl;
1058
1059
0
    foreach(tl, cols)
1060
0
    {
1061
0
      ResTarget  *col = (ResTarget *) lfirst(tl);
1062
0
      char     *name = col->name;
1063
0
      int     attrno;
1064
1065
      /* Lookup column name, ereport on failure */
1066
0
      attrno = attnameAttNum(pstate->p_target_relation, name, false);
1067
0
      if (attrno == InvalidAttrNumber)
1068
0
        ereport(ERROR,
1069
0
            (errcode(ERRCODE_UNDEFINED_COLUMN),
1070
0
             errmsg("column \"%s\" of relation \"%s\" does not exist",
1071
0
                name,
1072
0
                RelationGetRelationName(pstate->p_target_relation)),
1073
0
             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
0
      if (col->indirection == NIL)
1080
0
      {
1081
        /* whole column; must not have any other assignment */
1082
0
        if (bms_is_member(attrno, wholecols) ||
1083
0
          bms_is_member(attrno, partialcols))
1084
0
          ereport(ERROR,
1085
0
              (errcode(ERRCODE_DUPLICATE_COLUMN),
1086
0
               errmsg("column \"%s\" specified more than once",
1087
0
                  name),
1088
0
               parser_errposition(pstate, col->location)));
1089
0
        wholecols = bms_add_member(wholecols, attrno);
1090
0
      }
1091
0
      else
1092
0
      {
1093
        /* partial column; must not have any whole assignment */
1094
0
        if (bms_is_member(attrno, wholecols))
1095
0
          ereport(ERROR,
1096
0
              (errcode(ERRCODE_DUPLICATE_COLUMN),
1097
0
               errmsg("column \"%s\" specified more than once",
1098
0
                  name),
1099
0
               parser_errposition(pstate, col->location)));
1100
0
        partialcols = bms_add_member(partialcols, attrno);
1101
0
      }
1102
1103
0
      *attrnos = lappend_int(*attrnos, attrno);
1104
0
    }
1105
0
  }
1106
1107
0
  return cols;
1108
0
}
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
ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
1124
          bool make_target_entry)
1125
0
{
1126
0
  List     *fields = cref->fields;
1127
0
  int     numnames = list_length(fields);
1128
1129
0
  if (numnames == 1)
1130
0
  {
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
0
    Assert(make_target_entry);
1140
0
    return ExpandAllTables(pstate, cref->location);
1141
0
  }
1142
0
  else
1143
0
  {
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
0
    char     *nspname = NULL;
1159
0
    char     *relname = NULL;
1160
0
    ParseNamespaceItem *nsitem = NULL;
1161
0
    int     levels_up;
1162
0
    enum
1163
0
    {
1164
0
      CRSERR_NO_RTE,
1165
0
      CRSERR_WRONG_DB,
1166
0
      CRSERR_TOO_MANY
1167
0
    }     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
0
    if (pstate->p_pre_columnref_hook != NULL)
1174
0
    {
1175
0
      Node     *node;
1176
1177
0
      node = pstate->p_pre_columnref_hook(pstate, cref);
1178
0
      if (node != NULL)
1179
0
        return ExpandRowReference(pstate, node, make_target_entry);
1180
0
    }
1181
1182
0
    switch (numnames)
1183
0
    {
1184
0
      case 2:
1185
0
        relname = strVal(linitial(fields));
1186
0
        nsitem = refnameNamespaceItem(pstate, nspname, relname,
1187
0
                        cref->location,
1188
0
                        &levels_up);
1189
0
        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
0
                        cref->location,
1195
0
                        &levels_up);
1196
0
        break;
1197
0
      case 4:
1198
0
        {
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
0
          {
1206
0
            crserr = CRSERR_WRONG_DB;
1207
0
            break;
1208
0
          }
1209
0
          nspname = strVal(lsecond(fields));
1210
0
          relname = strVal(lthird(fields));
1211
0
          nsitem = refnameNamespaceItem(pstate, nspname, relname,
1212
0
                          cref->location,
1213
0
                          &levels_up);
1214
0
          break;
1215
0
        }
1216
0
      default:
1217
0
        crserr = CRSERR_TOO_MANY;
1218
0
        break;
1219
0
    }
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
0
    if (pstate->p_post_columnref_hook != NULL)
1231
0
    {
1232
0
      Node     *node;
1233
1234
0
      node = pstate->p_post_columnref_hook(pstate, cref,
1235
0
                         (Node *) (nsitem ? nsitem->p_rte : NULL));
1236
0
      if (node != NULL)
1237
0
      {
1238
0
        if (nsitem != NULL)
1239
0
          ereport(ERROR,
1240
0
              (errcode(ERRCODE_AMBIGUOUS_COLUMN),
1241
0
               errmsg("column reference \"%s\" is ambiguous",
1242
0
                  NameListToString(cref->fields)),
1243
0
               parser_errposition(pstate, cref->location)));
1244
0
        return ExpandRowReference(pstate, node, make_target_entry);
1245
0
      }
1246
0
    }
1247
1248
    /*
1249
     * Throw error if no translation found.
1250
     */
1251
0
    if (nsitem == NULL)
1252
0
    {
1253
0
      switch (crserr)
1254
0
      {
1255
0
        case CRSERR_NO_RTE:
1256
0
          errorMissingRTE(pstate, makeRangeVar(nspname, relname,
1257
0
                             cref->location));
1258
0
          break;
1259
0
        case CRSERR_WRONG_DB:
1260
0
          ereport(ERROR,
1261
0
              (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1262
0
               errmsg("cross-database references are not implemented: %s",
1263
0
                  NameListToString(cref->fields)),
1264
0
               parser_errposition(pstate, cref->location)));
1265
0
          break;
1266
0
        case CRSERR_TOO_MANY:
1267
0
          ereport(ERROR,
1268
0
              (errcode(ERRCODE_SYNTAX_ERROR),
1269
0
               errmsg("improper qualified name (too many dotted names): %s",
1270
0
                  NameListToString(cref->fields)),
1271
0
               parser_errposition(pstate, cref->location)));
1272
0
          break;
1273
0
      }
1274
0
    }
1275
1276
    /*
1277
     * OK, expand the nsitem into fields.
1278
     */
1279
0
    return ExpandSingleTable(pstate, nsitem, levels_up, cref->location,
1280
0
                 make_target_entry);
1281
0
  }
1282
0
}
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
ExpandAllTables(ParseState *pstate, int location)
1297
0
{
1298
0
  List     *target = NIL;
1299
0
  bool    found_table = false;
1300
0
  ListCell   *l;
1301
1302
0
  foreach(l, pstate->p_namespace)
1303
0
  {
1304
0
    ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
1305
1306
    /* Ignore table-only items */
1307
0
    if (!nsitem->p_cols_visible)
1308
0
      continue;
1309
    /* Should not have any lateral-only items when parsing targetlist */
1310
0
    Assert(!nsitem->p_lateral_only);
1311
    /* Remember we found a p_cols_visible item */
1312
0
    found_table = true;
1313
1314
0
    target = list_concat(target,
1315
0
               expandNSItemAttrs(pstate,
1316
0
                         nsitem,
1317
0
                         0,
1318
0
                         true,
1319
0
                         location));
1320
0
  }
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
0
  if (!found_table)
1328
0
    ereport(ERROR,
1329
0
        (errcode(ERRCODE_SYNTAX_ERROR),
1330
0
         errmsg("SELECT * with no tables specified is not valid"),
1331
0
         parser_errposition(pstate, location)));
1332
1333
0
  return target;
1334
0
}
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
ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind,
1349
            bool make_target_entry, ParseExprKind exprKind)
1350
0
{
1351
0
  Node     *expr;
1352
1353
  /* Strip off the '*' to create a reference to the rowtype object */
1354
0
  ind = copyObject(ind);
1355
0
  ind->indirection = list_truncate(ind->indirection,
1356
0
                   list_length(ind->indirection) - 1);
1357
1358
  /* And transform that */
1359
0
  expr = transformExpr(pstate, (Node *) ind, exprKind);
1360
1361
  /* Expand the rowtype expression into individual fields */
1362
0
  return ExpandRowReference(pstate, expr, make_target_entry);
1363
0
}
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
ExpandSingleTable(ParseState *pstate, ParseNamespaceItem *nsitem,
1376
          int sublevels_up, int location, bool make_target_entry)
1377
0
{
1378
0
  if (make_target_entry)
1379
0
  {
1380
    /* expandNSItemAttrs handles permissions marking */
1381
0
    return expandNSItemAttrs(pstate, nsitem, sublevels_up, true, location);
1382
0
  }
1383
0
  else
1384
0
  {
1385
0
    RangeTblEntry *rte = nsitem->p_rte;
1386
0
    RTEPermissionInfo *perminfo = nsitem->p_perminfo;
1387
0
    List     *vars;
1388
0
    ListCell   *l;
1389
1390
0
    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
0
    if (rte->rtekind == RTE_RELATION)
1401
0
    {
1402
0
      Assert(perminfo != NULL);
1403
0
      perminfo->requiredPerms |= ACL_SELECT;
1404
0
    }
1405
1406
    /* Require read access to each column */
1407
0
    foreach(l, vars)
1408
0
    {
1409
0
      Var      *var = (Var *) lfirst(l);
1410
1411
0
      markVarForSelectPriv(pstate, var);
1412
0
    }
1413
1414
0
    return vars;
1415
0
  }
1416
0
}
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
ExpandRowReference(ParseState *pstate, Node *expr,
1427
           bool make_target_entry)
1428
0
{
1429
0
  List     *result = NIL;
1430
0
  TupleDesc tupleDesc;
1431
0
  int     numAttrs;
1432
0
  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
0
  if (IsA(expr, Var) &&
1444
0
    ((Var *) expr)->varattno == InvalidAttrNumber)
1445
0
  {
1446
0
    Var      *var = (Var *) expr;
1447
0
    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
0
  }
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
0
  if (IsA(expr, Var) &&
1467
0
    ((Var *) expr)->vartype == RECORDOID)
1468
0
    tupleDesc = expandRecordVariable(pstate, (Var *) expr, 0);
1469
0
  else
1470
0
    tupleDesc = get_expr_result_tupdesc(expr, false);
1471
0
  Assert(tupleDesc);
1472
1473
  /* Generate a list of references to the individual fields */
1474
0
  numAttrs = tupleDesc->natts;
1475
0
  for (i = 0; i < numAttrs; i++)
1476
0
  {
1477
0
    Form_pg_attribute att = TupleDescAttr(tupleDesc, i);
1478
0
    FieldSelect *fselect;
1479
1480
0
    if (att->attisdropped)
1481
0
      continue;
1482
1483
0
    fselect = makeNode(FieldSelect);
1484
0
    fselect->arg = (Expr *) copyObject(expr);
1485
0
    fselect->fieldnum = i + 1;
1486
0
    fselect->resulttype = att->atttypid;
1487
0
    fselect->resulttypmod = att->atttypmod;
1488
    /* save attribute's collation for parse_collate.c */
1489
0
    fselect->resultcollid = att->attcollation;
1490
1491
0
    if (make_target_entry)
1492
0
    {
1493
      /* add TargetEntry decoration */
1494
0
      TargetEntry *te;
1495
1496
0
      te = makeTargetEntry((Expr *) fselect,
1497
0
                 (AttrNumber) pstate->p_next_resno++,
1498
0
                 pstrdup(NameStr(att->attname)),
1499
0
                 false);
1500
0
      result = lappend(result, te);
1501
0
    }
1502
0
    else
1503
0
      result = lappend(result, fselect);
1504
0
  }
1505
1506
0
  return result;
1507
0
}
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
expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
1523
0
{
1524
0
  TupleDesc tupleDesc;
1525
0
  int     netlevelsup;
1526
0
  RangeTblEntry *rte;
1527
0
  AttrNumber  attnum;
1528
0
  Node     *expr;
1529
1530
  /* Check my caller didn't mess up */
1531
0
  Assert(IsA(var, Var));
1532
0
  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
0
  netlevelsup = var->varlevelsup + levelsup;
1541
0
  rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup);
1542
0
  attnum = var->varattno;
1543
1544
0
  if (attnum == InvalidAttrNumber)
1545
0
  {
1546
    /* Whole-row reference to an RTE, so expand the known fields */
1547
0
    List     *names,
1548
0
           *vars;
1549
0
    ListCell   *lname,
1550
0
           *lvar;
1551
0
    int     i;
1552
1553
0
    expandRTE(rte, var->varno, 0, var->varreturningtype,
1554
0
          var->location, false, &names, &vars);
1555
1556
0
    tupleDesc = CreateTemplateTupleDesc(list_length(vars));
1557
0
    i = 1;
1558
0
    forboth(lname, names, lvar, vars)
1559
0
    {
1560
0
      char     *label = strVal(lfirst(lname));
1561
0
      Node     *varnode = (Node *) lfirst(lvar);
1562
1563
0
      TupleDescInitEntry(tupleDesc, i,
1564
0
                 label,
1565
0
                 exprType(varnode),
1566
0
                 exprTypmod(varnode),
1567
0
                 0);
1568
0
      TupleDescInitEntryCollation(tupleDesc, i,
1569
0
                    exprCollation(varnode));
1570
0
      i++;
1571
0
    }
1572
0
    Assert(lname == NULL && lvar == NULL);  /* lists same length? */
1573
1574
0
    return tupleDesc;
1575
0
  }
1576
1577
0
  expr = (Node *) var;    /* default if we can't drill down */
1578
1579
0
  switch (rte->rtekind)
1580
0
  {
1581
0
    case RTE_RELATION:
1582
0
    case RTE_VALUES:
1583
0
    case RTE_NAMEDTUPLESTORE:
1584
0
    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
0
    case RTE_SUBQUERY:
1593
0
      {
1594
        /* Subselect-in-FROM: examine sub-select's output expr */
1595
0
        TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
1596
0
                          attnum);
1597
1598
0
        if (ste == NULL || ste->resjunk)
1599
0
          elog(ERROR, "subquery %s does not have attribute %d",
1600
0
             rte->eref->aliasname, attnum);
1601
0
        expr = (Node *) ste->expr;
1602
0
        if (IsA(expr, Var))
1603
0
        {
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
0
          ParseState  mypstate = {0};
1613
0
          Index   levelsup;
1614
1615
          /* this loop must work, since GetRTEByRangeTablePosn did */
1616
0
          for (levelsup = 0; levelsup < netlevelsup; levelsup++)
1617
0
            pstate = pstate->parentParseState;
1618
0
          mypstate.parentParseState = pstate;
1619
0
          mypstate.p_rtable = rte->subquery->rtable;
1620
          /* don't bother filling the rest of the fake pstate */
1621
1622
0
          return expandRecordVariable(&mypstate, (Var *) expr, 0);
1623
0
        }
1624
        /* else fall through to inspect the expression */
1625
0
      }
1626
0
      break;
1627
0
    case RTE_JOIN:
1628
      /* Join RTE --- recursively inspect the alias variable */
1629
0
      Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
1630
0
      expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
1631
0
      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
0
    case RTE_CTE:
1651
      /* CTE reference: examine subquery's output expr */
1652
0
      if (!rte->self_reference)
1653
0
      {
1654
0
        CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup);
1655
0
        TargetEntry *ste;
1656
1657
0
        ste = get_tle_by_resno(GetCTETargetList(cte), attnum);
1658
0
        if (ste == NULL || ste->resjunk)
1659
0
          elog(ERROR, "CTE %s does not have attribute %d",
1660
0
             rte->eref->aliasname, attnum);
1661
0
        expr = (Node *) ste->expr;
1662
0
        if (IsA(expr, Var))
1663
0
        {
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
0
          ParseState  mypstate = {0};
1671
0
          Index   levelsup;
1672
1673
          /* this loop must work, since GetCTEForRTE did */
1674
0
          for (levelsup = 0;
1675
0
             levelsup < rte->ctelevelsup + netlevelsup;
1676
0
             levelsup++)
1677
0
            pstate = pstate->parentParseState;
1678
0
          mypstate.parentParseState = pstate;
1679
0
          mypstate.p_rtable = ((Query *) cte->ctequery)->rtable;
1680
          /* don't bother filling the rest of the fake pstate */
1681
1682
0
          return expandRecordVariable(&mypstate, (Var *) expr, 0);
1683
0
        }
1684
        /* else fall through to inspect the expression */
1685
0
      }
1686
0
      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
0
  }
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
0
  return get_expr_result_tupdesc(expr, false);
1700
0
}
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
FigureColname(Node *node)
1714
0
{
1715
0
  char     *name = NULL;
1716
1717
0
  (void) FigureColnameInternal(node, &name);
1718
0
  if (name != NULL)
1719
0
    return name;
1720
  /* default result if we can't guess anything */
1721
0
  return "?column?";
1722
0
}
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
FigureIndexColname(Node *node)
1733
0
{
1734
0
  char     *name = NULL;
1735
1736
0
  (void) FigureColnameInternal(node, &name);
1737
0
  return name;
1738
0
}
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
FigureColnameInternal(Node *node, char **name)
1753
0
{
1754
0
  int     strength = 0;
1755
1756
0
  if (node == NULL)
1757
0
    return strength;
1758
1759
0
  switch (nodeTag(node))
1760
0
  {
1761
0
    case T_ColumnRef:
1762
0
      {
1763
0
        char     *fname = NULL;
1764
0
        ListCell   *l;
1765
1766
        /* find last field name, if any, ignoring "*" */
1767
0
        foreach(l, ((ColumnRef *) node)->fields)
1768
0
        {
1769
0
          Node     *i = lfirst(l);
1770
1771
0
          if (IsA(i, String))
1772
0
            fname = strVal(i);
1773
0
        }
1774
0
        if (fname)
1775
0
        {
1776
0
          *name = fname;
1777
0
          return 2;
1778
0
        }
1779
0
      }
1780
0
      break;
1781
0
    case T_A_Indirection:
1782
0
      {
1783
0
        A_Indirection *ind = (A_Indirection *) node;
1784
0
        char     *fname = NULL;
1785
0
        ListCell   *l;
1786
1787
        /* find last field name, if any, ignoring "*" and subscripts */
1788
0
        foreach(l, ind->indirection)
1789
0
        {
1790
0
          Node     *i = lfirst(l);
1791
1792
0
          if (IsA(i, String))
1793
0
            fname = strVal(i);
1794
0
        }
1795
0
        if (fname)
1796
0
        {
1797
0
          *name = fname;
1798
0
          return 2;
1799
0
        }
1800
0
        return FigureColnameInternal(ind->arg, name);
1801
0
      }
1802
0
      break;
1803
0
    case T_FuncCall:
1804
0
      *name = strVal(llast(((FuncCall *) node)->funcname));
1805
0
      return 2;
1806
0
    case T_A_Expr:
1807
0
      if (((A_Expr *) node)->kind == AEXPR_NULLIF)
1808
0
      {
1809
        /* make nullif() act like a regular function */
1810
0
        *name = "nullif";
1811
0
        return 2;
1812
0
      }
1813
0
      break;
1814
0
    case T_TypeCast:
1815
0
      strength = FigureColnameInternal(((TypeCast *) node)->arg,
1816
0
                       name);
1817
0
      if (strength <= 1)
1818
0
      {
1819
0
        if (((TypeCast *) node)->typeName != NULL)
1820
0
        {
1821
0
          *name = strVal(llast(((TypeCast *) node)->typeName->names));
1822
0
          return 1;
1823
0
        }
1824
0
      }
1825
0
      break;
1826
0
    case T_CollateClause:
1827
0
      return FigureColnameInternal(((CollateClause *) node)->arg, name);
1828
0
    case T_GroupingFunc:
1829
      /* make GROUPING() act like a regular function */
1830
0
      *name = "grouping";
1831
0
      return 2;
1832
0
    case T_MergeSupportFunc:
1833
      /* make MERGE_ACTION() act like a regular function */
1834
0
      *name = "merge_action";
1835
0
      return 2;
1836
0
    case T_SubLink:
1837
0
      switch (((SubLink *) node)->subLinkType)
1838
0
      {
1839
0
        case EXISTS_SUBLINK:
1840
0
          *name = "exists";
1841
0
          return 2;
1842
0
        case ARRAY_SUBLINK:
1843
0
          *name = "array";
1844
0
          return 2;
1845
0
        case EXPR_SUBLINK:
1846
0
          {
1847
            /* Get column name of the subquery's single target */
1848
0
            SubLink    *sublink = (SubLink *) node;
1849
0
            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
0
            if (IsA(query, Query))
1859
0
            {
1860
0
              TargetEntry *te = (TargetEntry *) linitial(query->targetList);
1861
1862
0
              if (te->resname)
1863
0
              {
1864
0
                *name = te->resname;
1865
0
                return 2;
1866
0
              }
1867
0
            }
1868
0
          }
1869
0
          break;
1870
          /* As with other operator-like nodes, these have no names */
1871
0
        case MULTIEXPR_SUBLINK:
1872
0
        case ALL_SUBLINK:
1873
0
        case ANY_SUBLINK:
1874
0
        case ROWCOMPARE_SUBLINK:
1875
0
        case CTE_SUBLINK:
1876
0
          break;
1877
0
      }
1878
0
      break;
1879
0
    case T_CaseExpr:
1880
0
      strength = FigureColnameInternal((Node *) ((CaseExpr *) node)->defresult,
1881
0
                       name);
1882
0
      if (strength <= 1)
1883
0
      {
1884
0
        *name = "case";
1885
0
        return 1;
1886
0
      }
1887
0
      break;
1888
0
    case T_A_ArrayExpr:
1889
      /* make ARRAY[] act like a function */
1890
0
      *name = "array";
1891
0
      return 2;
1892
0
    case T_RowExpr:
1893
      /* make ROW() act like a function */
1894
0
      *name = "row";
1895
0
      return 2;
1896
0
    case T_CoalesceExpr:
1897
      /* make coalesce() act like a regular function */
1898
0
      *name = "coalesce";
1899
0
      return 2;
1900
0
    case T_MinMaxExpr:
1901
      /* make greatest/least act like a regular function */
1902
0
      switch (((MinMaxExpr *) node)->op)
1903
0
      {
1904
0
        case IS_GREATEST:
1905
0
          *name = "greatest";
1906
0
          return 2;
1907
0
        case IS_LEAST:
1908
0
          *name = "least";
1909
0
          return 2;
1910
0
      }
1911
0
      break;
1912
0
    case T_SQLValueFunction:
1913
      /* make these act like a function or variable */
1914
0
      switch (((SQLValueFunction *) node)->op)
1915
0
      {
1916
0
        case SVFOP_CURRENT_DATE:
1917
0
          *name = "current_date";
1918
0
          return 2;
1919
0
        case SVFOP_CURRENT_TIME:
1920
0
        case SVFOP_CURRENT_TIME_N:
1921
0
          *name = "current_time";
1922
0
          return 2;
1923
0
        case SVFOP_CURRENT_TIMESTAMP:
1924
0
        case SVFOP_CURRENT_TIMESTAMP_N:
1925
0
          *name = "current_timestamp";
1926
0
          return 2;
1927
0
        case SVFOP_LOCALTIME:
1928
0
        case SVFOP_LOCALTIME_N:
1929
0
          *name = "localtime";
1930
0
          return 2;
1931
0
        case SVFOP_LOCALTIMESTAMP:
1932
0
        case SVFOP_LOCALTIMESTAMP_N:
1933
0
          *name = "localtimestamp";
1934
0
          return 2;
1935
0
        case SVFOP_CURRENT_ROLE:
1936
0
          *name = "current_role";
1937
0
          return 2;
1938
0
        case SVFOP_CURRENT_USER:
1939
0
          *name = "current_user";
1940
0
          return 2;
1941
0
        case SVFOP_USER:
1942
0
          *name = "user";
1943
0
          return 2;
1944
0
        case SVFOP_SESSION_USER:
1945
0
          *name = "session_user";
1946
0
          return 2;
1947
0
        case SVFOP_CURRENT_CATALOG:
1948
0
          *name = "current_catalog";
1949
0
          return 2;
1950
0
        case SVFOP_CURRENT_SCHEMA:
1951
0
          *name = "current_schema";
1952
0
          return 2;
1953
0
      }
1954
0
      break;
1955
0
    case T_XmlExpr:
1956
      /* make SQL/XML functions act like a regular function */
1957
0
      switch (((XmlExpr *) node)->op)
1958
0
      {
1959
0
        case IS_XMLCONCAT:
1960
0
          *name = "xmlconcat";
1961
0
          return 2;
1962
0
        case IS_XMLELEMENT:
1963
0
          *name = "xmlelement";
1964
0
          return 2;
1965
0
        case IS_XMLFOREST:
1966
0
          *name = "xmlforest";
1967
0
          return 2;
1968
0
        case IS_XMLPARSE:
1969
0
          *name = "xmlparse";
1970
0
          return 2;
1971
0
        case IS_XMLPI:
1972
0
          *name = "xmlpi";
1973
0
          return 2;
1974
0
        case IS_XMLROOT:
1975
0
          *name = "xmlroot";
1976
0
          return 2;
1977
0
        case IS_XMLSERIALIZE:
1978
0
          *name = "xmlserialize";
1979
0
          return 2;
1980
0
        case IS_DOCUMENT:
1981
          /* nothing */
1982
0
          break;
1983
0
      }
1984
0
      break;
1985
0
    case T_XmlSerialize:
1986
      /* make XMLSERIALIZE act like a regular function */
1987
0
      *name = "xmlserialize";
1988
0
      return 2;
1989
0
    case T_JsonParseExpr:
1990
      /* make JSON act like a regular function */
1991
0
      *name = "json";
1992
0
      return 2;
1993
0
    case T_JsonScalarExpr:
1994
      /* make JSON_SCALAR act like a regular function */
1995
0
      *name = "json_scalar";
1996
0
      return 2;
1997
0
    case T_JsonSerializeExpr:
1998
      /* make JSON_SERIALIZE act like a regular function */
1999
0
      *name = "json_serialize";
2000
0
      return 2;
2001
0
    case T_JsonObjectConstructor:
2002
      /* make JSON_OBJECT act like a regular function */
2003
0
      *name = "json_object";
2004
0
      return 2;
2005
0
    case T_JsonArrayConstructor:
2006
0
    case T_JsonArrayQueryConstructor:
2007
      /* make JSON_ARRAY act like a regular function */
2008
0
      *name = "json_array";
2009
0
      return 2;
2010
0
    case T_JsonObjectAgg:
2011
      /* make JSON_OBJECTAGG act like a regular function */
2012
0
      *name = "json_objectagg";
2013
0
      return 2;
2014
0
    case T_JsonArrayAgg:
2015
      /* make JSON_ARRAYAGG act like a regular function */
2016
0
      *name = "json_arrayagg";
2017
0
      return 2;
2018
0
    case T_JsonFuncExpr:
2019
      /* make SQL/JSON functions act like a regular function */
2020
0
      switch (((JsonFuncExpr *) node)->op)
2021
0
      {
2022
0
        case JSON_EXISTS_OP:
2023
0
          *name = "json_exists";
2024
0
          return 2;
2025
0
        case JSON_QUERY_OP:
2026
0
          *name = "json_query";
2027
0
          return 2;
2028
0
        case JSON_VALUE_OP:
2029
0
          *name = "json_value";
2030
0
          return 2;
2031
          /* JSON_TABLE_OP can't happen here. */
2032
0
        default:
2033
0
          elog(ERROR, "unrecognized JsonExpr op: %d",
2034
0
             (int) ((JsonFuncExpr *) node)->op);
2035
0
      }
2036
0
      break;
2037
0
    default:
2038
0
      break;
2039
0
  }
2040
2041
0
  return strength;
2042
0
}