~ubuntu-branches/ubuntu/lucid/postgresql-8.4/lucid-security

« back to all changes in this revision

Viewing changes to src/backend/parser/parse_target.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-03-20 12:00:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090320120013-hogj7egc5mjncc5g
Tags: upstream-8.4~0cvs20090328
ImportĀ upstreamĀ versionĀ 8.4~0cvs20090328

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * parse_target.c
 
4
 *        handle target lists
 
5
 *
 
6
 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        $PostgreSQL$
 
12
 *
 
13
 *-------------------------------------------------------------------------
 
14
 */
 
15
#include "postgres.h"
 
16
 
 
17
#include "catalog/pg_type.h"
 
18
#include "commands/dbcommands.h"
 
19
#include "funcapi.h"
 
20
#include "miscadmin.h"
 
21
#include "nodes/makefuncs.h"
 
22
#include "nodes/nodeFuncs.h"
 
23
#include "parser/parsetree.h"
 
24
#include "parser/parse_coerce.h"
 
25
#include "parser/parse_expr.h"
 
26
#include "parser/parse_func.h"
 
27
#include "parser/parse_relation.h"
 
28
#include "parser/parse_target.h"
 
29
#include "parser/parse_type.h"
 
30
#include "utils/builtins.h"
 
31
#include "utils/lsyscache.h"
 
32
#include "utils/typcache.h"
 
33
 
 
34
 
 
35
static void markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
 
36
                                         Var *var, int levelsup);
 
37
static Node *transformAssignmentIndirection(ParseState *pstate,
 
38
                                                           Node *basenode,
 
39
                                                           const char *targetName,
 
40
                                                           bool targetIsArray,
 
41
                                                           Oid targetTypeId,
 
42
                                                           int32 targetTypMod,
 
43
                                                           ListCell *indirection,
 
44
                                                           Node *rhs,
 
45
                                                           int location);
 
46
static List *ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
 
47
                                        bool targetlist);
 
48
static List *ExpandAllTables(ParseState *pstate, int location);
 
49
static List *ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind,
 
50
                                          bool targetlist);
 
51
static int      FigureColnameInternal(Node *node, char **name);
 
52
 
 
53
 
 
54
/*
 
55
 * transformTargetEntry()
 
56
 *      Transform any ordinary "expression-type" node into a targetlist entry.
 
57
 *      This is exported so that parse_clause.c can generate targetlist entries
 
58
 *      for ORDER/GROUP BY items that are not already in the targetlist.
 
59
 *
 
60
 * node         the (untransformed) parse tree for the value expression.
 
61
 * expr         the transformed expression, or NULL if caller didn't do it yet.
 
62
 * colname      the column name to be assigned, or NULL if none yet set.
 
63
 * resjunk      true if the target should be marked resjunk, ie, it is not
 
64
 *                      wanted in the final projected tuple.
 
65
 */
 
66
TargetEntry *
 
67
transformTargetEntry(ParseState *pstate,
 
68
                                         Node *node,
 
69
                                         Node *expr,
 
70
                                         char *colname,
 
71
                                         bool resjunk)
 
72
{
 
73
        /* Transform the node if caller didn't do it already */
 
74
        if (expr == NULL)
 
75
                expr = transformExpr(pstate, node);
 
76
 
 
77
        if (colname == NULL && !resjunk)
 
78
        {
 
79
                /*
 
80
                 * Generate a suitable column name for a column without any explicit
 
81
                 * 'AS ColumnName' clause.
 
82
                 */
 
83
                colname = FigureColname(node);
 
84
        }
 
85
 
 
86
        return makeTargetEntry((Expr *) expr,
 
87
                                                   (AttrNumber) pstate->p_next_resno++,
 
88
                                                   colname,
 
89
                                                   resjunk);
 
90
}
 
91
 
 
92
 
 
93
/*
 
94
 * transformTargetList()
 
95
 * Turns a list of ResTarget's into a list of TargetEntry's.
 
96
 *
 
97
 * At this point, we don't care whether we are doing SELECT, INSERT,
 
98
 * or UPDATE; we just transform the given expressions (the "val" fields).
 
99
 */
 
100
List *
 
101
transformTargetList(ParseState *pstate, List *targetlist)
 
102
{
 
103
        List       *p_target = NIL;
 
104
        ListCell   *o_target;
 
105
 
 
106
        foreach(o_target, targetlist)
 
107
        {
 
108
                ResTarget  *res = (ResTarget *) lfirst(o_target);
 
109
 
 
110
                /*
 
111
                 * Check for "something.*".  Depending on the complexity of the
 
112
                 * "something", the star could appear as the last field in ColumnRef,
 
113
                 * or as the last indirection item in A_Indirection.
 
114
                 */
 
115
                if (IsA(res->val, ColumnRef))
 
116
                {
 
117
                        ColumnRef  *cref = (ColumnRef *) res->val;
 
118
 
 
119
                        if (IsA(llast(cref->fields), A_Star))
 
120
                        {
 
121
                                /* It is something.*, expand into multiple items */
 
122
                                p_target = list_concat(p_target,
 
123
                                                                           ExpandColumnRefStar(pstate, cref,
 
124
                                                                                                                   true));
 
125
                                continue;
 
126
                        }
 
127
                }
 
128
                else if (IsA(res->val, A_Indirection))
 
129
                {
 
130
                        A_Indirection *ind = (A_Indirection *) res->val;
 
131
 
 
132
                        if (IsA(llast(ind->indirection), A_Star))
 
133
                        {
 
134
                                /* It is something.*, expand into multiple items */
 
135
                                p_target = list_concat(p_target,
 
136
                                                                           ExpandIndirectionStar(pstate, ind,
 
137
                                                                                                                         true));
 
138
                                continue;
 
139
                        }
 
140
                }
 
141
 
 
142
                /*
 
143
                 * Not "something.*", so transform as a single expression
 
144
                 */
 
145
                p_target = lappend(p_target,
 
146
                                                   transformTargetEntry(pstate,
 
147
                                                                                                res->val,
 
148
                                                                                                NULL,
 
149
                                                                                                res->name,
 
150
                                                                                                false));
 
151
        }
 
152
 
 
153
        return p_target;
 
154
}
 
155
 
 
156
 
 
157
/*
 
158
 * transformExpressionList()
 
159
 *
 
160
 * This is the identical transformation to transformTargetList, except that
 
161
 * the input list elements are bare expressions without ResTarget decoration,
 
162
 * and the output elements are likewise just expressions without TargetEntry
 
163
 * decoration.  We use this for ROW() and VALUES() constructs.
 
164
 */
 
165
List *
 
166
transformExpressionList(ParseState *pstate, List *exprlist)
 
167
{
 
168
        List       *result = NIL;
 
169
        ListCell   *lc;
 
170
 
 
171
        foreach(lc, exprlist)
 
172
        {
 
173
                Node       *e = (Node *) lfirst(lc);
 
174
 
 
175
                /*
 
176
                 * Check for "something.*".  Depending on the complexity of the
 
177
                 * "something", the star could appear as the last field in ColumnRef,
 
178
                 * or as the last indirection item in A_Indirection.
 
179
                 */
 
180
                if (IsA(e, ColumnRef))
 
181
                {
 
182
                        ColumnRef  *cref = (ColumnRef *) e;
 
183
 
 
184
                        if (IsA(llast(cref->fields), A_Star))
 
185
                        {
 
186
                                /* It is something.*, expand into multiple items */
 
187
                                result = list_concat(result,
 
188
                                                                         ExpandColumnRefStar(pstate, cref,
 
189
                                                                                                                 false));
 
190
                                continue;
 
191
                        }
 
192
                }
 
193
                else if (IsA(e, A_Indirection))
 
194
                {
 
195
                        A_Indirection *ind = (A_Indirection *) e;
 
196
 
 
197
                        if (IsA(llast(ind->indirection), A_Star))
 
198
                        {
 
199
                                /* It is something.*, expand into multiple items */
 
200
                                result = list_concat(result,
 
201
                                                                         ExpandIndirectionStar(pstate, ind,
 
202
                                                                                                                   false));
 
203
                                continue;
 
204
                        }
 
205
                }
 
206
 
 
207
                /*
 
208
                 * Not "something.*", so transform as a single expression
 
209
                 */
 
210
                result = lappend(result,
 
211
                                                 transformExpr(pstate, e));
 
212
        }
 
213
 
 
214
        return result;
 
215
}
 
216
 
 
217
 
 
218
/*
 
219
 * markTargetListOrigins()
 
220
 *              Mark targetlist columns that are simple Vars with the source
 
221
 *              table's OID and column number.
 
222
 *
 
223
 * Currently, this is done only for SELECT targetlists, since we only
 
224
 * need the info if we are going to send it to the frontend.
 
225
 */
 
226
void
 
227
markTargetListOrigins(ParseState *pstate, List *targetlist)
 
228
{
 
229
        ListCell   *l;
 
230
 
 
231
        foreach(l, targetlist)
 
232
        {
 
233
                TargetEntry *tle = (TargetEntry *) lfirst(l);
 
234
 
 
235
                markTargetListOrigin(pstate, tle, (Var *) tle->expr, 0);
 
236
        }
 
237
}
 
238
 
 
239
/*
 
240
 * markTargetListOrigin()
 
241
 *              If 'var' is a Var of a plain relation, mark 'tle' with its origin
 
242
 *
 
243
 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
 
244
 *
 
245
 * This is split out so it can recurse for join references.  Note that we
 
246
 * do not drill down into views, but report the view as the column owner.
 
247
 */
 
248
static void
 
249
markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
 
250
                                         Var *var, int levelsup)
 
251
{
 
252
        int                     netlevelsup;
 
253
        RangeTblEntry *rte;
 
254
        AttrNumber      attnum;
 
255
 
 
256
        if (var == NULL || !IsA(var, Var))
 
257
                return;
 
258
        netlevelsup = var->varlevelsup + levelsup;
 
259
        rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup);
 
260
        attnum = var->varattno;
 
261
 
 
262
        switch (rte->rtekind)
 
263
        {
 
264
                case RTE_RELATION:
 
265
                        /* It's a table or view, report it */
 
266
                        tle->resorigtbl = rte->relid;
 
267
                        tle->resorigcol = attnum;
 
268
                        break;
 
269
                case RTE_SUBQUERY:
 
270
                        /* Subselect-in-FROM: copy up from the subselect */
 
271
                        if (attnum != InvalidAttrNumber)
 
272
                        {
 
273
                                TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
 
274
                                                                                                        attnum);
 
275
 
 
276
                                if (ste == NULL || ste->resjunk)
 
277
                                        elog(ERROR, "subquery %s does not have attribute %d",
 
278
                                                 rte->eref->aliasname, attnum);
 
279
                                tle->resorigtbl = ste->resorigtbl;
 
280
                                tle->resorigcol = ste->resorigcol;
 
281
                        }
 
282
                        break;
 
283
                case RTE_JOIN:
 
284
                        /* Join RTE --- recursively inspect the alias variable */
 
285
                        if (attnum != InvalidAttrNumber)
 
286
                        {
 
287
                                Var                *aliasvar;
 
288
 
 
289
                                Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
 
290
                                aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
 
291
                                markTargetListOrigin(pstate, tle, aliasvar, netlevelsup);
 
292
                        }
 
293
                        break;
 
294
                case RTE_SPECIAL:
 
295
                case RTE_FUNCTION:
 
296
                case RTE_VALUES:
 
297
                        /* not a simple relation, leave it unmarked */
 
298
                        break;
 
299
                case RTE_CTE:
 
300
                        /*
 
301
                         * CTE reference: copy up from the subquery, if possible.
 
302
                         * If the RTE is a recursive self-reference then we can't do
 
303
                         * anything because we haven't finished analyzing it yet.
 
304
                         * However, it's no big loss because we must be down inside
 
305
                         * the recursive term of a recursive CTE, and so any markings
 
306
                         * on the current targetlist are not going to affect the results
 
307
                         * anyway.
 
308
                         */
 
309
                        if (attnum != InvalidAttrNumber && !rte->self_reference)
 
310
                        {
 
311
                                CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup);
 
312
                                TargetEntry *ste;
 
313
 
 
314
                                /* should be analyzed by now */
 
315
                                Assert(IsA(cte->ctequery, Query));
 
316
                                ste = get_tle_by_resno(((Query *) cte->ctequery)->targetList,
 
317
                                                                           attnum);
 
318
                                if (ste == NULL || ste->resjunk)
 
319
                                        elog(ERROR, "subquery %s does not have attribute %d",
 
320
                                                 rte->eref->aliasname, attnum);
 
321
                                tle->resorigtbl = ste->resorigtbl;
 
322
                                tle->resorigcol = ste->resorigcol;
 
323
                        }
 
324
                        break;
 
325
        }
 
326
}
 
327
 
 
328
 
 
329
/*
 
330
 * transformAssignedExpr()
 
331
 *      This is used in INSERT and UPDATE statements only.      It prepares an
 
332
 *      expression for assignment to a column of the target table.
 
333
 *      This includes coercing the given value to the target column's type
 
334
 *      (if necessary), and dealing with any subfield names or subscripts
 
335
 *      attached to the target column itself.  The input expression has
 
336
 *      already been through transformExpr().
 
337
 *
 
338
 * pstate               parse state
 
339
 * expr                 expression to be modified
 
340
 * colname              target column name (ie, name of attribute to be assigned to)
 
341
 * attrno               target attribute number
 
342
 * indirection  subscripts/field names for target column, if any
 
343
 * location             error cursor position for the target column, or -1
 
344
 *
 
345
 * Returns the modified expression.
 
346
 *
 
347
 * Note: location points at the target column name (SET target or INSERT
 
348
 * column name list entry), and must therefore be -1 in an INSERT that
 
349
 * omits the column name list.  So we should usually prefer to use
 
350
 * exprLocation(expr) for errors that can happen in a default INSERT.
 
351
 */
 
352
Expr *
 
353
transformAssignedExpr(ParseState *pstate,
 
354
                                          Expr *expr,
 
355
                                          char *colname,
 
356
                                          int attrno,
 
357
                                          List *indirection,
 
358
                                          int location)
 
359
{
 
360
        Oid                     type_id;                /* type of value provided */
 
361
        Oid                     attrtype;               /* type of target column */
 
362
        int32           attrtypmod;
 
363
        Relation        rd = pstate->p_target_relation;
 
364
 
 
365
        Assert(rd != NULL);
 
366
        if (attrno <= 0)
 
367
                ereport(ERROR,
 
368
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
369
                                 errmsg("cannot assign to system column \"%s\"",
 
370
                                                colname),
 
371
                                 parser_errposition(pstate, location)));
 
372
        attrtype = attnumTypeId(rd, attrno);
 
373
        attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod;
 
374
 
 
375
        /*
 
376
         * If the expression is a DEFAULT placeholder, insert the attribute's
 
377
         * type/typmod into it so that exprType will report the right things. (We
 
378
         * expect that the eventually substituted default expression will in fact
 
379
         * have this type and typmod.)  Also, reject trying to update a subfield
 
380
         * or array element with DEFAULT, since there can't be any default for
 
381
         * portions of a column.
 
382
         */
 
383
        if (expr && IsA(expr, SetToDefault))
 
384
        {
 
385
                SetToDefault *def = (SetToDefault *) expr;
 
386
 
 
387
                def->typeId = attrtype;
 
388
                def->typeMod = attrtypmod;
 
389
                if (indirection)
 
390
                {
 
391
                        if (IsA(linitial(indirection), A_Indices))
 
392
                                ereport(ERROR,
 
393
                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
394
                                                 errmsg("cannot set an array element to DEFAULT"),
 
395
                                                 parser_errposition(pstate, location)));
 
396
                        else
 
397
                                ereport(ERROR,
 
398
                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
399
                                                 errmsg("cannot set a subfield to DEFAULT"),
 
400
                                                 parser_errposition(pstate, location)));
 
401
                }
 
402
        }
 
403
 
 
404
        /* Now we can use exprType() safely. */
 
405
        type_id = exprType((Node *) expr);
 
406
 
 
407
        /*
 
408
         * If there is indirection on the target column, prepare an array or
 
409
         * subfield assignment expression.      This will generate a new column value
 
410
         * that the source value has been inserted into, which can then be placed
 
411
         * in the new tuple constructed by INSERT or UPDATE.
 
412
         */
 
413
        if (indirection)
 
414
        {
 
415
                Node       *colVar;
 
416
 
 
417
                if (pstate->p_is_insert)
 
418
                {
 
419
                        /*
 
420
                         * The command is INSERT INTO table (col.something) ... so there
 
421
                         * is not really a source value to work with. Insert a NULL
 
422
                         * constant as the source value.
 
423
                         */
 
424
                        colVar = (Node *) makeNullConst(attrtype, attrtypmod);
 
425
                }
 
426
                else
 
427
                {
 
428
                        /*
 
429
                         * Build a Var for the column to be updated.
 
430
                         */
 
431
                        colVar = (Node *) make_var(pstate,
 
432
                                                                           pstate->p_target_rangetblentry,
 
433
                                                                           attrno,
 
434
                                                                           location);
 
435
                }
 
436
 
 
437
                expr = (Expr *)
 
438
                        transformAssignmentIndirection(pstate,
 
439
                                                                                   colVar,
 
440
                                                                                   colname,
 
441
                                                                                   false,
 
442
                                                                                   attrtype,
 
443
                                                                                   attrtypmod,
 
444
                                                                                   list_head(indirection),
 
445
                                                                                   (Node *) expr,
 
446
                                                                                   location);
 
447
        }
 
448
        else
 
449
        {
 
450
                /*
 
451
                 * For normal non-qualified target column, do type checking and
 
452
                 * coercion.
 
453
                 */
 
454
                Node   *orig_expr = (Node *) expr;
 
455
 
 
456
                expr = (Expr *)
 
457
                        coerce_to_target_type(pstate,
 
458
                                                                  orig_expr, type_id,
 
459
                                                                  attrtype, attrtypmod,
 
460
                                                                  COERCION_ASSIGNMENT,
 
461
                                                                  COERCE_IMPLICIT_CAST,
 
462
                                                                  -1);
 
463
                if (expr == NULL)
 
464
                        ereport(ERROR,
 
465
                                        (errcode(ERRCODE_DATATYPE_MISMATCH),
 
466
                                         errmsg("column \"%s\" is of type %s"
 
467
                                                        " but expression is of type %s",
 
468
                                                        colname,
 
469
                                                        format_type_be(attrtype),
 
470
                                                        format_type_be(type_id)),
 
471
                                 errhint("You will need to rewrite or cast the expression."),
 
472
                                         parser_errposition(pstate, exprLocation(orig_expr))));
 
473
        }
 
474
 
 
475
        return expr;
 
476
}
 
477
 
 
478
 
 
479
/*
 
480
 * updateTargetListEntry()
 
481
 *      This is used in UPDATE statements only. It prepares an UPDATE
 
482
 *      TargetEntry for assignment to a column of the target table.
 
483
 *      This includes coercing the given value to the target column's type
 
484
 *      (if necessary), and dealing with any subfield names or subscripts
 
485
 *      attached to the target column itself.
 
486
 *
 
487
 * pstate               parse state
 
488
 * tle                  target list entry to be modified
 
489
 * colname              target column name (ie, name of attribute to be assigned to)
 
490
 * attrno               target attribute number
 
491
 * indirection  subscripts/field names for target column, if any
 
492
 * location             error cursor position (should point at column name), or -1
 
493
 */
 
494
void
 
495
updateTargetListEntry(ParseState *pstate,
 
496
                                          TargetEntry *tle,
 
497
                                          char *colname,
 
498
                                          int attrno,
 
499
                                          List *indirection,
 
500
                                          int location)
 
501
{
 
502
        /* Fix up expression as needed */
 
503
        tle->expr = transformAssignedExpr(pstate,
 
504
                                                                          tle->expr,
 
505
                                                                          colname,
 
506
                                                                          attrno,
 
507
                                                                          indirection,
 
508
                                                                          location);
 
509
 
 
510
        /*
 
511
         * Set the resno to identify the target column --- the rewriter and
 
512
         * planner depend on this.      We also set the resname to identify the target
 
513
         * column, but this is only for debugging purposes; it should not be
 
514
         * relied on.  (In particular, it might be out of date in a stored rule.)
 
515
         */
 
516
        tle->resno = (AttrNumber) attrno;
 
517
        tle->resname = colname;
 
518
}
 
519
 
 
520
 
 
521
/*
 
522
 * Process indirection (field selection or subscripting) of the target
 
523
 * column in INSERT/UPDATE.  This routine recurses for multiple levels
 
524
 * of indirection --- but note that several adjacent A_Indices nodes in
 
525
 * the indirection list are treated as a single multidimensional subscript
 
526
 * operation.
 
527
 *
 
528
 * In the initial call, basenode is a Var for the target column in UPDATE,
 
529
 * or a null Const of the target's type in INSERT.  In recursive calls,
 
530
 * basenode is NULL, indicating that a substitute node should be consed up if
 
531
 * needed.
 
532
 *
 
533
 * targetName is the name of the field or subfield we're assigning to, and
 
534
 * targetIsArray is true if we're subscripting it.  These are just for
 
535
 * error reporting.
 
536
 *
 
537
 * targetTypeId and targetTypMod indicate the datatype of the object to
 
538
 * be assigned to (initially the target column, later some subobject).
 
539
 *
 
540
 * indirection is the sublist remaining to process.  When it's NULL, we're
 
541
 * done recursing and can just coerce and return the RHS.
 
542
 *
 
543
 * rhs is the already-transformed value to be assigned; note it has not been
 
544
 * coerced to any particular type.
 
545
 *
 
546
 * location is the cursor error position for any errors.  (Note: this points
 
547
 * to the head of the target clause, eg "foo" in "foo.bar[baz]".  Later we
 
548
 * might want to decorate indirection cells with their own location info,
 
549
 * in which case the location argument could probably be dropped.)
 
550
 */
 
551
static Node *
 
552
transformAssignmentIndirection(ParseState *pstate,
 
553
                                                           Node *basenode,
 
554
                                                           const char *targetName,
 
555
                                                           bool targetIsArray,
 
556
                                                           Oid targetTypeId,
 
557
                                                           int32 targetTypMod,
 
558
                                                           ListCell *indirection,
 
559
                                                           Node *rhs,
 
560
                                                           int location)
 
561
{
 
562
        Node       *result;
 
563
        List       *subscripts = NIL;
 
564
        bool            isSlice = false;
 
565
        ListCell   *i;
 
566
 
 
567
        if (indirection && !basenode)
 
568
        {
 
569
                /* Set up a substitution.  We reuse CaseTestExpr for this. */
 
570
                CaseTestExpr *ctest = makeNode(CaseTestExpr);
 
571
 
 
572
                ctest->typeId = targetTypeId;
 
573
                ctest->typeMod = targetTypMod;
 
574
                basenode = (Node *) ctest;
 
575
        }
 
576
 
 
577
        /*
 
578
         * We have to split any field-selection operations apart from
 
579
         * subscripting.  Adjacent A_Indices nodes have to be treated as a single
 
580
         * multidimensional subscript operation.
 
581
         */
 
582
        for_each_cell(i, indirection)
 
583
        {
 
584
                Node       *n = lfirst(i);
 
585
 
 
586
                if (IsA(n, A_Indices))
 
587
                {
 
588
                        subscripts = lappend(subscripts, n);
 
589
                        if (((A_Indices *) n)->lidx != NULL)
 
590
                                isSlice = true;
 
591
                }
 
592
                else if (IsA(n, A_Star))
 
593
                {
 
594
                        ereport(ERROR,
 
595
                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
596
                                         errmsg("row expansion via \"*\" is not supported here"),
 
597
                                         parser_errposition(pstate, location)));
 
598
                }
 
599
                else
 
600
                {
 
601
                        FieldStore *fstore;
 
602
                        Oid                     typrelid;
 
603
                        AttrNumber      attnum;
 
604
                        Oid                     fieldTypeId;
 
605
                        int32           fieldTypMod;
 
606
 
 
607
                        Assert(IsA(n, String));
 
608
 
 
609
                        /* process subscripts before this field selection */
 
610
                        if (subscripts)
 
611
                        {
 
612
                                Oid                     elementTypeId = transformArrayType(targetTypeId);
 
613
                                Oid                     typeNeeded = isSlice ? targetTypeId : elementTypeId;
 
614
 
 
615
                                /* recurse to create appropriate RHS for array assign */
 
616
                                rhs = transformAssignmentIndirection(pstate,
 
617
                                                                                                         NULL,
 
618
                                                                                                         targetName,
 
619
                                                                                                         true,
 
620
                                                                                                         typeNeeded,
 
621
                                                                                                         targetTypMod,
 
622
                                                                                                         i,
 
623
                                                                                                         rhs,
 
624
                                                                                                         location);
 
625
                                /* process subscripts */
 
626
                                return (Node *) transformArraySubscripts(pstate,
 
627
                                                                                                                 basenode,
 
628
                                                                                                                 targetTypeId,
 
629
                                                                                                                 elementTypeId,
 
630
                                                                                                                 targetTypMod,
 
631
                                                                                                                 subscripts,
 
632
                                                                                                                 rhs);
 
633
                        }
 
634
 
 
635
                        /* No subscripts, so can process field selection here */
 
636
 
 
637
                        typrelid = typeidTypeRelid(targetTypeId);
 
638
                        if (!typrelid)
 
639
                                ereport(ERROR,
 
640
                                                (errcode(ERRCODE_DATATYPE_MISMATCH),
 
641
                                                 errmsg("cannot assign to field \"%s\" of column \"%s\" because its type %s is not a composite type",
 
642
                                                                strVal(n), targetName,
 
643
                                                                format_type_be(targetTypeId)),
 
644
                                                 parser_errposition(pstate, location)));
 
645
 
 
646
                        attnum = get_attnum(typrelid, strVal(n));
 
647
                        if (attnum == InvalidAttrNumber)
 
648
                                ereport(ERROR,
 
649
                                                (errcode(ERRCODE_UNDEFINED_COLUMN),
 
650
                                                 errmsg("cannot assign to field \"%s\" of column \"%s\" because there is no such column in data type %s",
 
651
                                                                strVal(n), targetName,
 
652
                                                                format_type_be(targetTypeId)),
 
653
                                                 parser_errposition(pstate, location)));
 
654
                        if (attnum < 0)
 
655
                                ereport(ERROR,
 
656
                                                (errcode(ERRCODE_UNDEFINED_COLUMN),
 
657
                                                 errmsg("cannot assign to system column \"%s\"",
 
658
                                                                strVal(n)),
 
659
                                                 parser_errposition(pstate, location)));
 
660
 
 
661
                        get_atttypetypmod(typrelid, attnum,
 
662
                                                          &fieldTypeId, &fieldTypMod);
 
663
 
 
664
                        /* recurse to create appropriate RHS for field assign */
 
665
                        rhs = transformAssignmentIndirection(pstate,
 
666
                                                                                                 NULL,
 
667
                                                                                                 strVal(n),
 
668
                                                                                                 false,
 
669
                                                                                                 fieldTypeId,
 
670
                                                                                                 fieldTypMod,
 
671
                                                                                                 lnext(i),
 
672
                                                                                                 rhs,
 
673
                                                                                                 location);
 
674
 
 
675
                        /* and build a FieldStore node */
 
676
                        fstore = makeNode(FieldStore);
 
677
                        fstore->arg = (Expr *) basenode;
 
678
                        fstore->newvals = list_make1(rhs);
 
679
                        fstore->fieldnums = list_make1_int(attnum);
 
680
                        fstore->resulttype = targetTypeId;
 
681
 
 
682
                        return (Node *) fstore;
 
683
                }
 
684
        }
 
685
 
 
686
        /* process trailing subscripts, if any */
 
687
        if (subscripts)
 
688
        {
 
689
                Oid                     elementTypeId = transformArrayType(targetTypeId);
 
690
                Oid                     typeNeeded = isSlice ? targetTypeId : elementTypeId;
 
691
 
 
692
                /* recurse to create appropriate RHS for array assign */
 
693
                rhs = transformAssignmentIndirection(pstate,
 
694
                                                                                         NULL,
 
695
                                                                                         targetName,
 
696
                                                                                         true,
 
697
                                                                                         typeNeeded,
 
698
                                                                                         targetTypMod,
 
699
                                                                                         NULL,
 
700
                                                                                         rhs,
 
701
                                                                                         location);
 
702
                /* process subscripts */
 
703
                return (Node *) transformArraySubscripts(pstate,
 
704
                                                                                                 basenode,
 
705
                                                                                                 targetTypeId,
 
706
                                                                                                 elementTypeId,
 
707
                                                                                                 targetTypMod,
 
708
                                                                                                 subscripts,
 
709
                                                                                                 rhs);
 
710
        }
 
711
 
 
712
        /* base case: just coerce RHS to match target type ID */
 
713
 
 
714
        result = coerce_to_target_type(pstate,
 
715
                                                                   rhs, exprType(rhs),
 
716
                                                                   targetTypeId, targetTypMod,
 
717
                                                                   COERCION_ASSIGNMENT,
 
718
                                                                   COERCE_IMPLICIT_CAST,
 
719
                                                                   -1);
 
720
        if (result == NULL)
 
721
        {
 
722
                if (targetIsArray)
 
723
                        ereport(ERROR,
 
724
                                        (errcode(ERRCODE_DATATYPE_MISMATCH),
 
725
                                         errmsg("array assignment to \"%s\" requires type %s"
 
726
                                                        " but expression is of type %s",
 
727
                                                        targetName,
 
728
                                                        format_type_be(targetTypeId),
 
729
                                                        format_type_be(exprType(rhs))),
 
730
                                 errhint("You will need to rewrite or cast the expression."),
 
731
                                         parser_errposition(pstate, location)));
 
732
                else
 
733
                        ereport(ERROR,
 
734
                                        (errcode(ERRCODE_DATATYPE_MISMATCH),
 
735
                                         errmsg("subfield \"%s\" is of type %s"
 
736
                                                        " but expression is of type %s",
 
737
                                                        targetName,
 
738
                                                        format_type_be(targetTypeId),
 
739
                                                        format_type_be(exprType(rhs))),
 
740
                                 errhint("You will need to rewrite or cast the expression."),
 
741
                                         parser_errposition(pstate, location)));
 
742
        }
 
743
 
 
744
        return result;
 
745
}
 
746
 
 
747
 
 
748
/*
 
749
 * checkInsertTargets -
 
750
 *        generate a list of INSERT column targets if not supplied, or
 
751
 *        test supplied column names to make sure they are in target table.
 
752
 *        Also return an integer list of the columns' attribute numbers.
 
753
 */
 
754
List *
 
755
checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
 
756
{
 
757
        *attrnos = NIL;
 
758
 
 
759
        if (cols == NIL)
 
760
        {
 
761
                /*
 
762
                 * Generate default column list for INSERT.
 
763
                 */
 
764
                Form_pg_attribute *attr = pstate->p_target_relation->rd_att->attrs;
 
765
                int                     numcol = pstate->p_target_relation->rd_rel->relnatts;
 
766
                int                     i;
 
767
 
 
768
                for (i = 0; i < numcol; i++)
 
769
                {
 
770
                        ResTarget  *col;
 
771
 
 
772
                        if (attr[i]->attisdropped)
 
773
                                continue;
 
774
 
 
775
                        col = makeNode(ResTarget);
 
776
                        col->name = pstrdup(NameStr(attr[i]->attname));
 
777
                        col->indirection = NIL;
 
778
                        col->val = NULL;
 
779
                        col->location = -1;
 
780
                        cols = lappend(cols, col);
 
781
                        *attrnos = lappend_int(*attrnos, i + 1);
 
782
                }
 
783
        }
 
784
        else
 
785
        {
 
786
                /*
 
787
                 * Do initial validation of user-supplied INSERT column list.
 
788
                 */
 
789
                Bitmapset  *wholecols = NULL;
 
790
                Bitmapset  *partialcols = NULL;
 
791
                ListCell   *tl;
 
792
 
 
793
                foreach(tl, cols)
 
794
                {
 
795
                        ResTarget  *col = (ResTarget *) lfirst(tl);
 
796
                        char       *name = col->name;
 
797
                        int                     attrno;
 
798
 
 
799
                        /* Lookup column name, ereport on failure */
 
800
                        attrno = attnameAttNum(pstate->p_target_relation, name, false);
 
801
                        if (attrno == InvalidAttrNumber)
 
802
                                ereport(ERROR,
 
803
                                                (errcode(ERRCODE_UNDEFINED_COLUMN),
 
804
                                        errmsg("column \"%s\" of relation \"%s\" does not exist",
 
805
                                                   name,
 
806
                                                 RelationGetRelationName(pstate->p_target_relation)),
 
807
                                                 parser_errposition(pstate, col->location)));
 
808
 
 
809
                        /*
 
810
                         * Check for duplicates, but only of whole columns --- we allow
 
811
                         * INSERT INTO foo (col.subcol1, col.subcol2)
 
812
                         */
 
813
                        if (col->indirection == NIL)
 
814
                        {
 
815
                                /* whole column; must not have any other assignment */
 
816
                                if (bms_is_member(attrno, wholecols) ||
 
817
                                        bms_is_member(attrno, partialcols))
 
818
                                        ereport(ERROR,
 
819
                                                        (errcode(ERRCODE_DUPLICATE_COLUMN),
 
820
                                                         errmsg("column \"%s\" specified more than once",
 
821
                                                                        name),
 
822
                                                         parser_errposition(pstate, col->location)));
 
823
                                wholecols = bms_add_member(wholecols, attrno);
 
824
                        }
 
825
                        else
 
826
                        {
 
827
                                /* partial column; must not have any whole assignment */
 
828
                                if (bms_is_member(attrno, wholecols))
 
829
                                        ereport(ERROR,
 
830
                                                        (errcode(ERRCODE_DUPLICATE_COLUMN),
 
831
                                                         errmsg("column \"%s\" specified more than once",
 
832
                                                                        name),
 
833
                                                         parser_errposition(pstate, col->location)));
 
834
                                partialcols = bms_add_member(partialcols, attrno);
 
835
                        }
 
836
 
 
837
                        *attrnos = lappend_int(*attrnos, attrno);
 
838
                }
 
839
        }
 
840
 
 
841
        return cols;
 
842
}
 
843
 
 
844
/*
 
845
 * ExpandColumnRefStar()
 
846
 *              Transforms foo.* into a list of expressions or targetlist entries.
 
847
 *
 
848
 * This handles the case where '*' appears as the last or only item in a
 
849
 * ColumnRef.  The code is shared between the case of foo.* at the top level
 
850
 * in a SELECT target list (where we want TargetEntry nodes in the result)
 
851
 * and foo.* in a ROW() or VALUES() construct (where we want just bare
 
852
 * expressions).
 
853
 *
 
854
 * The referenced columns are marked as requiring SELECT access.
 
855
 */
 
856
static List *
 
857
ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
 
858
                                        bool targetlist)
 
859
{
 
860
        List       *fields = cref->fields;
 
861
        int                     numnames = list_length(fields);
 
862
 
 
863
        if (numnames == 1)
 
864
        {
 
865
                /*
 
866
                 * Target item is a bare '*', expand all tables
 
867
                 *
 
868
                 * (e.g., SELECT * FROM emp, dept)
 
869
                 *
 
870
                 * Since the grammar only accepts bare '*' at top level of SELECT, we
 
871
                 * need not handle the targetlist==false case here.
 
872
                 */
 
873
                Assert(targetlist);
 
874
                return ExpandAllTables(pstate, cref->location);
 
875
        }
 
876
        else
 
877
        {
 
878
                /*
 
879
                 * Target item is relation.*, expand that table
 
880
                 *
 
881
                 * (e.g., SELECT emp.*, dname FROM emp, dept)
 
882
                 */
 
883
                char       *schemaname;
 
884
                char       *relname;
 
885
                RangeTblEntry *rte;
 
886
                int                     sublevels_up;
 
887
                int                     rtindex;
 
888
 
 
889
                switch (numnames)
 
890
                {
 
891
                        case 2:
 
892
                                schemaname = NULL;
 
893
                                relname = strVal(linitial(fields));
 
894
                                break;
 
895
                        case 3:
 
896
                                schemaname = strVal(linitial(fields));
 
897
                                relname = strVal(lsecond(fields));
 
898
                                break;
 
899
                        case 4:
 
900
                                {
 
901
                                        char       *name1 = strVal(linitial(fields));
 
902
 
 
903
                                        /*
 
904
                                         * We check the catalog name and then ignore it.
 
905
                                         */
 
906
                                        if (strcmp(name1, get_database_name(MyDatabaseId)) != 0)
 
907
                                                ereport(ERROR,
 
908
                                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
909
                                                                 errmsg("cross-database references are not implemented: %s",
 
910
                                                                                NameListToString(fields)),
 
911
                                                                 parser_errposition(pstate, cref->location)));
 
912
                                        schemaname = strVal(lsecond(fields));
 
913
                                        relname = strVal(lthird(fields));
 
914
                                        break;
 
915
                                }
 
916
                        default:
 
917
                                ereport(ERROR,
 
918
                                                (errcode(ERRCODE_SYNTAX_ERROR),
 
919
                                errmsg("improper qualified name (too many dotted names): %s",
 
920
                                           NameListToString(fields)),
 
921
                                                 parser_errposition(pstate, cref->location)));
 
922
                                schemaname = NULL;              /* keep compiler quiet */
 
923
                                relname = NULL;
 
924
                                break;
 
925
                }
 
926
 
 
927
                rte = refnameRangeTblEntry(pstate, schemaname, relname, cref->location,
 
928
                                                                   &sublevels_up);
 
929
                if (rte == NULL)
 
930
                        rte = addImplicitRTE(pstate,
 
931
                                                                 makeRangeVar(schemaname, relname,
 
932
                                                                                          cref->location));
 
933
 
 
934
                rtindex = RTERangeTablePosn(pstate, rte, &sublevels_up);
 
935
 
 
936
                if (targetlist)
 
937
                {
 
938
                        /* expandRelAttrs handles permissions marking */
 
939
                        return expandRelAttrs(pstate, rte, rtindex, sublevels_up,
 
940
                                                                  cref->location);
 
941
                }
 
942
                else
 
943
                {
 
944
                        List       *vars;
 
945
                        ListCell   *l;
 
946
 
 
947
                        expandRTE(rte, rtindex, sublevels_up, cref->location, false,
 
948
                                          NULL, &vars);
 
949
 
 
950
                        /*
 
951
                         * Require read access to the table.  This is normally redundant
 
952
                         * with the markVarForSelectPriv calls below, but not if the table
 
953
                         * has zero columns.
 
954
                         */
 
955
                        rte->requiredPerms |= ACL_SELECT;
 
956
 
 
957
                        /* Require read access to each column */
 
958
                        foreach(l, vars)
 
959
                        {
 
960
                                Var        *var = (Var *) lfirst(l);
 
961
 
 
962
                                markVarForSelectPriv(pstate, var, rte);
 
963
                        }
 
964
 
 
965
                        return vars;
 
966
                }
 
967
        }
 
968
}
 
969
 
 
970
/*
 
971
 * ExpandAllTables()
 
972
 *              Transforms '*' (in the target list) into a list of targetlist entries.
 
973
 *
 
974
 * tlist entries are generated for each relation appearing in the query's
 
975
 * varnamespace.  We do not consider relnamespace because that would include
 
976
 * input tables of aliasless JOINs, NEW/OLD pseudo-entries, implicit RTEs,
 
977
 * etc.
 
978
 *
 
979
 * The referenced relations/columns are marked as requiring SELECT access.
 
980
 */
 
981
static List *
 
982
ExpandAllTables(ParseState *pstate, int location)
 
983
{
 
984
        List       *target = NIL;
 
985
        ListCell   *l;
 
986
 
 
987
        /* Check for SELECT *; */
 
988
        if (!pstate->p_varnamespace)
 
989
                ereport(ERROR,
 
990
                                (errcode(ERRCODE_SYNTAX_ERROR),
 
991
                                 errmsg("SELECT * with no tables specified is not valid"),
 
992
                                 parser_errposition(pstate, location)));
 
993
 
 
994
        foreach(l, pstate->p_varnamespace)
 
995
        {
 
996
                RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
 
997
                int                     rtindex = RTERangeTablePosn(pstate, rte, NULL);
 
998
 
 
999
                target = list_concat(target,
 
1000
                                                         expandRelAttrs(pstate, rte, rtindex, 0,
 
1001
                                                                                        location));
 
1002
        }
 
1003
 
 
1004
        return target;
 
1005
}
 
1006
 
 
1007
/*
 
1008
 * ExpandIndirectionStar()
 
1009
 *              Transforms foo.* into a list of expressions or targetlist entries.
 
1010
 *
 
1011
 * This handles the case where '*' appears as the last item in A_Indirection.
 
1012
 * The code is shared between the case of foo.* at the top level in a SELECT
 
1013
 * target list (where we want TargetEntry nodes in the result) and foo.* in
 
1014
 * a ROW() or VALUES() construct (where we want just bare expressions).
 
1015
 */
 
1016
static List *
 
1017
ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind,
 
1018
                                          bool targetlist)
 
1019
{
 
1020
        List       *result = NIL;
 
1021
        Node       *expr;
 
1022
        TupleDesc       tupleDesc;
 
1023
        int                     numAttrs;
 
1024
        int                     i;
 
1025
 
 
1026
        /* Strip off the '*' to create a reference to the rowtype object */
 
1027
        ind = copyObject(ind);
 
1028
        ind->indirection = list_truncate(ind->indirection,
 
1029
                                                                         list_length(ind->indirection) - 1);
 
1030
 
 
1031
        /* And transform that */
 
1032
        expr = transformExpr(pstate, (Node *) ind);
 
1033
 
 
1034
        /*
 
1035
         * Verify it's a composite type, and get the tupdesc.  We use
 
1036
         * get_expr_result_type() because that can handle references to functions
 
1037
         * returning anonymous record types.  If that fails, use
 
1038
         * lookup_rowtype_tupdesc(), which will almost certainly fail as well, but
 
1039
         * it will give an appropriate error message.
 
1040
         *
 
1041
         * If it's a Var of type RECORD, we have to work even harder: we have to
 
1042
         * find what the Var refers to, and pass that to get_expr_result_type.
 
1043
         * That task is handled by expandRecordVariable().
 
1044
         */
 
1045
        if (IsA(expr, Var) &&
 
1046
                ((Var *) expr)->vartype == RECORDOID)
 
1047
                tupleDesc = expandRecordVariable(pstate, (Var *) expr, 0);
 
1048
        else if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
 
1049
                tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
 
1050
                                                                                                exprTypmod(expr));
 
1051
        Assert(tupleDesc);
 
1052
 
 
1053
        /* Generate a list of references to the individual fields */
 
1054
        numAttrs = tupleDesc->natts;
 
1055
        for (i = 0; i < numAttrs; i++)
 
1056
        {
 
1057
                Form_pg_attribute att = tupleDesc->attrs[i];
 
1058
                Node       *fieldnode;
 
1059
 
 
1060
                if (att->attisdropped)
 
1061
                        continue;
 
1062
 
 
1063
                /*
 
1064
                 * If we got a whole-row Var from the rowtype reference, we can expand
 
1065
                 * the fields as simple Vars.  Otherwise we must generate multiple
 
1066
                 * copies of the rowtype reference and do FieldSelects.
 
1067
                 */
 
1068
                if (IsA(expr, Var) &&
 
1069
                        ((Var *) expr)->varattno == InvalidAttrNumber)
 
1070
                {
 
1071
                        Var                *var = (Var *) expr;
 
1072
                        Var                *newvar;
 
1073
 
 
1074
                        newvar = makeVar(var->varno,
 
1075
                                                         i + 1,
 
1076
                                                         att->atttypid,
 
1077
                                                         att->atttypmod,
 
1078
                                                         var->varlevelsup);
 
1079
                        newvar->location = var->location;
 
1080
 
 
1081
                        fieldnode = (Node *) newvar;
 
1082
                }
 
1083
                else
 
1084
                {
 
1085
                        FieldSelect *fselect = makeNode(FieldSelect);
 
1086
 
 
1087
                        fselect->arg = (Expr *) copyObject(expr);
 
1088
                        fselect->fieldnum = i + 1;
 
1089
                        fselect->resulttype = att->atttypid;
 
1090
                        fselect->resulttypmod = att->atttypmod;
 
1091
 
 
1092
                        fieldnode = (Node *) fselect;
 
1093
                }
 
1094
 
 
1095
                if (targetlist)
 
1096
                {
 
1097
                        /* add TargetEntry decoration */
 
1098
                        TargetEntry *te;
 
1099
 
 
1100
                        te = makeTargetEntry((Expr *) fieldnode,
 
1101
                                                                 (AttrNumber) pstate->p_next_resno++,
 
1102
                                                                 pstrdup(NameStr(att->attname)),
 
1103
                                                                 false);
 
1104
                        result = lappend(result, te);
 
1105
                }
 
1106
                else
 
1107
                        result = lappend(result, fieldnode);
 
1108
        }
 
1109
 
 
1110
        return result;
 
1111
}
 
1112
 
 
1113
/*
 
1114
 * expandRecordVariable
 
1115
 *              Get the tuple descriptor for a Var of type RECORD, if possible.
 
1116
 *
 
1117
 * Since no actual table or view column is allowed to have type RECORD, such
 
1118
 * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output.  We
 
1119
 * drill down to find the ultimate defining expression and attempt to infer
 
1120
 * the tupdesc from it.  We ereport if we can't determine the tupdesc.
 
1121
 *
 
1122
 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
 
1123
 */
 
1124
TupleDesc
 
1125
expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
 
1126
{
 
1127
        TupleDesc       tupleDesc;
 
1128
        int                     netlevelsup;
 
1129
        RangeTblEntry *rte;
 
1130
        AttrNumber      attnum;
 
1131
        Node       *expr;
 
1132
 
 
1133
        /* Check my caller didn't mess up */
 
1134
        Assert(IsA(var, Var));
 
1135
        Assert(var->vartype == RECORDOID);
 
1136
 
 
1137
        netlevelsup = var->varlevelsup + levelsup;
 
1138
        rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup);
 
1139
        attnum = var->varattno;
 
1140
 
 
1141
        if (attnum == InvalidAttrNumber)
 
1142
        {
 
1143
                /* Whole-row reference to an RTE, so expand the known fields */
 
1144
                List       *names,
 
1145
                                   *vars;
 
1146
                ListCell   *lname,
 
1147
                                   *lvar;
 
1148
                int                     i;
 
1149
 
 
1150
                expandRTE(rte, var->varno, 0, var->location, false,
 
1151
                                  &names, &vars);
 
1152
 
 
1153
                tupleDesc = CreateTemplateTupleDesc(list_length(vars), false);
 
1154
                i = 1;
 
1155
                forboth(lname, names, lvar, vars)
 
1156
                {
 
1157
                        char       *label = strVal(lfirst(lname));
 
1158
                        Node       *varnode = (Node *) lfirst(lvar);
 
1159
 
 
1160
                        TupleDescInitEntry(tupleDesc, i,
 
1161
                                                           label,
 
1162
                                                           exprType(varnode),
 
1163
                                                           exprTypmod(varnode),
 
1164
                                                           0);
 
1165
                        i++;
 
1166
                }
 
1167
                Assert(lname == NULL && lvar == NULL);  /* lists same length? */
 
1168
 
 
1169
                return tupleDesc;
 
1170
        }
 
1171
 
 
1172
        expr = (Node *) var;            /* default if we can't drill down */
 
1173
 
 
1174
        switch (rte->rtekind)
 
1175
        {
 
1176
                case RTE_RELATION:
 
1177
                case RTE_SPECIAL:
 
1178
                case RTE_VALUES:
 
1179
 
 
1180
                        /*
 
1181
                         * This case should not occur: a column of a table or values list
 
1182
                         * shouldn't have type RECORD.  Fall through and fail (most
 
1183
                         * likely) at the bottom.
 
1184
                         */
 
1185
                        break;
 
1186
                case RTE_SUBQUERY:
 
1187
                        {
 
1188
                                /* Subselect-in-FROM: examine sub-select's output expr */
 
1189
                                TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
 
1190
                                                                                                        attnum);
 
1191
 
 
1192
                                if (ste == NULL || ste->resjunk)
 
1193
                                        elog(ERROR, "subquery %s does not have attribute %d",
 
1194
                                                 rte->eref->aliasname, attnum);
 
1195
                                expr = (Node *) ste->expr;
 
1196
                                if (IsA(expr, Var))
 
1197
                                {
 
1198
                                        /*
 
1199
                                         * Recurse into the sub-select to see what its Var refers
 
1200
                                         * to.  We have to build an additional level of ParseState
 
1201
                                         * to keep in step with varlevelsup in the subselect.
 
1202
                                         */
 
1203
                                        ParseState      mypstate;
 
1204
 
 
1205
                                        MemSet(&mypstate, 0, sizeof(mypstate));
 
1206
                                        mypstate.parentParseState = pstate;
 
1207
                                        mypstate.p_rtable = rte->subquery->rtable;
 
1208
                                        /* don't bother filling the rest of the fake pstate */
 
1209
 
 
1210
                                        return expandRecordVariable(&mypstate, (Var *) expr, 0);
 
1211
                                }
 
1212
                                /* else fall through to inspect the expression */
 
1213
                        }
 
1214
                        break;
 
1215
                case RTE_JOIN:
 
1216
                        /* Join RTE --- recursively inspect the alias variable */
 
1217
                        Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
 
1218
                        expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
 
1219
                        if (IsA(expr, Var))
 
1220
                                return expandRecordVariable(pstate, (Var *) expr, netlevelsup);
 
1221
                        /* else fall through to inspect the expression */
 
1222
                        break;
 
1223
                case RTE_FUNCTION:
 
1224
 
 
1225
                        /*
 
1226
                         * We couldn't get here unless a function is declared with one of
 
1227
                         * its result columns as RECORD, which is not allowed.
 
1228
                         */
 
1229
                        break;
 
1230
                case RTE_CTE:
 
1231
                        /* CTE reference: examine subquery's output expr */
 
1232
                        if (!rte->self_reference)
 
1233
                        {
 
1234
                                CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup);
 
1235
                                TargetEntry *ste;
 
1236
 
 
1237
                                /* should be analyzed by now */
 
1238
                                Assert(IsA(cte->ctequery, Query));
 
1239
                                ste = get_tle_by_resno(((Query *) cte->ctequery)->targetList,
 
1240
                                                                           attnum);
 
1241
                                if (ste == NULL || ste->resjunk)
 
1242
                                        elog(ERROR, "subquery %s does not have attribute %d",
 
1243
                                                 rte->eref->aliasname, attnum);
 
1244
                                expr = (Node *) ste->expr;
 
1245
                                if (IsA(expr, Var))
 
1246
                                {
 
1247
                                        /*
 
1248
                                         * Recurse into the CTE to see what its Var refers to. We
 
1249
                                         * have to build an additional level of ParseState to keep
 
1250
                                         * in step with varlevelsup in the CTE; furthermore it
 
1251
                                         * could be an outer CTE.
 
1252
                                         */
 
1253
                                        ParseState      mypstate;
 
1254
                                        Index           levelsup;
 
1255
 
 
1256
                                        MemSet(&mypstate, 0, sizeof(mypstate));
 
1257
                                        /* this loop must work, since GetCTEForRTE did */
 
1258
                                        for (levelsup = 0;
 
1259
                                                 levelsup < rte->ctelevelsup + netlevelsup;
 
1260
                                                 levelsup++)
 
1261
                                                pstate = pstate->parentParseState;
 
1262
                                        mypstate.parentParseState = pstate;
 
1263
                                        mypstate.p_rtable = ((Query *) cte->ctequery)->rtable;
 
1264
                                        /* don't bother filling the rest of the fake pstate */
 
1265
 
 
1266
                                        return expandRecordVariable(&mypstate, (Var *) expr, 0);
 
1267
                                }
 
1268
                                /* else fall through to inspect the expression */
 
1269
                        }
 
1270
                        break;
 
1271
        }
 
1272
 
 
1273
        /*
 
1274
         * We now have an expression we can't expand any more, so see if
 
1275
         * get_expr_result_type() can do anything with it.      If not, pass to
 
1276
         * lookup_rowtype_tupdesc() which will probably fail, but will give an
 
1277
         * appropriate error message while failing.
 
1278
         */
 
1279
        if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
 
1280
                tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
 
1281
                                                                                                exprTypmod(expr));
 
1282
 
 
1283
        return tupleDesc;
 
1284
}
 
1285
 
 
1286
 
 
1287
/*
 
1288
 * FigureColname -
 
1289
 *        if the name of the resulting column is not specified in the target
 
1290
 *        list, we have to guess a suitable name.  The SQL spec provides some
 
1291
 *        guidance, but not much...
 
1292
 *
 
1293
 * Note that the argument is the *untransformed* parse tree for the target
 
1294
 * item.  This is a shade easier to work with than the transformed tree.
 
1295
 */
 
1296
char *
 
1297
FigureColname(Node *node)
 
1298
{
 
1299
        char       *name = NULL;
 
1300
 
 
1301
        FigureColnameInternal(node, &name);
 
1302
        if (name != NULL)
 
1303
                return name;
 
1304
        /* default result if we can't guess anything */
 
1305
        return "?column?";
 
1306
}
 
1307
 
 
1308
static int
 
1309
FigureColnameInternal(Node *node, char **name)
 
1310
{
 
1311
        int                     strength = 0;
 
1312
 
 
1313
        if (node == NULL)
 
1314
                return strength;
 
1315
 
 
1316
        switch (nodeTag(node))
 
1317
        {
 
1318
                case T_ColumnRef:
 
1319
                        {
 
1320
                                char       *fname = NULL;
 
1321
                                ListCell   *l;
 
1322
 
 
1323
                                /* find last field name, if any, ignoring "*" */
 
1324
                                foreach(l, ((ColumnRef *) node)->fields)
 
1325
                                {
 
1326
                                        Node       *i = lfirst(l);
 
1327
 
 
1328
                                        if (IsA(i, String))
 
1329
                                                fname = strVal(i);
 
1330
                                }
 
1331
                                if (fname)
 
1332
                                {
 
1333
                                        *name = fname;
 
1334
                                        return 2;
 
1335
                                }
 
1336
                        }
 
1337
                        break;
 
1338
                case T_A_Indirection:
 
1339
                        {
 
1340
                                A_Indirection *ind = (A_Indirection *) node;
 
1341
                                char       *fname = NULL;
 
1342
                                ListCell   *l;
 
1343
 
 
1344
                                /* find last field name, if any, ignoring "*" and subscripts */
 
1345
                                foreach(l, ind->indirection)
 
1346
                                {
 
1347
                                        Node       *i = lfirst(l);
 
1348
 
 
1349
                                        if (IsA(i, String))
 
1350
                                                fname = strVal(i);
 
1351
                                }
 
1352
                                if (fname)
 
1353
                                {
 
1354
                                        *name = fname;
 
1355
                                        return 2;
 
1356
                                }
 
1357
                                return FigureColnameInternal(ind->arg, name);
 
1358
                        }
 
1359
                        break;
 
1360
                case T_FuncCall:
 
1361
                        *name = strVal(llast(((FuncCall *) node)->funcname));
 
1362
                        return 2;
 
1363
                case T_A_Expr:
 
1364
                        /* make nullif() act like a regular function */
 
1365
                        if (((A_Expr *) node)->kind == AEXPR_NULLIF)
 
1366
                        {
 
1367
                                *name = "nullif";
 
1368
                                return 2;
 
1369
                        }
 
1370
                        break;
 
1371
                case T_TypeCast:
 
1372
                        strength = FigureColnameInternal(((TypeCast *) node)->arg,
 
1373
                                                                                         name);
 
1374
                        if (strength <= 1)
 
1375
                        {
 
1376
                                if (((TypeCast *) node)->typename != NULL)
 
1377
                                {
 
1378
                                        *name = strVal(llast(((TypeCast *) node)->typename->names));
 
1379
                                        return 1;
 
1380
                                }
 
1381
                        }
 
1382
                        break;
 
1383
                case T_CaseExpr:
 
1384
                        strength = FigureColnameInternal((Node *) ((CaseExpr *) node)->defresult,
 
1385
                                                                                         name);
 
1386
                        if (strength <= 1)
 
1387
                        {
 
1388
                                *name = "case";
 
1389
                                return 1;
 
1390
                        }
 
1391
                        break;
 
1392
                case T_A_ArrayExpr:
 
1393
                        /* make ARRAY[] act like a function */
 
1394
                        *name = "array";
 
1395
                        return 2;
 
1396
                case T_RowExpr:
 
1397
                        /* make ROW() act like a function */
 
1398
                        *name = "row";
 
1399
                        return 2;
 
1400
                case T_CoalesceExpr:
 
1401
                        /* make coalesce() act like a regular function */
 
1402
                        *name = "coalesce";
 
1403
                        return 2;
 
1404
                case T_MinMaxExpr:
 
1405
                        /* make greatest/least act like a regular function */
 
1406
                        switch (((MinMaxExpr *) node)->op)
 
1407
                        {
 
1408
                                case IS_GREATEST:
 
1409
                                        *name = "greatest";
 
1410
                                        return 2;
 
1411
                                case IS_LEAST:
 
1412
                                        *name = "least";
 
1413
                                        return 2;
 
1414
                        }
 
1415
                        break;
 
1416
                case T_XmlExpr:
 
1417
                        /* make SQL/XML functions act like a regular function */
 
1418
                        switch (((XmlExpr *) node)->op)
 
1419
                        {
 
1420
                                case IS_XMLCONCAT:
 
1421
                                        *name = "xmlconcat";
 
1422
                                        return 2;
 
1423
                                case IS_XMLELEMENT:
 
1424
                                        *name = "xmlelement";
 
1425
                                        return 2;
 
1426
                                case IS_XMLFOREST:
 
1427
                                        *name = "xmlforest";
 
1428
                                        return 2;
 
1429
                                case IS_XMLPARSE:
 
1430
                                        *name = "xmlparse";
 
1431
                                        return 2;
 
1432
                                case IS_XMLPI:
 
1433
                                        *name = "xmlpi";
 
1434
                                        return 2;
 
1435
                                case IS_XMLROOT:
 
1436
                                        *name = "xmlroot";
 
1437
                                        return 2;
 
1438
                                case IS_XMLSERIALIZE:
 
1439
                                        *name = "xmlserialize";
 
1440
                                        return 2;
 
1441
                                case IS_DOCUMENT:
 
1442
                                        /* nothing */
 
1443
                                        break;
 
1444
                        }
 
1445
                        break;
 
1446
                case T_XmlSerialize:
 
1447
                        *name = "xmlserialize";
 
1448
                        return 2;
 
1449
                default:
 
1450
                        break;
 
1451
        }
 
1452
 
 
1453
        return strength;
 
1454
}