1 /*-------------------------------------------------------------------------
2 *
3 * parse_relation.c
4 * parser support routines dealing with relations
5 *
6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/parser/parse_relation.c
12 *
13 *-------------------------------------------------------------------------
14 */
15 #include "postgres.h"
16
17 #include <ctype.h>
18
19 #include "access/htup_details.h"
20 #include "access/relation.h"
21 #include "access/sysattr.h"
22 #include "access/table.h"
23 #include "catalog/heap.h"
24 #include "catalog/namespace.h"
25 #include "catalog/pg_type.h"
26 #include "funcapi.h"
27 #include "nodes/makefuncs.h"
28 #include "nodes/nodeFuncs.h"
29 #include "parser/parsetree.h"
30 #include "parser/parse_enr.h"
31 #include "parser/parse_relation.h"
32 #include "parser/parse_type.h"
33 #include "storage/lmgr.h"
34 #include "utils/builtins.h"
35 #include "utils/lsyscache.h"
36 #include "utils/rel.h"
37 #include "utils/syscache.h"
38 #include "utils/varlena.h"
39
40
41 #define MAX_FUZZY_DISTANCE 3
42
43 static RangeTblEntry *scanNameSpaceForRefname(ParseState *pstate,
44 const char *refname, int location);
45 static RangeTblEntry *scanNameSpaceForRelid(ParseState *pstate, Oid relid,
46 int location);
47 static void check_lateral_ref_ok(ParseState *pstate, ParseNamespaceItem *nsitem,
48 int location);
49 static void markRTEForSelectPriv(ParseState *pstate, RangeTblEntry *rte,
50 int rtindex, AttrNumber col);
51 static void expandRelation(Oid relid, Alias *eref,
52 int rtindex, int sublevels_up,
53 int location, bool include_dropped,
54 List **colnames, List **colvars);
55 static void expandTupleDesc(TupleDesc tupdesc, Alias *eref,
56 int count, int offset,
57 int rtindex, int sublevels_up,
58 int location, bool include_dropped,
59 List **colnames, List **colvars);
60 static int specialAttNum(const char *attname);
61 static bool isQueryUsingTempRelation_walker(Node *node, void *context);
62
63
64 /*
65 * refnameRangeTblEntry
66 * Given a possibly-qualified refname, look to see if it matches any RTE.
67 * If so, return a pointer to the RangeTblEntry; else return NULL.
68 *
69 * Optionally get RTE's nesting depth (0 = current) into *sublevels_up.
70 * If sublevels_up is NULL, only consider items at the current nesting
71 * level.
72 *
73 * An unqualified refname (schemaname == NULL) can match any RTE with matching
74 * alias, or matching unqualified relname in the case of alias-less relation
75 * RTEs. It is possible that such a refname matches multiple RTEs in the
76 * nearest nesting level that has a match; if so, we report an error via
77 * ereport().
78 *
79 * A qualified refname (schemaname != NULL) can only match a relation RTE
80 * that (a) has no alias and (b) is for the same relation identified by
81 * schemaname.refname. In this case we convert schemaname.refname to a
82 * relation OID and search by relid, rather than by alias name. This is
83 * peculiar, but it's what SQL says to do.
84 */
85 RangeTblEntry *
refnameRangeTblEntry(ParseState * pstate,const char * schemaname,const char * refname,int location,int * sublevels_up)86 refnameRangeTblEntry(ParseState *pstate,
87 const char *schemaname,
88 const char *refname,
89 int location,
90 int *sublevels_up)
91 {
92 Oid relId = InvalidOid;
93
94 if (sublevels_up)
95 *sublevels_up = 0;
96
97 if (schemaname != NULL)
98 {
99 Oid namespaceId;
100
101 /*
102 * We can use LookupNamespaceNoError() here because we are only
103 * interested in finding existing RTEs. Checking USAGE permission on
104 * the schema is unnecessary since it would have already been checked
105 * when the RTE was made. Furthermore, we want to report "RTE not
106 * found", not "no permissions for schema", if the name happens to
107 * match a schema name the user hasn't got access to.
108 */
109 namespaceId = LookupNamespaceNoError(schemaname);
110 if (!OidIsValid(namespaceId))
111 return NULL;
112 relId = get_relname_relid(refname, namespaceId);
113 if (!OidIsValid(relId))
114 return NULL;
115 }
116
117 while (pstate != NULL)
118 {
119 RangeTblEntry *result;
120
121 if (OidIsValid(relId))
122 result = scanNameSpaceForRelid(pstate, relId, location);
123 else
124 result = scanNameSpaceForRefname(pstate, refname, location);
125
126 if (result)
127 return result;
128
129 if (sublevels_up)
130 (*sublevels_up)++;
131 else
132 break;
133
134 pstate = pstate->parentParseState;
135 }
136 return NULL;
137 }
138
139 /*
140 * Search the query's table namespace for an RTE matching the
141 * given unqualified refname. Return the RTE if a unique match, or NULL
142 * if no match. Raise error if multiple matches.
143 *
144 * Note: it might seem that we shouldn't have to worry about the possibility
145 * of multiple matches; after all, the SQL standard disallows duplicate table
146 * aliases within a given SELECT level. Historically, however, Postgres has
147 * been laxer than that. For example, we allow
148 * SELECT ... FROM tab1 x CROSS JOIN (tab2 x CROSS JOIN tab3 y) z
149 * on the grounds that the aliased join (z) hides the aliases within it,
150 * therefore there is no conflict between the two RTEs named "x". However,
151 * if tab3 is a LATERAL subquery, then from within the subquery both "x"es
152 * are visible. Rather than rejecting queries that used to work, we allow
153 * this situation, and complain only if there's actually an ambiguous
154 * reference to "x".
155 */
156 static RangeTblEntry *
scanNameSpaceForRefname(ParseState * pstate,const char * refname,int location)157 scanNameSpaceForRefname(ParseState *pstate, const char *refname, int location)
158 {
159 RangeTblEntry *result = NULL;
160 ListCell *l;
161
162 foreach(l, pstate->p_namespace)
163 {
164 ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
165 RangeTblEntry *rte = nsitem->p_rte;
166
167 /* Ignore columns-only items */
168 if (!nsitem->p_rel_visible)
169 continue;
170 /* If not inside LATERAL, ignore lateral-only items */
171 if (nsitem->p_lateral_only && !pstate->p_lateral_active)
172 continue;
173
174 if (strcmp(rte->eref->aliasname, refname) == 0)
175 {
176 if (result)
177 ereport(ERROR,
178 (errcode(ERRCODE_AMBIGUOUS_ALIAS),
179 errmsg("table reference \"%s\" is ambiguous",
180 refname),
181 parser_errposition(pstate, location)));
182 check_lateral_ref_ok(pstate, nsitem, location);
183 result = rte;
184 }
185 }
186 return result;
187 }
188
189 /*
190 * Search the query's table namespace for a relation RTE matching the
191 * given relation OID. Return the RTE if a unique match, or NULL
192 * if no match. Raise error if multiple matches.
193 *
194 * See the comments for refnameRangeTblEntry to understand why this
195 * acts the way it does.
196 */
197 static RangeTblEntry *
scanNameSpaceForRelid(ParseState * pstate,Oid relid,int location)198 scanNameSpaceForRelid(ParseState *pstate, Oid relid, int location)
199 {
200 RangeTblEntry *result = NULL;
201 ListCell *l;
202
203 foreach(l, pstate->p_namespace)
204 {
205 ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
206 RangeTblEntry *rte = nsitem->p_rte;
207
208 /* Ignore columns-only items */
209 if (!nsitem->p_rel_visible)
210 continue;
211 /* If not inside LATERAL, ignore lateral-only items */
212 if (nsitem->p_lateral_only && !pstate->p_lateral_active)
213 continue;
214
215 /* yes, the test for alias == NULL should be there... */
216 if (rte->rtekind == RTE_RELATION &&
217 rte->relid == relid &&
218 rte->alias == NULL)
219 {
220 if (result)
221 ereport(ERROR,
222 (errcode(ERRCODE_AMBIGUOUS_ALIAS),
223 errmsg("table reference %u is ambiguous",
224 relid),
225 parser_errposition(pstate, location)));
226 check_lateral_ref_ok(pstate, nsitem, location);
227 result = rte;
228 }
229 }
230 return result;
231 }
232
233 /*
234 * Search the query's CTE namespace for a CTE matching the given unqualified
235 * refname. Return the CTE (and its levelsup count) if a match, or NULL
236 * if no match. We need not worry about multiple matches, since parse_cte.c
237 * rejects WITH lists containing duplicate CTE names.
238 */
239 CommonTableExpr *
scanNameSpaceForCTE(ParseState * pstate,const char * refname,Index * ctelevelsup)240 scanNameSpaceForCTE(ParseState *pstate, const char *refname,
241 Index *ctelevelsup)
242 {
243 Index levelsup;
244
245 for (levelsup = 0;
246 pstate != NULL;
247 pstate = pstate->parentParseState, levelsup++)
248 {
249 ListCell *lc;
250
251 foreach(lc, pstate->p_ctenamespace)
252 {
253 CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
254
255 if (strcmp(cte->ctename, refname) == 0)
256 {
257 *ctelevelsup = levelsup;
258 return cte;
259 }
260 }
261 }
262 return NULL;
263 }
264
265 /*
266 * Search for a possible "future CTE", that is one that is not yet in scope
267 * according to the WITH scoping rules. This has nothing to do with valid
268 * SQL semantics, but it's important for error reporting purposes.
269 */
270 static bool
isFutureCTE(ParseState * pstate,const char * refname)271 isFutureCTE(ParseState *pstate, const char *refname)
272 {
273 for (; pstate != NULL; pstate = pstate->parentParseState)
274 {
275 ListCell *lc;
276
277 foreach(lc, pstate->p_future_ctes)
278 {
279 CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
280
281 if (strcmp(cte->ctename, refname) == 0)
282 return true;
283 }
284 }
285 return false;
286 }
287
288 /*
289 * Search the query's ephemeral named relation namespace for a relation
290 * matching the given unqualified refname.
291 */
292 bool
scanNameSpaceForENR(ParseState * pstate,const char * refname)293 scanNameSpaceForENR(ParseState *pstate, const char *refname)
294 {
295 return name_matches_visible_ENR(pstate, refname);
296 }
297
298 /*
299 * searchRangeTableForRel
300 * See if any RangeTblEntry could possibly match the RangeVar.
301 * If so, return a pointer to the RangeTblEntry; else return NULL.
302 *
303 * This is different from refnameRangeTblEntry in that it considers every
304 * entry in the ParseState's rangetable(s), not only those that are currently
305 * visible in the p_namespace list(s). This behavior is invalid per the SQL
306 * spec, and it may give ambiguous results (there might be multiple equally
307 * valid matches, but only one will be returned). This must be used ONLY
308 * as a heuristic in giving suitable error messages. See errorMissingRTE.
309 *
310 * Notice that we consider both matches on actual relation (or CTE) name
311 * and matches on alias.
312 */
313 static RangeTblEntry *
searchRangeTableForRel(ParseState * pstate,RangeVar * relation)314 searchRangeTableForRel(ParseState *pstate, RangeVar *relation)
315 {
316 const char *refname = relation->relname;
317 Oid relId = InvalidOid;
318 CommonTableExpr *cte = NULL;
319 bool isenr = false;
320 Index ctelevelsup = 0;
321 Index levelsup;
322
323 /*
324 * If it's an unqualified name, check for possible CTE matches. A CTE
325 * hides any real relation matches. If no CTE, look for a matching
326 * relation.
327 *
328 * NB: It's not critical that RangeVarGetRelid return the correct answer
329 * here in the face of concurrent DDL. If it doesn't, the worst case
330 * scenario is a less-clear error message. Also, the tables involved in
331 * the query are already locked, which reduces the number of cases in
332 * which surprising behavior can occur. So we do the name lookup
333 * unlocked.
334 */
335 if (!relation->schemaname)
336 {
337 cte = scanNameSpaceForCTE(pstate, refname, &ctelevelsup);
338 if (!cte)
339 isenr = scanNameSpaceForENR(pstate, refname);
340 }
341
342 if (!cte && !isenr)
343 relId = RangeVarGetRelid(relation, NoLock, true);
344
345 /* Now look for RTEs matching either the relation/CTE/ENR or the alias */
346 for (levelsup = 0;
347 pstate != NULL;
348 pstate = pstate->parentParseState, levelsup++)
349 {
350 ListCell *l;
351
352 foreach(l, pstate->p_rtable)
353 {
354 RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
355
356 if (rte->rtekind == RTE_RELATION &&
357 OidIsValid(relId) &&
358 rte->relid == relId)
359 return rte;
360 if (rte->rtekind == RTE_CTE &&
361 cte != NULL &&
362 rte->ctelevelsup + levelsup == ctelevelsup &&
363 strcmp(rte->ctename, refname) == 0)
364 return rte;
365 if (rte->rtekind == RTE_NAMEDTUPLESTORE &&
366 isenr &&
367 strcmp(rte->enrname, refname) == 0)
368 return rte;
369 if (strcmp(rte->eref->aliasname, refname) == 0)
370 return rte;
371 }
372 }
373 return NULL;
374 }
375
376 /*
377 * Check for relation-name conflicts between two namespace lists.
378 * Raise an error if any is found.
379 *
380 * Note: we assume that each given argument does not contain conflicts
381 * itself; we just want to know if the two can be merged together.
382 *
383 * Per SQL, two alias-less plain relation RTEs do not conflict even if
384 * they have the same eref->aliasname (ie, same relation name), if they
385 * are for different relation OIDs (implying they are in different schemas).
386 *
387 * We ignore the lateral-only flags in the namespace items: the lists must
388 * not conflict, even when all items are considered visible. However,
389 * columns-only items should be ignored.
390 */
391 void
checkNameSpaceConflicts(ParseState * pstate,List * namespace1,List * namespace2)392 checkNameSpaceConflicts(ParseState *pstate, List *namespace1,
393 List *namespace2)
394 {
395 ListCell *l1;
396
397 foreach(l1, namespace1)
398 {
399 ParseNamespaceItem *nsitem1 = (ParseNamespaceItem *) lfirst(l1);
400 RangeTblEntry *rte1 = nsitem1->p_rte;
401 const char *aliasname1 = rte1->eref->aliasname;
402 ListCell *l2;
403
404 if (!nsitem1->p_rel_visible)
405 continue;
406
407 foreach(l2, namespace2)
408 {
409 ParseNamespaceItem *nsitem2 = (ParseNamespaceItem *) lfirst(l2);
410 RangeTblEntry *rte2 = nsitem2->p_rte;
411
412 if (!nsitem2->p_rel_visible)
413 continue;
414 if (strcmp(rte2->eref->aliasname, aliasname1) != 0)
415 continue; /* definitely no conflict */
416 if (rte1->rtekind == RTE_RELATION && rte1->alias == NULL &&
417 rte2->rtekind == RTE_RELATION && rte2->alias == NULL &&
418 rte1->relid != rte2->relid)
419 continue; /* no conflict per SQL rule */
420 ereport(ERROR,
421 (errcode(ERRCODE_DUPLICATE_ALIAS),
422 errmsg("table name \"%s\" specified more than once",
423 aliasname1)));
424 }
425 }
426 }
427
428 /*
429 * Complain if a namespace item is currently disallowed as a LATERAL reference.
430 * This enforces both SQL:2008's rather odd idea of what to do with a LATERAL
431 * reference to the wrong side of an outer join, and our own prohibition on
432 * referencing the target table of an UPDATE or DELETE as a lateral reference
433 * in a FROM/USING clause.
434 *
435 * Convenience subroutine to avoid multiple copies of a rather ugly ereport.
436 */
437 static void
check_lateral_ref_ok(ParseState * pstate,ParseNamespaceItem * nsitem,int location)438 check_lateral_ref_ok(ParseState *pstate, ParseNamespaceItem *nsitem,
439 int location)
440 {
441 if (nsitem->p_lateral_only && !nsitem->p_lateral_ok)
442 {
443 /* SQL:2008 demands this be an error, not an invisible item */
444 RangeTblEntry *rte = nsitem->p_rte;
445 char *refname = rte->eref->aliasname;
446
447 ereport(ERROR,
448 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
449 errmsg("invalid reference to FROM-clause entry for table \"%s\"",
450 refname),
451 (rte == pstate->p_target_rangetblentry) ?
452 errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.",
453 refname) :
454 errdetail("The combining JOIN type must be INNER or LEFT for a LATERAL reference."),
455 parser_errposition(pstate, location)));
456 }
457 }
458
459 /*
460 * given an RTE, return RT index (starting with 1) of the entry,
461 * and optionally get its nesting depth (0 = current). If sublevels_up
462 * is NULL, only consider rels at the current nesting level.
463 * Raises error if RTE not found.
464 */
465 int
RTERangeTablePosn(ParseState * pstate,RangeTblEntry * rte,int * sublevels_up)466 RTERangeTablePosn(ParseState *pstate, RangeTblEntry *rte, int *sublevels_up)
467 {
468 int index;
469 ListCell *l;
470
471 if (sublevels_up)
472 *sublevels_up = 0;
473
474 while (pstate != NULL)
475 {
476 index = 1;
477 foreach(l, pstate->p_rtable)
478 {
479 if (rte == (RangeTblEntry *) lfirst(l))
480 return index;
481 index++;
482 }
483 pstate = pstate->parentParseState;
484 if (sublevels_up)
485 (*sublevels_up)++;
486 else
487 break;
488 }
489
490 elog(ERROR, "RTE not found (internal error)");
491 return 0; /* keep compiler quiet */
492 }
493
494 /*
495 * Given an RT index and nesting depth, find the corresponding RTE.
496 * This is the inverse of RTERangeTablePosn.
497 */
498 RangeTblEntry *
GetRTEByRangeTablePosn(ParseState * pstate,int varno,int sublevels_up)499 GetRTEByRangeTablePosn(ParseState *pstate,
500 int varno,
501 int sublevels_up)
502 {
503 while (sublevels_up-- > 0)
504 {
505 pstate = pstate->parentParseState;
506 Assert(pstate != NULL);
507 }
508 Assert(varno > 0 && varno <= list_length(pstate->p_rtable));
509 return rt_fetch(varno, pstate->p_rtable);
510 }
511
512 /*
513 * Fetch the CTE for a CTE-reference RTE.
514 *
515 * rtelevelsup is the number of query levels above the given pstate that the
516 * RTE came from. Callers that don't have this information readily available
517 * may pass -1 instead.
518 */
519 CommonTableExpr *
GetCTEForRTE(ParseState * pstate,RangeTblEntry * rte,int rtelevelsup)520 GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte, int rtelevelsup)
521 {
522 Index levelsup;
523 ListCell *lc;
524
525 /* Determine RTE's levelsup if caller didn't know it */
526 if (rtelevelsup < 0)
527 (void) RTERangeTablePosn(pstate, rte, &rtelevelsup);
528
529 Assert(rte->rtekind == RTE_CTE);
530 levelsup = rte->ctelevelsup + rtelevelsup;
531 while (levelsup-- > 0)
532 {
533 pstate = pstate->parentParseState;
534 if (!pstate) /* shouldn't happen */
535 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
536 }
537 foreach(lc, pstate->p_ctenamespace)
538 {
539 CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
540
541 if (strcmp(cte->ctename, rte->ctename) == 0)
542 return cte;
543 }
544 /* shouldn't happen */
545 elog(ERROR, "could not find CTE \"%s\"", rte->ctename);
546 return NULL; /* keep compiler quiet */
547 }
548
549 /*
550 * updateFuzzyAttrMatchState
551 * Using Levenshtein distance, consider if column is best fuzzy match.
552 */
553 static void
updateFuzzyAttrMatchState(int fuzzy_rte_penalty,FuzzyAttrMatchState * fuzzystate,RangeTblEntry * rte,const char * actual,const char * match,int attnum)554 updateFuzzyAttrMatchState(int fuzzy_rte_penalty,
555 FuzzyAttrMatchState *fuzzystate, RangeTblEntry *rte,
556 const char *actual, const char *match, int attnum)
557 {
558 int columndistance;
559 int matchlen;
560
561 /* Bail before computing the Levenshtein distance if there's no hope. */
562 if (fuzzy_rte_penalty > fuzzystate->distance)
563 return;
564
565 /*
566 * Outright reject dropped columns, which can appear here with apparent
567 * empty actual names, per remarks within scanRTEForColumn().
568 */
569 if (actual[0] == '\0')
570 return;
571
572 /* Use Levenshtein to compute match distance. */
573 matchlen = strlen(match);
574 columndistance =
575 varstr_levenshtein_less_equal(actual, strlen(actual), match, matchlen,
576 1, 1, 1,
577 fuzzystate->distance + 1
578 - fuzzy_rte_penalty,
579 true);
580
581 /*
582 * If more than half the characters are different, don't treat it as a
583 * match, to avoid making ridiculous suggestions.
584 */
585 if (columndistance > matchlen / 2)
586 return;
587
588 /*
589 * From this point on, we can ignore the distinction between the RTE-name
590 * distance and the column-name distance.
591 */
592 columndistance += fuzzy_rte_penalty;
593
594 /*
595 * If the new distance is less than or equal to that of the best match
596 * found so far, update fuzzystate.
597 */
598 if (columndistance < fuzzystate->distance)
599 {
600 /* Store new lowest observed distance for RTE */
601 fuzzystate->distance = columndistance;
602 fuzzystate->rfirst = rte;
603 fuzzystate->first = attnum;
604 fuzzystate->rsecond = NULL;
605 fuzzystate->second = InvalidAttrNumber;
606 }
607 else if (columndistance == fuzzystate->distance)
608 {
609 /*
610 * This match distance may equal a prior match within this same range
611 * table. When that happens, the prior match may also be given, but
612 * only if there is no more than two equally distant matches from the
613 * RTE (in turn, our caller will only accept two equally distant
614 * matches overall).
615 */
616 if (AttributeNumberIsValid(fuzzystate->second))
617 {
618 /* Too many RTE-level matches */
619 fuzzystate->rfirst = NULL;
620 fuzzystate->first = InvalidAttrNumber;
621 fuzzystate->rsecond = NULL;
622 fuzzystate->second = InvalidAttrNumber;
623 /* Clearly, distance is too low a bar (for *any* RTE) */
624 fuzzystate->distance = columndistance - 1;
625 }
626 else if (AttributeNumberIsValid(fuzzystate->first))
627 {
628 /* Record as provisional second match for RTE */
629 fuzzystate->rsecond = rte;
630 fuzzystate->second = attnum;
631 }
632 else if (fuzzystate->distance <= MAX_FUZZY_DISTANCE)
633 {
634 /*
635 * Record as provisional first match (this can occasionally occur
636 * because previous lowest distance was "too low a bar", rather
637 * than being associated with a real match)
638 */
639 fuzzystate->rfirst = rte;
640 fuzzystate->first = attnum;
641 }
642 }
643 }
644
645 /*
646 * scanRTEForColumn
647 * Search the column names of a single RTE for the given name.
648 * If found, return an appropriate Var node, else return NULL.
649 * If the name proves ambiguous within this RTE, raise error.
650 *
651 * Side effect: if we find a match, mark the RTE as requiring read access
652 * for the column.
653 *
654 * Additional side effect: if fuzzystate is non-NULL, check non-system columns
655 * for an approximate match and update fuzzystate accordingly.
656 */
657 Node *
scanRTEForColumn(ParseState * pstate,RangeTblEntry * rte,const char * colname,int location,int fuzzy_rte_penalty,FuzzyAttrMatchState * fuzzystate)658 scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, const char *colname,
659 int location, int fuzzy_rte_penalty,
660 FuzzyAttrMatchState *fuzzystate)
661 {
662 Node *result = NULL;
663 int attnum = 0;
664 Var *var;
665 ListCell *c;
666
667 /*
668 * Scan the user column names (or aliases) for a match. Complain if
669 * multiple matches.
670 *
671 * Note: eref->colnames may include entries for dropped columns, but those
672 * will be empty strings that cannot match any legal SQL identifier, so we
673 * don't bother to test for that case here.
674 *
675 * Should this somehow go wrong and we try to access a dropped column,
676 * we'll still catch it by virtue of the checks in
677 * get_rte_attribute_type(), which is called by make_var(). That routine
678 * has to do a cache lookup anyway, so the check there is cheap. Callers
679 * interested in finding match with shortest distance need to defend
680 * against this directly, though.
681 */
682 foreach(c, rte->eref->colnames)
683 {
684 const char *attcolname = strVal(lfirst(c));
685
686 attnum++;
687 if (strcmp(attcolname, colname) == 0)
688 {
689 if (result)
690 ereport(ERROR,
691 (errcode(ERRCODE_AMBIGUOUS_COLUMN),
692 errmsg("column reference \"%s\" is ambiguous",
693 colname),
694 parser_errposition(pstate, location)));
695 var = make_var(pstate, rte, attnum, location);
696 /* Require read access to the column */
697 markVarForSelectPriv(pstate, var, rte);
698 result = (Node *) var;
699 }
700
701 /* Updating fuzzy match state, if provided. */
702 if (fuzzystate != NULL)
703 updateFuzzyAttrMatchState(fuzzy_rte_penalty, fuzzystate,
704 rte, attcolname, colname, attnum);
705 }
706
707 /*
708 * If we have a unique match, return it. Note that this allows a user
709 * alias to override a system column name (such as OID) without error.
710 */
711 if (result)
712 return result;
713
714 /*
715 * If the RTE represents a real relation, consider system column names.
716 * Composites are only used for pseudo-relations like ON CONFLICT's
717 * excluded.
718 */
719 if (rte->rtekind == RTE_RELATION &&
720 rte->relkind != RELKIND_COMPOSITE_TYPE)
721 {
722 /* quick check to see if name could be a system column */
723 attnum = specialAttNum(colname);
724
725 /* In constraint check, no system column is allowed except tableOid */
726 if (pstate->p_expr_kind == EXPR_KIND_CHECK_CONSTRAINT &&
727 attnum < InvalidAttrNumber && attnum != TableOidAttributeNumber)
728 ereport(ERROR,
729 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
730 errmsg("system column \"%s\" reference in check constraint is invalid",
731 colname),
732 parser_errposition(pstate, location)));
733
734 /*
735 * In generated column, no system column is allowed except tableOid.
736 */
737 if (pstate->p_expr_kind == EXPR_KIND_GENERATED_COLUMN &&
738 attnum < InvalidAttrNumber && attnum != TableOidAttributeNumber)
739 ereport(ERROR,
740 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
741 errmsg("cannot use system column \"%s\" in column generation expression",
742 colname),
743 parser_errposition(pstate, location)));
744
745 if (attnum != InvalidAttrNumber)
746 {
747 /* now check to see if column actually is defined */
748 if (SearchSysCacheExists2(ATTNUM,
749 ObjectIdGetDatum(rte->relid),
750 Int16GetDatum(attnum)))
751 {
752 var = make_var(pstate, rte, attnum, location);
753 /* Require read access to the column */
754 markVarForSelectPriv(pstate, var, rte);
755 result = (Node *) var;
756 }
757 }
758 }
759
760 return result;
761 }
762
763 /*
764 * colNameToVar
765 * Search for an unqualified column name.
766 * If found, return the appropriate Var node (or expression).
767 * If not found, return NULL. If the name proves ambiguous, raise error.
768 * If localonly is true, only names in the innermost query are considered.
769 */
770 Node *
colNameToVar(ParseState * pstate,const char * colname,bool localonly,int location)771 colNameToVar(ParseState *pstate, const char *colname, bool localonly,
772 int location)
773 {
774 Node *result = NULL;
775 ParseState *orig_pstate = pstate;
776
777 while (pstate != NULL)
778 {
779 ListCell *l;
780
781 foreach(l, pstate->p_namespace)
782 {
783 ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
784 RangeTblEntry *rte = nsitem->p_rte;
785 Node *newresult;
786
787 /* Ignore table-only items */
788 if (!nsitem->p_cols_visible)
789 continue;
790 /* If not inside LATERAL, ignore lateral-only items */
791 if (nsitem->p_lateral_only && !pstate->p_lateral_active)
792 continue;
793
794 /* use orig_pstate here to get the right sublevels_up */
795 newresult = scanRTEForColumn(orig_pstate, rte, colname, location,
796 0, NULL);
797
798 if (newresult)
799 {
800 if (result)
801 ereport(ERROR,
802 (errcode(ERRCODE_AMBIGUOUS_COLUMN),
803 errmsg("column reference \"%s\" is ambiguous",
804 colname),
805 parser_errposition(pstate, location)));
806 check_lateral_ref_ok(pstate, nsitem, location);
807 result = newresult;
808 }
809 }
810
811 if (result != NULL || localonly)
812 break; /* found, or don't want to look at parent */
813
814 pstate = pstate->parentParseState;
815 }
816
817 return result;
818 }
819
820 /*
821 * searchRangeTableForCol
822 * See if any RangeTblEntry could possibly provide the given column name (or
823 * find the best match available). Returns state with relevant details.
824 *
825 * This is different from colNameToVar in that it considers every entry in
826 * the ParseState's rangetable(s), not only those that are currently visible
827 * in the p_namespace list(s). This behavior is invalid per the SQL spec,
828 * and it may give ambiguous results (there might be multiple equally valid
829 * matches, but only one will be returned). This must be used ONLY as a
830 * heuristic in giving suitable error messages. See errorMissingColumn.
831 *
832 * This function is also different in that it will consider approximate
833 * matches -- if the user entered an alias/column pair that is only slightly
834 * different from a valid pair, we may be able to infer what they meant to
835 * type and provide a reasonable hint.
836 *
837 * The FuzzyAttrMatchState will have 'rfirst' pointing to the best RTE
838 * containing the most promising match for the alias and column name. If
839 * the alias and column names match exactly, 'first' will be InvalidAttrNumber;
840 * otherwise, it will be the attribute number for the match. In the latter
841 * case, 'rsecond' may point to a second, equally close approximate match,
842 * and 'second' will contain the attribute number for the second match.
843 */
844 static FuzzyAttrMatchState *
searchRangeTableForCol(ParseState * pstate,const char * alias,const char * colname,int location)845 searchRangeTableForCol(ParseState *pstate, const char *alias, const char *colname,
846 int location)
847 {
848 ParseState *orig_pstate = pstate;
849 FuzzyAttrMatchState *fuzzystate = palloc(sizeof(FuzzyAttrMatchState));
850
851 fuzzystate->distance = MAX_FUZZY_DISTANCE + 1;
852 fuzzystate->rfirst = NULL;
853 fuzzystate->rsecond = NULL;
854 fuzzystate->first = InvalidAttrNumber;
855 fuzzystate->second = InvalidAttrNumber;
856
857 while (pstate != NULL)
858 {
859 ListCell *l;
860
861 foreach(l, pstate->p_rtable)
862 {
863 RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
864 int fuzzy_rte_penalty = 0;
865
866 /*
867 * Typically, it is not useful to look for matches within join
868 * RTEs; they effectively duplicate other RTEs for our purposes,
869 * and if a match is chosen from a join RTE, an unhelpful alias is
870 * displayed in the final diagnostic message.
871 */
872 if (rte->rtekind == RTE_JOIN)
873 continue;
874
875 /*
876 * If the user didn't specify an alias, then matches against one
877 * RTE are as good as another. But if the user did specify an
878 * alias, then we want at least a fuzzy - and preferably an exact
879 * - match for the range table entry.
880 */
881 if (alias != NULL)
882 fuzzy_rte_penalty =
883 varstr_levenshtein_less_equal(alias, strlen(alias),
884 rte->eref->aliasname,
885 strlen(rte->eref->aliasname),
886 1, 1, 1,
887 MAX_FUZZY_DISTANCE + 1,
888 true);
889
890 /*
891 * Scan for a matching column; if we find an exact match, we're
892 * done. Otherwise, update fuzzystate.
893 */
894 if (scanRTEForColumn(orig_pstate, rte, colname, location,
895 fuzzy_rte_penalty, fuzzystate)
896 && fuzzy_rte_penalty == 0)
897 {
898 fuzzystate->rfirst = rte;
899 fuzzystate->first = InvalidAttrNumber;
900 fuzzystate->rsecond = NULL;
901 fuzzystate->second = InvalidAttrNumber;
902 return fuzzystate;
903 }
904 }
905
906 pstate = pstate->parentParseState;
907 }
908
909 return fuzzystate;
910 }
911
912 /*
913 * markRTEForSelectPriv
914 * Mark the specified column of an RTE as requiring SELECT privilege
915 *
916 * col == InvalidAttrNumber means a "whole row" reference
917 *
918 * The caller should pass the actual RTE if it has it handy; otherwise pass
919 * NULL, and we'll look it up here. (This uglification of the API is
920 * worthwhile because nearly all external callers have the RTE at hand.)
921 */
922 static void
markRTEForSelectPriv(ParseState * pstate,RangeTblEntry * rte,int rtindex,AttrNumber col)923 markRTEForSelectPriv(ParseState *pstate, RangeTblEntry *rte,
924 int rtindex, AttrNumber col)
925 {
926 if (rte == NULL)
927 rte = rt_fetch(rtindex, pstate->p_rtable);
928
929 if (rte->rtekind == RTE_RELATION)
930 {
931 /* Make sure the rel as a whole is marked for SELECT access */
932 rte->requiredPerms |= ACL_SELECT;
933 /* Must offset the attnum to fit in a bitmapset */
934 rte->selectedCols = bms_add_member(rte->selectedCols,
935 col - FirstLowInvalidHeapAttributeNumber);
936 }
937 else if (rte->rtekind == RTE_JOIN)
938 {
939 if (col == InvalidAttrNumber)
940 {
941 /*
942 * A whole-row reference to a join has to be treated as whole-row
943 * references to the two inputs.
944 */
945 JoinExpr *j;
946
947 if (rtindex > 0 && rtindex <= list_length(pstate->p_joinexprs))
948 j = list_nth_node(JoinExpr, pstate->p_joinexprs, rtindex - 1);
949 else
950 j = NULL;
951 if (j == NULL)
952 elog(ERROR, "could not find JoinExpr for whole-row reference");
953
954 /* Note: we can't see FromExpr here */
955 if (IsA(j->larg, RangeTblRef))
956 {
957 int varno = ((RangeTblRef *) j->larg)->rtindex;
958
959 markRTEForSelectPriv(pstate, NULL, varno, InvalidAttrNumber);
960 }
961 else if (IsA(j->larg, JoinExpr))
962 {
963 int varno = ((JoinExpr *) j->larg)->rtindex;
964
965 markRTEForSelectPriv(pstate, NULL, varno, InvalidAttrNumber);
966 }
967 else
968 elog(ERROR, "unrecognized node type: %d",
969 (int) nodeTag(j->larg));
970 if (IsA(j->rarg, RangeTblRef))
971 {
972 int varno = ((RangeTblRef *) j->rarg)->rtindex;
973
974 markRTEForSelectPriv(pstate, NULL, varno, InvalidAttrNumber);
975 }
976 else if (IsA(j->rarg, JoinExpr))
977 {
978 int varno = ((JoinExpr *) j->rarg)->rtindex;
979
980 markRTEForSelectPriv(pstate, NULL, varno, InvalidAttrNumber);
981 }
982 else
983 elog(ERROR, "unrecognized node type: %d",
984 (int) nodeTag(j->rarg));
985 }
986 else
987 {
988 /*
989 * Regular join attribute, look at the alias-variable list.
990 *
991 * The aliasvar could be either a Var or a COALESCE expression,
992 * but in the latter case we should already have marked the two
993 * referent variables as being selected, due to their use in the
994 * JOIN clause. So we need only be concerned with the Var case.
995 * But we do need to drill down through implicit coercions.
996 */
997 Var *aliasvar;
998
999 Assert(col > 0 && col <= list_length(rte->joinaliasvars));
1000 aliasvar = (Var *) list_nth(rte->joinaliasvars, col - 1);
1001 aliasvar = (Var *) strip_implicit_coercions((Node *) aliasvar);
1002 if (aliasvar && IsA(aliasvar, Var))
1003 markVarForSelectPriv(pstate, aliasvar, NULL);
1004 }
1005 }
1006 /* other RTE types don't require privilege marking */
1007 }
1008
1009 /*
1010 * markVarForSelectPriv
1011 * Mark the RTE referenced by a Var as requiring SELECT privilege
1012 *
1013 * The caller should pass the Var's referenced RTE if it has it handy
1014 * (nearly all do); otherwise pass NULL.
1015 */
1016 void
markVarForSelectPriv(ParseState * pstate,Var * var,RangeTblEntry * rte)1017 markVarForSelectPriv(ParseState *pstate, Var *var, RangeTblEntry *rte)
1018 {
1019 Index lv;
1020
1021 Assert(IsA(var, Var));
1022 /* Find the appropriate pstate if it's an uplevel Var */
1023 for (lv = 0; lv < var->varlevelsup; lv++)
1024 pstate = pstate->parentParseState;
1025 markRTEForSelectPriv(pstate, rte, var->varno, var->varattno);
1026 }
1027
1028 /*
1029 * buildRelationAliases
1030 * Construct the eref column name list for a relation RTE.
1031 * This code is also used for function RTEs.
1032 *
1033 * tupdesc: the physical column information
1034 * alias: the user-supplied alias, or NULL if none
1035 * eref: the eref Alias to store column names in
1036 *
1037 * eref->colnames is filled in. Also, alias->colnames is rebuilt to insert
1038 * empty strings for any dropped columns, so that it will be one-to-one with
1039 * physical column numbers.
1040 *
1041 * It is an error for there to be more aliases present than required.
1042 */
1043 static void
buildRelationAliases(TupleDesc tupdesc,Alias * alias,Alias * eref)1044 buildRelationAliases(TupleDesc tupdesc, Alias *alias, Alias *eref)
1045 {
1046 int maxattrs = tupdesc->natts;
1047 ListCell *aliaslc;
1048 int numaliases;
1049 int varattno;
1050 int numdropped = 0;
1051
1052 Assert(eref->colnames == NIL);
1053
1054 if (alias)
1055 {
1056 aliaslc = list_head(alias->colnames);
1057 numaliases = list_length(alias->colnames);
1058 /* We'll rebuild the alias colname list */
1059 alias->colnames = NIL;
1060 }
1061 else
1062 {
1063 aliaslc = NULL;
1064 numaliases = 0;
1065 }
1066
1067 for (varattno = 0; varattno < maxattrs; varattno++)
1068 {
1069 Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
1070 Value *attrname;
1071
1072 if (attr->attisdropped)
1073 {
1074 /* Always insert an empty string for a dropped column */
1075 attrname = makeString(pstrdup(""));
1076 if (aliaslc)
1077 alias->colnames = lappend(alias->colnames, attrname);
1078 numdropped++;
1079 }
1080 else if (aliaslc)
1081 {
1082 /* Use the next user-supplied alias */
1083 attrname = (Value *) lfirst(aliaslc);
1084 aliaslc = lnext(aliaslc);
1085 alias->colnames = lappend(alias->colnames, attrname);
1086 }
1087 else
1088 {
1089 attrname = makeString(pstrdup(NameStr(attr->attname)));
1090 /* we're done with the alias if any */
1091 }
1092
1093 eref->colnames = lappend(eref->colnames, attrname);
1094 }
1095
1096 /* Too many user-supplied aliases? */
1097 if (aliaslc)
1098 ereport(ERROR,
1099 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1100 errmsg("table \"%s\" has %d columns available but %d columns specified",
1101 eref->aliasname, maxattrs - numdropped, numaliases)));
1102 }
1103
1104 /*
1105 * chooseScalarFunctionAlias
1106 * Select the column alias for a function in a function RTE,
1107 * when the function returns a scalar type (not composite or RECORD).
1108 *
1109 * funcexpr: transformed expression tree for the function call
1110 * funcname: function name (as determined by FigureColname)
1111 * alias: the user-supplied alias for the RTE, or NULL if none
1112 * nfuncs: the number of functions appearing in the function RTE
1113 *
1114 * Note that the name we choose might be overridden later, if the user-given
1115 * alias includes column alias names. That's of no concern here.
1116 */
1117 static char *
chooseScalarFunctionAlias(Node * funcexpr,char * funcname,Alias * alias,int nfuncs)1118 chooseScalarFunctionAlias(Node *funcexpr, char *funcname,
1119 Alias *alias, int nfuncs)
1120 {
1121 char *pname;
1122
1123 /*
1124 * If the expression is a simple function call, and the function has a
1125 * single OUT parameter that is named, use the parameter's name.
1126 */
1127 if (funcexpr && IsA(funcexpr, FuncExpr))
1128 {
1129 pname = get_func_result_name(((FuncExpr *) funcexpr)->funcid);
1130 if (pname)
1131 return pname;
1132 }
1133
1134 /*
1135 * If there's just one function in the RTE, and the user gave an RTE alias
1136 * name, use that name. (This makes FROM func() AS foo use "foo" as the
1137 * column name as well as the table alias.)
1138 */
1139 if (nfuncs == 1 && alias)
1140 return alias->aliasname;
1141
1142 /*
1143 * Otherwise use the function name.
1144 */
1145 return funcname;
1146 }
1147
1148 /*
1149 * Open a table during parse analysis
1150 *
1151 * This is essentially just the same as table_openrv(), except that it caters
1152 * to some parser-specific error reporting needs, notably that it arranges
1153 * to include the RangeVar's parse location in any resulting error.
1154 *
1155 * Note: properly, lockmode should be declared LOCKMODE not int, but that
1156 * would require importing storage/lock.h into parse_relation.h. Since
1157 * LOCKMODE is typedef'd as int anyway, that seems like overkill.
1158 */
1159 Relation
parserOpenTable(ParseState * pstate,const RangeVar * relation,int lockmode)1160 parserOpenTable(ParseState *pstate, const RangeVar *relation, int lockmode)
1161 {
1162 Relation rel;
1163 ParseCallbackState pcbstate;
1164
1165 setup_parser_errposition_callback(&pcbstate, pstate, relation->location);
1166 rel = table_openrv_extended(relation, lockmode, true);
1167 if (rel == NULL)
1168 {
1169 if (relation->schemaname)
1170 ereport(ERROR,
1171 (errcode(ERRCODE_UNDEFINED_TABLE),
1172 errmsg("relation \"%s.%s\" does not exist",
1173 relation->schemaname, relation->relname)));
1174 else
1175 {
1176 /*
1177 * An unqualified name might have been meant as a reference to
1178 * some not-yet-in-scope CTE. The bare "does not exist" message
1179 * has proven remarkably unhelpful for figuring out such problems,
1180 * so we take pains to offer a specific hint.
1181 */
1182 if (isFutureCTE(pstate, relation->relname))
1183 ereport(ERROR,
1184 (errcode(ERRCODE_UNDEFINED_TABLE),
1185 errmsg("relation \"%s\" does not exist",
1186 relation->relname),
1187 errdetail("There is a WITH item named \"%s\", but it cannot be referenced from this part of the query.",
1188 relation->relname),
1189 errhint("Use WITH RECURSIVE, or re-order the WITH items to remove forward references.")));
1190 else
1191 ereport(ERROR,
1192 (errcode(ERRCODE_UNDEFINED_TABLE),
1193 errmsg("relation \"%s\" does not exist",
1194 relation->relname)));
1195 }
1196 }
1197 cancel_parser_errposition_callback(&pcbstate);
1198 return rel;
1199 }
1200
1201 /*
1202 * Add an entry for a relation to the pstate's range table (p_rtable).
1203 *
1204 * Note: formerly this checked for refname conflicts, but that's wrong.
1205 * Caller is responsible for checking for conflicts in the appropriate scope.
1206 */
1207 RangeTblEntry *
addRangeTableEntry(ParseState * pstate,RangeVar * relation,Alias * alias,bool inh,bool inFromCl)1208 addRangeTableEntry(ParseState *pstate,
1209 RangeVar *relation,
1210 Alias *alias,
1211 bool inh,
1212 bool inFromCl)
1213 {
1214 RangeTblEntry *rte = makeNode(RangeTblEntry);
1215 char *refname = alias ? alias->aliasname : relation->relname;
1216 LOCKMODE lockmode;
1217 Relation rel;
1218
1219 Assert(pstate != NULL);
1220
1221 rte->rtekind = RTE_RELATION;
1222 rte->alias = alias;
1223
1224 /*
1225 * Identify the type of lock we'll need on this relation. It's not the
1226 * query's target table (that case is handled elsewhere), so we need
1227 * either RowShareLock if it's locked by FOR UPDATE/SHARE, or plain
1228 * AccessShareLock otherwise.
1229 */
1230 lockmode = isLockedRefname(pstate, refname) ? RowShareLock : AccessShareLock;
1231
1232 /*
1233 * Get the rel's OID. This access also ensures that we have an up-to-date
1234 * relcache entry for the rel. Since this is typically the first access
1235 * to a rel in a statement, we must open the rel with the proper lockmode.
1236 */
1237 rel = parserOpenTable(pstate, relation, lockmode);
1238 rte->relid = RelationGetRelid(rel);
1239 rte->relkind = rel->rd_rel->relkind;
1240 rte->rellockmode = lockmode;
1241
1242 /*
1243 * Build the list of effective column names using user-supplied aliases
1244 * and/or actual column names.
1245 */
1246 rte->eref = makeAlias(refname, NIL);
1247 buildRelationAliases(rel->rd_att, alias, rte->eref);
1248
1249 /*
1250 * Drop the rel refcount, but keep the access lock till end of transaction
1251 * so that the table can't be deleted or have its schema modified
1252 * underneath us.
1253 */
1254 table_close(rel, NoLock);
1255
1256 /*
1257 * Set flags and access permissions.
1258 *
1259 * The initial default on access checks is always check-for-READ-access,
1260 * which is the right thing for all except target tables.
1261 */
1262 rte->lateral = false;
1263 rte->inh = inh;
1264 rte->inFromCl = inFromCl;
1265
1266 rte->requiredPerms = ACL_SELECT;
1267 rte->checkAsUser = InvalidOid; /* not set-uid by default, either */
1268 rte->selectedCols = NULL;
1269 rte->insertedCols = NULL;
1270 rte->updatedCols = NULL;
1271 rte->extraUpdatedCols = NULL;
1272
1273 /*
1274 * Add completed RTE to pstate's range table list, but not to join list
1275 * nor namespace --- caller must do that if appropriate.
1276 */
1277 pstate->p_rtable = lappend(pstate->p_rtable, rte);
1278
1279 return rte;
1280 }
1281
1282 /*
1283 * Add an entry for a relation to the pstate's range table (p_rtable).
1284 *
1285 * This is just like addRangeTableEntry() except that it makes an RTE
1286 * given an already-open relation instead of a RangeVar reference.
1287 *
1288 * lockmode is the lock type required for query execution; it must be one
1289 * of AccessShareLock, RowShareLock, or RowExclusiveLock depending on the
1290 * RTE's role within the query. The caller must hold that lock mode
1291 * or a stronger one.
1292 *
1293 * Note: properly, lockmode should be declared LOCKMODE not int, but that
1294 * would require importing storage/lock.h into parse_relation.h. Since
1295 * LOCKMODE is typedef'd as int anyway, that seems like overkill.
1296 */
1297 RangeTblEntry *
addRangeTableEntryForRelation(ParseState * pstate,Relation rel,int lockmode,Alias * alias,bool inh,bool inFromCl)1298 addRangeTableEntryForRelation(ParseState *pstate,
1299 Relation rel,
1300 int lockmode,
1301 Alias *alias,
1302 bool inh,
1303 bool inFromCl)
1304 {
1305 RangeTblEntry *rte = makeNode(RangeTblEntry);
1306 char *refname = alias ? alias->aliasname : RelationGetRelationName(rel);
1307
1308 Assert(pstate != NULL);
1309
1310 Assert(lockmode == AccessShareLock ||
1311 lockmode == RowShareLock ||
1312 lockmode == RowExclusiveLock);
1313 Assert(CheckRelationLockedByMe(rel, lockmode, true));
1314
1315 rte->rtekind = RTE_RELATION;
1316 rte->alias = alias;
1317 rte->relid = RelationGetRelid(rel);
1318 rte->relkind = rel->rd_rel->relkind;
1319 rte->rellockmode = lockmode;
1320
1321 /*
1322 * Build the list of effective column names using user-supplied aliases
1323 * and/or actual column names.
1324 */
1325 rte->eref = makeAlias(refname, NIL);
1326 buildRelationAliases(rel->rd_att, alias, rte->eref);
1327
1328 /*
1329 * Set flags and access permissions.
1330 *
1331 * The initial default on access checks is always check-for-READ-access,
1332 * which is the right thing for all except target tables.
1333 */
1334 rte->lateral = false;
1335 rte->inh = inh;
1336 rte->inFromCl = inFromCl;
1337
1338 rte->requiredPerms = ACL_SELECT;
1339 rte->checkAsUser = InvalidOid; /* not set-uid by default, either */
1340 rte->selectedCols = NULL;
1341 rte->insertedCols = NULL;
1342 rte->updatedCols = NULL;
1343 rte->extraUpdatedCols = NULL;
1344
1345 /*
1346 * Add completed RTE to pstate's range table list, but not to join list
1347 * nor namespace --- caller must do that if appropriate.
1348 */
1349 pstate->p_rtable = lappend(pstate->p_rtable, rte);
1350
1351 return rte;
1352 }
1353
1354 /*
1355 * Add an entry for a subquery to the pstate's range table (p_rtable).
1356 *
1357 * This is just like addRangeTableEntry() except that it makes a subquery RTE.
1358 * Note that an alias clause *must* be supplied.
1359 */
1360 RangeTblEntry *
addRangeTableEntryForSubquery(ParseState * pstate,Query * subquery,Alias * alias,bool lateral,bool inFromCl)1361 addRangeTableEntryForSubquery(ParseState *pstate,
1362 Query *subquery,
1363 Alias *alias,
1364 bool lateral,
1365 bool inFromCl)
1366 {
1367 RangeTblEntry *rte = makeNode(RangeTblEntry);
1368 char *refname = alias->aliasname;
1369 Alias *eref;
1370 int numaliases;
1371 int varattno;
1372 ListCell *tlistitem;
1373
1374 Assert(pstate != NULL);
1375
1376 rte->rtekind = RTE_SUBQUERY;
1377 rte->subquery = subquery;
1378 rte->alias = alias;
1379
1380 eref = copyObject(alias);
1381 numaliases = list_length(eref->colnames);
1382
1383 /* fill in any unspecified alias columns */
1384 varattno = 0;
1385 foreach(tlistitem, subquery->targetList)
1386 {
1387 TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
1388
1389 if (te->resjunk)
1390 continue;
1391 varattno++;
1392 Assert(varattno == te->resno);
1393 if (varattno > numaliases)
1394 {
1395 char *attrname;
1396
1397 attrname = pstrdup(te->resname);
1398 eref->colnames = lappend(eref->colnames, makeString(attrname));
1399 }
1400 }
1401 if (varattno < numaliases)
1402 ereport(ERROR,
1403 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1404 errmsg("table \"%s\" has %d columns available but %d columns specified",
1405 refname, varattno, numaliases)));
1406
1407 rte->eref = eref;
1408
1409 /*
1410 * Set flags and access permissions.
1411 *
1412 * Subqueries are never checked for access rights.
1413 */
1414 rte->lateral = lateral;
1415 rte->inh = false; /* never true for subqueries */
1416 rte->inFromCl = inFromCl;
1417
1418 rte->requiredPerms = 0;
1419 rte->checkAsUser = InvalidOid;
1420 rte->selectedCols = NULL;
1421 rte->insertedCols = NULL;
1422 rte->updatedCols = NULL;
1423 rte->extraUpdatedCols = NULL;
1424
1425 /*
1426 * Add completed RTE to pstate's range table list, but not to join list
1427 * nor namespace --- caller must do that if appropriate.
1428 */
1429 pstate->p_rtable = lappend(pstate->p_rtable, rte);
1430
1431 return rte;
1432 }
1433
1434 /*
1435 * Add an entry for a function (or functions) to the pstate's range table
1436 * (p_rtable).
1437 *
1438 * This is just like addRangeTableEntry() except that it makes a function RTE.
1439 */
1440 RangeTblEntry *
addRangeTableEntryForFunction(ParseState * pstate,List * funcnames,List * funcexprs,List * coldeflists,RangeFunction * rangefunc,bool lateral,bool inFromCl)1441 addRangeTableEntryForFunction(ParseState *pstate,
1442 List *funcnames,
1443 List *funcexprs,
1444 List *coldeflists,
1445 RangeFunction *rangefunc,
1446 bool lateral,
1447 bool inFromCl)
1448 {
1449 RangeTblEntry *rte = makeNode(RangeTblEntry);
1450 Alias *alias = rangefunc->alias;
1451 Alias *eref;
1452 char *aliasname;
1453 int nfuncs = list_length(funcexprs);
1454 TupleDesc *functupdescs;
1455 TupleDesc tupdesc;
1456 ListCell *lc1,
1457 *lc2,
1458 *lc3;
1459 int i;
1460 int j;
1461 int funcno;
1462 int natts,
1463 totalatts;
1464
1465 Assert(pstate != NULL);
1466
1467 rte->rtekind = RTE_FUNCTION;
1468 rte->relid = InvalidOid;
1469 rte->subquery = NULL;
1470 rte->functions = NIL; /* we'll fill this list below */
1471 rte->funcordinality = rangefunc->ordinality;
1472 rte->alias = alias;
1473
1474 /*
1475 * Choose the RTE alias name. We default to using the first function's
1476 * name even when there's more than one; which is maybe arguable but beats
1477 * using something constant like "table".
1478 */
1479 if (alias)
1480 aliasname = alias->aliasname;
1481 else
1482 aliasname = linitial(funcnames);
1483
1484 eref = makeAlias(aliasname, NIL);
1485 rte->eref = eref;
1486
1487 /* Process each function ... */
1488 functupdescs = (TupleDesc *) palloc(nfuncs * sizeof(TupleDesc));
1489
1490 totalatts = 0;
1491 funcno = 0;
1492 forthree(lc1, funcexprs, lc2, funcnames, lc3, coldeflists)
1493 {
1494 Node *funcexpr = (Node *) lfirst(lc1);
1495 char *funcname = (char *) lfirst(lc2);
1496 List *coldeflist = (List *) lfirst(lc3);
1497 RangeTblFunction *rtfunc = makeNode(RangeTblFunction);
1498 TypeFuncClass functypclass;
1499 Oid funcrettype;
1500
1501 /* Initialize RangeTblFunction node */
1502 rtfunc->funcexpr = funcexpr;
1503 rtfunc->funccolnames = NIL;
1504 rtfunc->funccoltypes = NIL;
1505 rtfunc->funccoltypmods = NIL;
1506 rtfunc->funccolcollations = NIL;
1507 rtfunc->funcparams = NULL; /* not set until planning */
1508
1509 /*
1510 * Now determine if the function returns a simple or composite type.
1511 */
1512 functypclass = get_expr_result_type(funcexpr,
1513 &funcrettype,
1514 &tupdesc);
1515
1516 /*
1517 * A coldeflist is required if the function returns RECORD and hasn't
1518 * got a predetermined record type, and is prohibited otherwise.
1519 */
1520 if (coldeflist != NIL)
1521 {
1522 if (functypclass != TYPEFUNC_RECORD)
1523 ereport(ERROR,
1524 (errcode(ERRCODE_SYNTAX_ERROR),
1525 errmsg("a column definition list is only allowed for functions returning \"record\""),
1526 parser_errposition(pstate,
1527 exprLocation((Node *) coldeflist))));
1528 }
1529 else
1530 {
1531 if (functypclass == TYPEFUNC_RECORD)
1532 ereport(ERROR,
1533 (errcode(ERRCODE_SYNTAX_ERROR),
1534 errmsg("a column definition list is required for functions returning \"record\""),
1535 parser_errposition(pstate, exprLocation(funcexpr))));
1536 }
1537
1538 if (functypclass == TYPEFUNC_COMPOSITE ||
1539 functypclass == TYPEFUNC_COMPOSITE_DOMAIN)
1540 {
1541 /* Composite data type, e.g. a table's row type */
1542 Assert(tupdesc);
1543 }
1544 else if (functypclass == TYPEFUNC_SCALAR)
1545 {
1546 /* Base data type, i.e. scalar */
1547 tupdesc = CreateTemplateTupleDesc(1);
1548 TupleDescInitEntry(tupdesc,
1549 (AttrNumber) 1,
1550 chooseScalarFunctionAlias(funcexpr, funcname,
1551 alias, nfuncs),
1552 funcrettype,
1553 -1,
1554 0);
1555 }
1556 else if (functypclass == TYPEFUNC_RECORD)
1557 {
1558 ListCell *col;
1559
1560 /*
1561 * Use the column definition list to construct a tupdesc and fill
1562 * in the RangeTblFunction's lists.
1563 */
1564 tupdesc = CreateTemplateTupleDesc(list_length(coldeflist));
1565 i = 1;
1566 foreach(col, coldeflist)
1567 {
1568 ColumnDef *n = (ColumnDef *) lfirst(col);
1569 char *attrname;
1570 Oid attrtype;
1571 int32 attrtypmod;
1572 Oid attrcollation;
1573
1574 attrname = n->colname;
1575 if (n->typeName->setof)
1576 ereport(ERROR,
1577 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
1578 errmsg("column \"%s\" cannot be declared SETOF",
1579 attrname),
1580 parser_errposition(pstate, n->location)));
1581 typenameTypeIdAndMod(pstate, n->typeName,
1582 &attrtype, &attrtypmod);
1583 attrcollation = GetColumnDefCollation(pstate, n, attrtype);
1584 TupleDescInitEntry(tupdesc,
1585 (AttrNumber) i,
1586 attrname,
1587 attrtype,
1588 attrtypmod,
1589 0);
1590 TupleDescInitEntryCollation(tupdesc,
1591 (AttrNumber) i,
1592 attrcollation);
1593 rtfunc->funccolnames = lappend(rtfunc->funccolnames,
1594 makeString(pstrdup(attrname)));
1595 rtfunc->funccoltypes = lappend_oid(rtfunc->funccoltypes,
1596 attrtype);
1597 rtfunc->funccoltypmods = lappend_int(rtfunc->funccoltypmods,
1598 attrtypmod);
1599 rtfunc->funccolcollations = lappend_oid(rtfunc->funccolcollations,
1600 attrcollation);
1601
1602 i++;
1603 }
1604
1605 /*
1606 * Ensure that the coldeflist defines a legal set of names (no
1607 * duplicates, but we needn't worry about system column names) and
1608 * datatypes. Although we mostly can't allow pseudo-types, it
1609 * seems safe to allow RECORD and RECORD[], since values within
1610 * those type classes are self-identifying at runtime, and the
1611 * coldeflist doesn't represent anything that will be visible to
1612 * other sessions.
1613 */
1614 CheckAttributeNamesTypes(tupdesc, RELKIND_COMPOSITE_TYPE,
1615 CHKATYPE_ANYRECORD);
1616 }
1617 else
1618 ereport(ERROR,
1619 (errcode(ERRCODE_DATATYPE_MISMATCH),
1620 errmsg("function \"%s\" in FROM has unsupported return type %s",
1621 funcname, format_type_be(funcrettype)),
1622 parser_errposition(pstate, exprLocation(funcexpr))));
1623
1624 /* Finish off the RangeTblFunction and add it to the RTE's list */
1625 rtfunc->funccolcount = tupdesc->natts;
1626 rte->functions = lappend(rte->functions, rtfunc);
1627
1628 /* Save the tupdesc for use below */
1629 functupdescs[funcno] = tupdesc;
1630 totalatts += tupdesc->natts;
1631 funcno++;
1632 }
1633
1634 /*
1635 * If there's more than one function, or we want an ordinality column, we
1636 * have to produce a merged tupdesc.
1637 */
1638 if (nfuncs > 1 || rangefunc->ordinality)
1639 {
1640 if (rangefunc->ordinality)
1641 totalatts++;
1642
1643 /* Merge the tuple descs of each function into a composite one */
1644 tupdesc = CreateTemplateTupleDesc(totalatts);
1645 natts = 0;
1646 for (i = 0; i < nfuncs; i++)
1647 {
1648 for (j = 1; j <= functupdescs[i]->natts; j++)
1649 TupleDescCopyEntry(tupdesc, ++natts, functupdescs[i], j);
1650 }
1651
1652 /* Add the ordinality column if needed */
1653 if (rangefunc->ordinality)
1654 TupleDescInitEntry(tupdesc,
1655 (AttrNumber) ++natts,
1656 "ordinality",
1657 INT8OID,
1658 -1,
1659 0);
1660
1661 Assert(natts == totalatts);
1662 }
1663 else
1664 {
1665 /* We can just use the single function's tupdesc as-is */
1666 tupdesc = functupdescs[0];
1667 }
1668
1669 /* Use the tupdesc while assigning column aliases for the RTE */
1670 buildRelationAliases(tupdesc, alias, eref);
1671
1672 /*
1673 * Set flags and access permissions.
1674 *
1675 * Functions are never checked for access rights (at least, not by the RTE
1676 * permissions mechanism).
1677 */
1678 rte->lateral = lateral;
1679 rte->inh = false; /* never true for functions */
1680 rte->inFromCl = inFromCl;
1681
1682 rte->requiredPerms = 0;
1683 rte->checkAsUser = InvalidOid;
1684 rte->selectedCols = NULL;
1685 rte->insertedCols = NULL;
1686 rte->updatedCols = NULL;
1687 rte->extraUpdatedCols = NULL;
1688
1689 /*
1690 * Add completed RTE to pstate's range table list, but not to join list
1691 * nor namespace --- caller must do that if appropriate.
1692 */
1693 pstate->p_rtable = lappend(pstate->p_rtable, rte);
1694
1695 return rte;
1696 }
1697
1698 /*
1699 * Add an entry for a table function to the pstate's range table (p_rtable).
1700 *
1701 * This is much like addRangeTableEntry() except that it makes a tablefunc RTE.
1702 */
1703 RangeTblEntry *
addRangeTableEntryForTableFunc(ParseState * pstate,TableFunc * tf,Alias * alias,bool lateral,bool inFromCl)1704 addRangeTableEntryForTableFunc(ParseState *pstate,
1705 TableFunc *tf,
1706 Alias *alias,
1707 bool lateral,
1708 bool inFromCl)
1709 {
1710 RangeTblEntry *rte = makeNode(RangeTblEntry);
1711 char *refname = alias ? alias->aliasname : pstrdup("xmltable");
1712 Alias *eref;
1713 int numaliases;
1714
1715 Assert(pstate != NULL);
1716
1717 rte->rtekind = RTE_TABLEFUNC;
1718 rte->relid = InvalidOid;
1719 rte->subquery = NULL;
1720 rte->tablefunc = tf;
1721 rte->coltypes = tf->coltypes;
1722 rte->coltypmods = tf->coltypmods;
1723 rte->colcollations = tf->colcollations;
1724 rte->alias = alias;
1725
1726 eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
1727 numaliases = list_length(eref->colnames);
1728
1729 /* fill in any unspecified alias columns */
1730 if (numaliases < list_length(tf->colnames))
1731 eref->colnames = list_concat(eref->colnames,
1732 list_copy_tail(tf->colnames, numaliases));
1733
1734 rte->eref = eref;
1735
1736 /*
1737 * Set flags and access permissions.
1738 *
1739 * Tablefuncs are never checked for access rights (at least, not by the
1740 * RTE permissions mechanism).
1741 */
1742 rte->lateral = lateral;
1743 rte->inh = false; /* never true for tablefunc RTEs */
1744 rte->inFromCl = inFromCl;
1745
1746 rte->requiredPerms = 0;
1747 rte->checkAsUser = InvalidOid;
1748 rte->selectedCols = NULL;
1749 rte->insertedCols = NULL;
1750 rte->updatedCols = NULL;
1751 rte->extraUpdatedCols = NULL;
1752
1753 /*
1754 * Add completed RTE to pstate's range table list, but not to join list
1755 * nor namespace --- caller must do that if appropriate.
1756 */
1757 pstate->p_rtable = lappend(pstate->p_rtable, rte);
1758
1759 return rte;
1760 }
1761
1762 /*
1763 * Add an entry for a VALUES list to the pstate's range table (p_rtable).
1764 *
1765 * This is much like addRangeTableEntry() except that it makes a values RTE.
1766 */
1767 RangeTblEntry *
addRangeTableEntryForValues(ParseState * pstate,List * exprs,List * coltypes,List * coltypmods,List * colcollations,Alias * alias,bool lateral,bool inFromCl)1768 addRangeTableEntryForValues(ParseState *pstate,
1769 List *exprs,
1770 List *coltypes,
1771 List *coltypmods,
1772 List *colcollations,
1773 Alias *alias,
1774 bool lateral,
1775 bool inFromCl)
1776 {
1777 RangeTblEntry *rte = makeNode(RangeTblEntry);
1778 char *refname = alias ? alias->aliasname : pstrdup("*VALUES*");
1779 Alias *eref;
1780 int numaliases;
1781 int numcolumns;
1782
1783 Assert(pstate != NULL);
1784
1785 rte->rtekind = RTE_VALUES;
1786 rte->relid = InvalidOid;
1787 rte->subquery = NULL;
1788 rte->values_lists = exprs;
1789 rte->coltypes = coltypes;
1790 rte->coltypmods = coltypmods;
1791 rte->colcollations = colcollations;
1792 rte->alias = alias;
1793
1794 eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
1795
1796 /* fill in any unspecified alias columns */
1797 numcolumns = list_length((List *) linitial(exprs));
1798 numaliases = list_length(eref->colnames);
1799 while (numaliases < numcolumns)
1800 {
1801 char attrname[64];
1802
1803 numaliases++;
1804 snprintf(attrname, sizeof(attrname), "column%d", numaliases);
1805 eref->colnames = lappend(eref->colnames,
1806 makeString(pstrdup(attrname)));
1807 }
1808 if (numcolumns < numaliases)
1809 ereport(ERROR,
1810 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1811 errmsg("VALUES lists \"%s\" have %d columns available but %d columns specified",
1812 refname, numcolumns, numaliases)));
1813
1814 rte->eref = eref;
1815
1816 /*
1817 * Set flags and access permissions.
1818 *
1819 * Subqueries are never checked for access rights.
1820 */
1821 rte->lateral = lateral;
1822 rte->inh = false; /* never true for values RTEs */
1823 rte->inFromCl = inFromCl;
1824
1825 rte->requiredPerms = 0;
1826 rte->checkAsUser = InvalidOid;
1827 rte->selectedCols = NULL;
1828 rte->insertedCols = NULL;
1829 rte->updatedCols = NULL;
1830 rte->extraUpdatedCols = NULL;
1831
1832 /*
1833 * Add completed RTE to pstate's range table list, but not to join list
1834 * nor namespace --- caller must do that if appropriate.
1835 */
1836 pstate->p_rtable = lappend(pstate->p_rtable, rte);
1837
1838 return rte;
1839 }
1840
1841 /*
1842 * Add an entry for a join to the pstate's range table (p_rtable).
1843 *
1844 * This is much like addRangeTableEntry() except that it makes a join RTE.
1845 */
1846 RangeTblEntry *
addRangeTableEntryForJoin(ParseState * pstate,List * colnames,JoinType jointype,List * aliasvars,Alias * alias,bool inFromCl)1847 addRangeTableEntryForJoin(ParseState *pstate,
1848 List *colnames,
1849 JoinType jointype,
1850 List *aliasvars,
1851 Alias *alias,
1852 bool inFromCl)
1853 {
1854 RangeTblEntry *rte = makeNode(RangeTblEntry);
1855 Alias *eref;
1856 int numaliases;
1857
1858 Assert(pstate != NULL);
1859
1860 /*
1861 * Fail if join has too many columns --- we must be able to reference any
1862 * of the columns with an AttrNumber.
1863 */
1864 if (list_length(aliasvars) > MaxAttrNumber)
1865 ereport(ERROR,
1866 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1867 errmsg("joins can have at most %d columns",
1868 MaxAttrNumber)));
1869
1870 rte->rtekind = RTE_JOIN;
1871 rte->relid = InvalidOid;
1872 rte->subquery = NULL;
1873 rte->jointype = jointype;
1874 rte->joinaliasvars = aliasvars;
1875 rte->alias = alias;
1876
1877 eref = alias ? copyObject(alias) : makeAlias("unnamed_join", NIL);
1878 numaliases = list_length(eref->colnames);
1879
1880 /* fill in any unspecified alias columns */
1881 if (numaliases < list_length(colnames))
1882 eref->colnames = list_concat(eref->colnames,
1883 list_copy_tail(colnames, numaliases));
1884
1885 rte->eref = eref;
1886
1887 /*
1888 * Set flags and access permissions.
1889 *
1890 * Joins are never checked for access rights.
1891 */
1892 rte->lateral = false;
1893 rte->inh = false; /* never true for joins */
1894 rte->inFromCl = inFromCl;
1895
1896 rte->requiredPerms = 0;
1897 rte->checkAsUser = InvalidOid;
1898 rte->selectedCols = NULL;
1899 rte->insertedCols = NULL;
1900 rte->updatedCols = NULL;
1901 rte->extraUpdatedCols = NULL;
1902
1903 /*
1904 * Add completed RTE to pstate's range table list, but not to join list
1905 * nor namespace --- caller must do that if appropriate.
1906 */
1907 pstate->p_rtable = lappend(pstate->p_rtable, rte);
1908
1909 return rte;
1910 }
1911
1912 /*
1913 * Add an entry for a CTE reference to the pstate's range table (p_rtable).
1914 *
1915 * This is much like addRangeTableEntry() except that it makes a CTE RTE.
1916 */
1917 RangeTblEntry *
addRangeTableEntryForCTE(ParseState * pstate,CommonTableExpr * cte,Index levelsup,RangeVar * rv,bool inFromCl)1918 addRangeTableEntryForCTE(ParseState *pstate,
1919 CommonTableExpr *cte,
1920 Index levelsup,
1921 RangeVar *rv,
1922 bool inFromCl)
1923 {
1924 RangeTblEntry *rte = makeNode(RangeTblEntry);
1925 Alias *alias = rv->alias;
1926 char *refname = alias ? alias->aliasname : cte->ctename;
1927 Alias *eref;
1928 int numaliases;
1929 int varattno;
1930 ListCell *lc;
1931
1932 Assert(pstate != NULL);
1933
1934 rte->rtekind = RTE_CTE;
1935 rte->ctename = cte->ctename;
1936 rte->ctelevelsup = levelsup;
1937
1938 /* Self-reference if and only if CTE's parse analysis isn't completed */
1939 rte->self_reference = !IsA(cte->ctequery, Query);
1940 Assert(cte->cterecursive || !rte->self_reference);
1941 /* Bump the CTE's refcount if this isn't a self-reference */
1942 if (!rte->self_reference)
1943 cte->cterefcount++;
1944
1945 /*
1946 * We throw error if the CTE is INSERT/UPDATE/DELETE without RETURNING.
1947 * This won't get checked in case of a self-reference, but that's OK
1948 * because data-modifying CTEs aren't allowed to be recursive anyhow.
1949 */
1950 if (IsA(cte->ctequery, Query))
1951 {
1952 Query *ctequery = (Query *) cte->ctequery;
1953
1954 if (ctequery->commandType != CMD_SELECT &&
1955 ctequery->returningList == NIL)
1956 ereport(ERROR,
1957 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1958 errmsg("WITH query \"%s\" does not have a RETURNING clause",
1959 cte->ctename),
1960 parser_errposition(pstate, rv->location)));
1961 }
1962
1963 rte->coltypes = cte->ctecoltypes;
1964 rte->coltypmods = cte->ctecoltypmods;
1965 rte->colcollations = cte->ctecolcollations;
1966
1967 rte->alias = alias;
1968 if (alias)
1969 eref = copyObject(alias);
1970 else
1971 eref = makeAlias(refname, NIL);
1972 numaliases = list_length(eref->colnames);
1973
1974 /* fill in any unspecified alias columns */
1975 varattno = 0;
1976 foreach(lc, cte->ctecolnames)
1977 {
1978 varattno++;
1979 if (varattno > numaliases)
1980 eref->colnames = lappend(eref->colnames, lfirst(lc));
1981 }
1982 if (varattno < numaliases)
1983 ereport(ERROR,
1984 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1985 errmsg("table \"%s\" has %d columns available but %d columns specified",
1986 refname, varattno, numaliases)));
1987
1988 rte->eref = eref;
1989
1990 /*
1991 * Set flags and access permissions.
1992 *
1993 * Subqueries are never checked for access rights.
1994 */
1995 rte->lateral = false;
1996 rte->inh = false; /* never true for subqueries */
1997 rte->inFromCl = inFromCl;
1998
1999 rte->requiredPerms = 0;
2000 rte->checkAsUser = InvalidOid;
2001 rte->selectedCols = NULL;
2002 rte->insertedCols = NULL;
2003 rte->updatedCols = NULL;
2004 rte->extraUpdatedCols = NULL;
2005
2006 /*
2007 * Add completed RTE to pstate's range table list, but not to join list
2008 * nor namespace --- caller must do that if appropriate.
2009 */
2010 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2011
2012 return rte;
2013 }
2014
2015 /*
2016 * Add an entry for an ephemeral named relation reference to the pstate's
2017 * range table (p_rtable).
2018 *
2019 * It is expected that the RangeVar, which up until now is only known to be an
2020 * ephemeral named relation, will (in conjunction with the QueryEnvironment in
2021 * the ParseState), create a RangeTblEntry for a specific *kind* of ephemeral
2022 * named relation, based on enrtype.
2023 *
2024 * This is much like addRangeTableEntry() except that it makes an RTE for an
2025 * ephemeral named relation.
2026 */
2027 RangeTblEntry *
addRangeTableEntryForENR(ParseState * pstate,RangeVar * rv,bool inFromCl)2028 addRangeTableEntryForENR(ParseState *pstate,
2029 RangeVar *rv,
2030 bool inFromCl)
2031 {
2032 RangeTblEntry *rte = makeNode(RangeTblEntry);
2033 Alias *alias = rv->alias;
2034 char *refname = alias ? alias->aliasname : rv->relname;
2035 EphemeralNamedRelationMetadata enrmd;
2036 TupleDesc tupdesc;
2037 int attno;
2038
2039 Assert(pstate != NULL);
2040 enrmd = get_visible_ENR(pstate, rv->relname);
2041 Assert(enrmd != NULL);
2042
2043 switch (enrmd->enrtype)
2044 {
2045 case ENR_NAMED_TUPLESTORE:
2046 rte->rtekind = RTE_NAMEDTUPLESTORE;
2047 break;
2048
2049 default:
2050 elog(ERROR, "unexpected enrtype: %d", enrmd->enrtype);
2051 return NULL; /* for fussy compilers */
2052 }
2053
2054 /*
2055 * Record dependency on a relation. This allows plans to be invalidated
2056 * if they access transition tables linked to a table that is altered.
2057 */
2058 rte->relid = enrmd->reliddesc;
2059
2060 /*
2061 * Build the list of effective column names using user-supplied aliases
2062 * and/or actual column names.
2063 */
2064 tupdesc = ENRMetadataGetTupDesc(enrmd);
2065 rte->eref = makeAlias(refname, NIL);
2066 buildRelationAliases(tupdesc, alias, rte->eref);
2067
2068 /* Record additional data for ENR, including column type info */
2069 rte->enrname = enrmd->name;
2070 rte->enrtuples = enrmd->enrtuples;
2071 rte->coltypes = NIL;
2072 rte->coltypmods = NIL;
2073 rte->colcollations = NIL;
2074 for (attno = 1; attno <= tupdesc->natts; ++attno)
2075 {
2076 Form_pg_attribute att = TupleDescAttr(tupdesc, attno - 1);
2077
2078 if (att->attisdropped)
2079 {
2080 /* Record zeroes for a dropped column */
2081 rte->coltypes = lappend_oid(rte->coltypes, InvalidOid);
2082 rte->coltypmods = lappend_int(rte->coltypmods, 0);
2083 rte->colcollations = lappend_oid(rte->colcollations, InvalidOid);
2084 }
2085 else
2086 {
2087 /* Let's just make sure we can tell this isn't dropped */
2088 if (att->atttypid == InvalidOid)
2089 elog(ERROR, "atttypid is invalid for non-dropped column in \"%s\"",
2090 rv->relname);
2091 rte->coltypes = lappend_oid(rte->coltypes, att->atttypid);
2092 rte->coltypmods = lappend_int(rte->coltypmods, att->atttypmod);
2093 rte->colcollations = lappend_oid(rte->colcollations,
2094 att->attcollation);
2095 }
2096 }
2097
2098 /*
2099 * Set flags and access permissions.
2100 *
2101 * ENRs are never checked for access rights.
2102 */
2103 rte->lateral = false;
2104 rte->inh = false; /* never true for ENRs */
2105 rte->inFromCl = inFromCl;
2106
2107 rte->requiredPerms = 0;
2108 rte->checkAsUser = InvalidOid;
2109 rte->selectedCols = NULL;
2110
2111 /*
2112 * Add completed RTE to pstate's range table list, but not to join list
2113 * nor namespace --- caller must do that if appropriate.
2114 */
2115 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2116
2117 return rte;
2118 }
2119
2120
2121 /*
2122 * Has the specified refname been selected FOR UPDATE/FOR SHARE?
2123 *
2124 * This is used when we have not yet done transformLockingClause, but need
2125 * to know the correct lock to take during initial opening of relations.
2126 *
2127 * Note: we pay no attention to whether it's FOR UPDATE vs FOR SHARE,
2128 * since the table-level lock is the same either way.
2129 */
2130 bool
isLockedRefname(ParseState * pstate,const char * refname)2131 isLockedRefname(ParseState *pstate, const char *refname)
2132 {
2133 ListCell *l;
2134
2135 /*
2136 * If we are in a subquery specified as locked FOR UPDATE/SHARE from
2137 * parent level, then act as though there's a generic FOR UPDATE here.
2138 */
2139 if (pstate->p_locked_from_parent)
2140 return true;
2141
2142 foreach(l, pstate->p_locking_clause)
2143 {
2144 LockingClause *lc = (LockingClause *) lfirst(l);
2145
2146 if (lc->lockedRels == NIL)
2147 {
2148 /* all tables used in query */
2149 return true;
2150 }
2151 else
2152 {
2153 /* just the named tables */
2154 ListCell *l2;
2155
2156 foreach(l2, lc->lockedRels)
2157 {
2158 RangeVar *thisrel = (RangeVar *) lfirst(l2);
2159
2160 if (strcmp(refname, thisrel->relname) == 0)
2161 return true;
2162 }
2163 }
2164 }
2165 return false;
2166 }
2167
2168 /*
2169 * Add the given RTE as a top-level entry in the pstate's join list
2170 * and/or namespace list. (We assume caller has checked for any
2171 * namespace conflicts.) The RTE is always marked as unconditionally
2172 * visible, that is, not LATERAL-only.
2173 *
2174 * Note: some callers know that they can find the new ParseNamespaceItem
2175 * at the end of the pstate->p_namespace list. This is a bit ugly but not
2176 * worth complicating this function's signature for.
2177 */
2178 void
addRTEtoQuery(ParseState * pstate,RangeTblEntry * rte,bool addToJoinList,bool addToRelNameSpace,bool addToVarNameSpace)2179 addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
2180 bool addToJoinList,
2181 bool addToRelNameSpace, bool addToVarNameSpace)
2182 {
2183 if (addToJoinList)
2184 {
2185 int rtindex = RTERangeTablePosn(pstate, rte, NULL);
2186 RangeTblRef *rtr = makeNode(RangeTblRef);
2187
2188 rtr->rtindex = rtindex;
2189 pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
2190 }
2191 if (addToRelNameSpace || addToVarNameSpace)
2192 {
2193 ParseNamespaceItem *nsitem;
2194
2195 nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
2196 nsitem->p_rte = rte;
2197 nsitem->p_rel_visible = addToRelNameSpace;
2198 nsitem->p_cols_visible = addToVarNameSpace;
2199 nsitem->p_lateral_only = false;
2200 nsitem->p_lateral_ok = true;
2201 pstate->p_namespace = lappend(pstate->p_namespace, nsitem);
2202 }
2203 }
2204
2205 /*
2206 * expandRTE -- expand the columns of a rangetable entry
2207 *
2208 * This creates lists of an RTE's column names (aliases if provided, else
2209 * real names) and Vars for each column. Only user columns are considered.
2210 * If include_dropped is false then dropped columns are omitted from the
2211 * results. If include_dropped is true then empty strings and NULL constants
2212 * (not Vars!) are returned for dropped columns.
2213 *
2214 * rtindex, sublevels_up, and location are the varno, varlevelsup, and location
2215 * values to use in the created Vars. Ordinarily rtindex should match the
2216 * actual position of the RTE in its rangetable.
2217 *
2218 * The output lists go into *colnames and *colvars.
2219 * If only one of the two kinds of output list is needed, pass NULL for the
2220 * output pointer for the unwanted one.
2221 */
2222 void
expandRTE(RangeTblEntry * rte,int rtindex,int sublevels_up,int location,bool include_dropped,List ** colnames,List ** colvars)2223 expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
2224 int location, bool include_dropped,
2225 List **colnames, List **colvars)
2226 {
2227 int varattno;
2228
2229 if (colnames)
2230 *colnames = NIL;
2231 if (colvars)
2232 *colvars = NIL;
2233
2234 switch (rte->rtekind)
2235 {
2236 case RTE_RELATION:
2237 /* Ordinary relation RTE */
2238 expandRelation(rte->relid, rte->eref,
2239 rtindex, sublevels_up, location,
2240 include_dropped, colnames, colvars);
2241 break;
2242 case RTE_SUBQUERY:
2243 {
2244 /* Subquery RTE */
2245 ListCell *aliasp_item = list_head(rte->eref->colnames);
2246 ListCell *tlistitem;
2247
2248 varattno = 0;
2249 foreach(tlistitem, rte->subquery->targetList)
2250 {
2251 TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
2252
2253 if (te->resjunk)
2254 continue;
2255 varattno++;
2256 Assert(varattno == te->resno);
2257
2258 /*
2259 * In scenarios where columns have been added to a view
2260 * since the outer query was originally parsed, there can
2261 * be more items in the subquery tlist than the outer
2262 * query expects. We should ignore such extra column(s)
2263 * --- compare the behavior for composite-returning
2264 * functions, in the RTE_FUNCTION case below.
2265 */
2266 if (!aliasp_item)
2267 break;
2268
2269 if (colnames)
2270 {
2271 char *label = strVal(lfirst(aliasp_item));
2272
2273 *colnames = lappend(*colnames, makeString(pstrdup(label)));
2274 }
2275
2276 if (colvars)
2277 {
2278 Var *varnode;
2279
2280 varnode = makeVar(rtindex, varattno,
2281 exprType((Node *) te->expr),
2282 exprTypmod((Node *) te->expr),
2283 exprCollation((Node *) te->expr),
2284 sublevels_up);
2285 varnode->location = location;
2286
2287 *colvars = lappend(*colvars, varnode);
2288 }
2289
2290 aliasp_item = lnext(aliasp_item);
2291 }
2292 }
2293 break;
2294 case RTE_FUNCTION:
2295 {
2296 /* Function RTE */
2297 int atts_done = 0;
2298 ListCell *lc;
2299
2300 foreach(lc, rte->functions)
2301 {
2302 RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
2303 TypeFuncClass functypclass;
2304 Oid funcrettype;
2305 TupleDesc tupdesc;
2306
2307 functypclass = get_expr_result_type(rtfunc->funcexpr,
2308 &funcrettype,
2309 &tupdesc);
2310 if (functypclass == TYPEFUNC_COMPOSITE ||
2311 functypclass == TYPEFUNC_COMPOSITE_DOMAIN)
2312 {
2313 /* Composite data type, e.g. a table's row type */
2314 Assert(tupdesc);
2315 expandTupleDesc(tupdesc, rte->eref,
2316 rtfunc->funccolcount, atts_done,
2317 rtindex, sublevels_up, location,
2318 include_dropped, colnames, colvars);
2319 }
2320 else if (functypclass == TYPEFUNC_SCALAR)
2321 {
2322 /* Base data type, i.e. scalar */
2323 if (colnames)
2324 *colnames = lappend(*colnames,
2325 list_nth(rte->eref->colnames,
2326 atts_done));
2327
2328 if (colvars)
2329 {
2330 Var *varnode;
2331
2332 varnode = makeVar(rtindex, atts_done + 1,
2333 funcrettype, -1,
2334 exprCollation(rtfunc->funcexpr),
2335 sublevels_up);
2336 varnode->location = location;
2337
2338 *colvars = lappend(*colvars, varnode);
2339 }
2340 }
2341 else if (functypclass == TYPEFUNC_RECORD)
2342 {
2343 if (colnames)
2344 {
2345 List *namelist;
2346
2347 /* extract appropriate subset of column list */
2348 namelist = list_copy_tail(rte->eref->colnames,
2349 atts_done);
2350 namelist = list_truncate(namelist,
2351 rtfunc->funccolcount);
2352 *colnames = list_concat(*colnames, namelist);
2353 }
2354
2355 if (colvars)
2356 {
2357 ListCell *l1;
2358 ListCell *l2;
2359 ListCell *l3;
2360 int attnum = atts_done;
2361
2362 forthree(l1, rtfunc->funccoltypes,
2363 l2, rtfunc->funccoltypmods,
2364 l3, rtfunc->funccolcollations)
2365 {
2366 Oid attrtype = lfirst_oid(l1);
2367 int32 attrtypmod = lfirst_int(l2);
2368 Oid attrcollation = lfirst_oid(l3);
2369 Var *varnode;
2370
2371 attnum++;
2372 varnode = makeVar(rtindex,
2373 attnum,
2374 attrtype,
2375 attrtypmod,
2376 attrcollation,
2377 sublevels_up);
2378 varnode->location = location;
2379 *colvars = lappend(*colvars, varnode);
2380 }
2381 }
2382 }
2383 else
2384 {
2385 /* addRangeTableEntryForFunction should've caught this */
2386 elog(ERROR, "function in FROM has unsupported return type");
2387 }
2388 atts_done += rtfunc->funccolcount;
2389 }
2390
2391 /* Append the ordinality column if any */
2392 if (rte->funcordinality)
2393 {
2394 if (colnames)
2395 *colnames = lappend(*colnames,
2396 llast(rte->eref->colnames));
2397
2398 if (colvars)
2399 {
2400 Var *varnode = makeVar(rtindex,
2401 atts_done + 1,
2402 INT8OID,
2403 -1,
2404 InvalidOid,
2405 sublevels_up);
2406
2407 *colvars = lappend(*colvars, varnode);
2408 }
2409 }
2410 }
2411 break;
2412 case RTE_JOIN:
2413 {
2414 /* Join RTE */
2415 ListCell *colname;
2416 ListCell *aliasvar;
2417
2418 Assert(list_length(rte->eref->colnames) == list_length(rte->joinaliasvars));
2419
2420 varattno = 0;
2421 forboth(colname, rte->eref->colnames, aliasvar, rte->joinaliasvars)
2422 {
2423 Node *avar = (Node *) lfirst(aliasvar);
2424
2425 varattno++;
2426
2427 /*
2428 * During ordinary parsing, there will never be any
2429 * deleted columns in the join; but we have to check since
2430 * this routine is also used by the rewriter, and joins
2431 * found in stored rules might have join columns for
2432 * since-deleted columns. This will be signaled by a null
2433 * pointer in the alias-vars list.
2434 */
2435 if (avar == NULL)
2436 {
2437 if (include_dropped)
2438 {
2439 if (colnames)
2440 *colnames = lappend(*colnames,
2441 makeString(pstrdup("")));
2442 if (colvars)
2443 {
2444 /*
2445 * Can't use join's column type here (it might
2446 * be dropped!); but it doesn't really matter
2447 * what type the Const claims to be.
2448 */
2449 *colvars = lappend(*colvars,
2450 makeNullConst(INT4OID, -1,
2451 InvalidOid));
2452 }
2453 }
2454 continue;
2455 }
2456
2457 if (colnames)
2458 {
2459 char *label = strVal(lfirst(colname));
2460
2461 *colnames = lappend(*colnames,
2462 makeString(pstrdup(label)));
2463 }
2464
2465 if (colvars)
2466 {
2467 Var *varnode;
2468
2469 varnode = makeVar(rtindex, varattno,
2470 exprType(avar),
2471 exprTypmod(avar),
2472 exprCollation(avar),
2473 sublevels_up);
2474 varnode->location = location;
2475
2476 *colvars = lappend(*colvars, varnode);
2477 }
2478 }
2479 }
2480 break;
2481 case RTE_TABLEFUNC:
2482 case RTE_VALUES:
2483 case RTE_CTE:
2484 case RTE_NAMEDTUPLESTORE:
2485 {
2486 /* Tablefunc, Values, CTE, or ENR RTE */
2487 ListCell *aliasp_item = list_head(rte->eref->colnames);
2488 ListCell *lct;
2489 ListCell *lcm;
2490 ListCell *lcc;
2491
2492 varattno = 0;
2493 forthree(lct, rte->coltypes,
2494 lcm, rte->coltypmods,
2495 lcc, rte->colcollations)
2496 {
2497 Oid coltype = lfirst_oid(lct);
2498 int32 coltypmod = lfirst_int(lcm);
2499 Oid colcoll = lfirst_oid(lcc);
2500
2501 varattno++;
2502
2503 if (colnames)
2504 {
2505 /* Assume there is one alias per output column */
2506 if (OidIsValid(coltype))
2507 {
2508 char *label = strVal(lfirst(aliasp_item));
2509
2510 *colnames = lappend(*colnames,
2511 makeString(pstrdup(label)));
2512 }
2513 else if (include_dropped)
2514 *colnames = lappend(*colnames,
2515 makeString(pstrdup("")));
2516
2517 aliasp_item = lnext(aliasp_item);
2518 }
2519
2520 if (colvars)
2521 {
2522 if (OidIsValid(coltype))
2523 {
2524 Var *varnode;
2525
2526 varnode = makeVar(rtindex, varattno,
2527 coltype, coltypmod, colcoll,
2528 sublevels_up);
2529 varnode->location = location;
2530
2531 *colvars = lappend(*colvars, varnode);
2532 }
2533 else if (include_dropped)
2534 {
2535 /*
2536 * It doesn't really matter what type the Const
2537 * claims to be.
2538 */
2539 *colvars = lappend(*colvars,
2540 makeNullConst(INT4OID, -1,
2541 InvalidOid));
2542 }
2543 }
2544 }
2545 }
2546 break;
2547 case RTE_RESULT:
2548 /* These expose no columns, so nothing to do */
2549 break;
2550 default:
2551 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
2552 }
2553 }
2554
2555 /*
2556 * expandRelation -- expandRTE subroutine
2557 */
2558 static void
expandRelation(Oid relid,Alias * eref,int rtindex,int sublevels_up,int location,bool include_dropped,List ** colnames,List ** colvars)2559 expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up,
2560 int location, bool include_dropped,
2561 List **colnames, List **colvars)
2562 {
2563 Relation rel;
2564
2565 /* Get the tupledesc and turn it over to expandTupleDesc */
2566 rel = relation_open(relid, AccessShareLock);
2567 expandTupleDesc(rel->rd_att, eref, rel->rd_att->natts, 0,
2568 rtindex, sublevels_up,
2569 location, include_dropped,
2570 colnames, colvars);
2571 relation_close(rel, AccessShareLock);
2572 }
2573
2574 /*
2575 * expandTupleDesc -- expandRTE subroutine
2576 *
2577 * Generate names and/or Vars for the first "count" attributes of the tupdesc,
2578 * and append them to colnames/colvars. "offset" is added to the varattno
2579 * that each Var would otherwise have, and we also skip the first "offset"
2580 * entries in eref->colnames. (These provisions allow use of this code for
2581 * an individual composite-returning function in an RTE_FUNCTION RTE.)
2582 */
2583 static void
expandTupleDesc(TupleDesc tupdesc,Alias * eref,int count,int offset,int rtindex,int sublevels_up,int location,bool include_dropped,List ** colnames,List ** colvars)2584 expandTupleDesc(TupleDesc tupdesc, Alias *eref, int count, int offset,
2585 int rtindex, int sublevels_up,
2586 int location, bool include_dropped,
2587 List **colnames, List **colvars)
2588 {
2589 ListCell *aliascell = list_head(eref->colnames);
2590 int varattno;
2591
2592 if (colnames)
2593 {
2594 int i;
2595
2596 for (i = 0; i < offset; i++)
2597 {
2598 if (aliascell)
2599 aliascell = lnext(aliascell);
2600 }
2601 }
2602
2603 Assert(count <= tupdesc->natts);
2604 for (varattno = 0; varattno < count; varattno++)
2605 {
2606 Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
2607
2608 if (attr->attisdropped)
2609 {
2610 if (include_dropped)
2611 {
2612 if (colnames)
2613 *colnames = lappend(*colnames, makeString(pstrdup("")));
2614 if (colvars)
2615 {
2616 /*
2617 * can't use atttypid here, but it doesn't really matter
2618 * what type the Const claims to be.
2619 */
2620 *colvars = lappend(*colvars,
2621 makeNullConst(INT4OID, -1, InvalidOid));
2622 }
2623 }
2624 if (aliascell)
2625 aliascell = lnext(aliascell);
2626 continue;
2627 }
2628
2629 if (colnames)
2630 {
2631 char *label;
2632
2633 if (aliascell)
2634 {
2635 label = strVal(lfirst(aliascell));
2636 aliascell = lnext(aliascell);
2637 }
2638 else
2639 {
2640 /* If we run out of aliases, use the underlying name */
2641 label = NameStr(attr->attname);
2642 }
2643 *colnames = lappend(*colnames, makeString(pstrdup(label)));
2644 }
2645
2646 if (colvars)
2647 {
2648 Var *varnode;
2649
2650 varnode = makeVar(rtindex, varattno + offset + 1,
2651 attr->atttypid, attr->atttypmod,
2652 attr->attcollation,
2653 sublevels_up);
2654 varnode->location = location;
2655
2656 *colvars = lappend(*colvars, varnode);
2657 }
2658 }
2659 }
2660
2661 /*
2662 * expandRelAttrs -
2663 * Workhorse for "*" expansion: produce a list of targetentries
2664 * for the attributes of the RTE
2665 *
2666 * As with expandRTE, rtindex/sublevels_up determine the varno/varlevelsup
2667 * fields of the Vars produced, and location sets their location.
2668 * pstate->p_next_resno determines the resnos assigned to the TLEs.
2669 * The referenced columns are marked as requiring SELECT access.
2670 */
2671 List *
expandRelAttrs(ParseState * pstate,RangeTblEntry * rte,int rtindex,int sublevels_up,int location)2672 expandRelAttrs(ParseState *pstate, RangeTblEntry *rte,
2673 int rtindex, int sublevels_up, int location)
2674 {
2675 List *names,
2676 *vars;
2677 ListCell *name,
2678 *var;
2679 List *te_list = NIL;
2680
2681 expandRTE(rte, rtindex, sublevels_up, location, false,
2682 &names, &vars);
2683
2684 /*
2685 * Require read access to the table. This is normally redundant with the
2686 * markVarForSelectPriv calls below, but not if the table has zero
2687 * columns.
2688 */
2689 rte->requiredPerms |= ACL_SELECT;
2690
2691 forboth(name, names, var, vars)
2692 {
2693 char *label = strVal(lfirst(name));
2694 Var *varnode = (Var *) lfirst(var);
2695 TargetEntry *te;
2696
2697 te = makeTargetEntry((Expr *) varnode,
2698 (AttrNumber) pstate->p_next_resno++,
2699 label,
2700 false);
2701 te_list = lappend(te_list, te);
2702
2703 /* Require read access to each column */
2704 markVarForSelectPriv(pstate, varnode, rte);
2705 }
2706
2707 Assert(name == NULL && var == NULL); /* lists not the same length? */
2708
2709 return te_list;
2710 }
2711
2712 /*
2713 * get_rte_attribute_name
2714 * Get an attribute name from a RangeTblEntry
2715 *
2716 * This is unlike get_attname() because we use aliases if available.
2717 * In particular, it will work on an RTE for a subselect or join, whereas
2718 * get_attname() only works on real relations.
2719 *
2720 * "*" is returned if the given attnum is InvalidAttrNumber --- this case
2721 * occurs when a Var represents a whole tuple of a relation.
2722 */
2723 char *
get_rte_attribute_name(RangeTblEntry * rte,AttrNumber attnum)2724 get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
2725 {
2726 if (attnum == InvalidAttrNumber)
2727 return "*";
2728
2729 /*
2730 * If there is a user-written column alias, use it.
2731 */
2732 if (rte->alias &&
2733 attnum > 0 && attnum <= list_length(rte->alias->colnames))
2734 return strVal(list_nth(rte->alias->colnames, attnum - 1));
2735
2736 /*
2737 * If the RTE is a relation, go to the system catalogs not the
2738 * eref->colnames list. This is a little slower but it will give the
2739 * right answer if the column has been renamed since the eref list was
2740 * built (which can easily happen for rules).
2741 */
2742 if (rte->rtekind == RTE_RELATION)
2743 return get_attname(rte->relid, attnum, false);
2744
2745 /*
2746 * Otherwise use the column name from eref. There should always be one.
2747 */
2748 if (attnum > 0 && attnum <= list_length(rte->eref->colnames))
2749 return strVal(list_nth(rte->eref->colnames, attnum - 1));
2750
2751 /* else caller gave us a bogus attnum */
2752 elog(ERROR, "invalid attnum %d for rangetable entry %s",
2753 attnum, rte->eref->aliasname);
2754 return NULL; /* keep compiler quiet */
2755 }
2756
2757 /*
2758 * get_rte_attribute_type
2759 * Get attribute type/typmod/collation information from a RangeTblEntry
2760 */
2761 void
get_rte_attribute_type(RangeTblEntry * rte,AttrNumber attnum,Oid * vartype,int32 * vartypmod,Oid * varcollid)2762 get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
2763 Oid *vartype, int32 *vartypmod, Oid *varcollid)
2764 {
2765 switch (rte->rtekind)
2766 {
2767 case RTE_RELATION:
2768 {
2769 /* Plain relation RTE --- get the attribute's type info */
2770 HeapTuple tp;
2771 Form_pg_attribute att_tup;
2772
2773 tp = SearchSysCache2(ATTNUM,
2774 ObjectIdGetDatum(rte->relid),
2775 Int16GetDatum(attnum));
2776 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
2777 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2778 attnum, rte->relid);
2779 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
2780
2781 /*
2782 * If dropped column, pretend it ain't there. See notes in
2783 * scanRTEForColumn.
2784 */
2785 if (att_tup->attisdropped)
2786 ereport(ERROR,
2787 (errcode(ERRCODE_UNDEFINED_COLUMN),
2788 errmsg("column \"%s\" of relation \"%s\" does not exist",
2789 NameStr(att_tup->attname),
2790 get_rel_name(rte->relid))));
2791 *vartype = att_tup->atttypid;
2792 *vartypmod = att_tup->atttypmod;
2793 *varcollid = att_tup->attcollation;
2794 ReleaseSysCache(tp);
2795 }
2796 break;
2797 case RTE_SUBQUERY:
2798 {
2799 /* Subselect RTE --- get type info from subselect's tlist */
2800 TargetEntry *te = get_tle_by_resno(rte->subquery->targetList,
2801 attnum);
2802
2803 if (te == NULL || te->resjunk)
2804 elog(ERROR, "subquery %s does not have attribute %d",
2805 rte->eref->aliasname, attnum);
2806 *vartype = exprType((Node *) te->expr);
2807 *vartypmod = exprTypmod((Node *) te->expr);
2808 *varcollid = exprCollation((Node *) te->expr);
2809 }
2810 break;
2811 case RTE_FUNCTION:
2812 {
2813 /* Function RTE */
2814 ListCell *lc;
2815 int atts_done = 0;
2816
2817 /* Identify which function covers the requested column */
2818 foreach(lc, rte->functions)
2819 {
2820 RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
2821
2822 if (attnum > atts_done &&
2823 attnum <= atts_done + rtfunc->funccolcount)
2824 {
2825 TypeFuncClass functypclass;
2826 Oid funcrettype;
2827 TupleDesc tupdesc;
2828
2829 attnum -= atts_done; /* now relative to this func */
2830 functypclass = get_expr_result_type(rtfunc->funcexpr,
2831 &funcrettype,
2832 &tupdesc);
2833
2834 if (functypclass == TYPEFUNC_COMPOSITE ||
2835 functypclass == TYPEFUNC_COMPOSITE_DOMAIN)
2836 {
2837 /* Composite data type, e.g. a table's row type */
2838 Form_pg_attribute att_tup;
2839
2840 Assert(tupdesc);
2841 Assert(attnum <= tupdesc->natts);
2842 att_tup = TupleDescAttr(tupdesc, attnum - 1);
2843
2844 /*
2845 * If dropped column, pretend it ain't there. See
2846 * notes in scanRTEForColumn.
2847 */
2848 if (att_tup->attisdropped)
2849 ereport(ERROR,
2850 (errcode(ERRCODE_UNDEFINED_COLUMN),
2851 errmsg("column \"%s\" of relation \"%s\" does not exist",
2852 NameStr(att_tup->attname),
2853 rte->eref->aliasname)));
2854 *vartype = att_tup->atttypid;
2855 *vartypmod = att_tup->atttypmod;
2856 *varcollid = att_tup->attcollation;
2857 }
2858 else if (functypclass == TYPEFUNC_SCALAR)
2859 {
2860 /* Base data type, i.e. scalar */
2861 *vartype = funcrettype;
2862 *vartypmod = -1;
2863 *varcollid = exprCollation(rtfunc->funcexpr);
2864 }
2865 else if (functypclass == TYPEFUNC_RECORD)
2866 {
2867 *vartype = list_nth_oid(rtfunc->funccoltypes,
2868 attnum - 1);
2869 *vartypmod = list_nth_int(rtfunc->funccoltypmods,
2870 attnum - 1);
2871 *varcollid = list_nth_oid(rtfunc->funccolcollations,
2872 attnum - 1);
2873 }
2874 else
2875 {
2876 /*
2877 * addRangeTableEntryForFunction should've caught
2878 * this
2879 */
2880 elog(ERROR, "function in FROM has unsupported return type");
2881 }
2882 return;
2883 }
2884 atts_done += rtfunc->funccolcount;
2885 }
2886
2887 /* If we get here, must be looking for the ordinality column */
2888 if (rte->funcordinality && attnum == atts_done + 1)
2889 {
2890 *vartype = INT8OID;
2891 *vartypmod = -1;
2892 *varcollid = InvalidOid;
2893 return;
2894 }
2895
2896 /* this probably can't happen ... */
2897 ereport(ERROR,
2898 (errcode(ERRCODE_UNDEFINED_COLUMN),
2899 errmsg("column %d of relation \"%s\" does not exist",
2900 attnum,
2901 rte->eref->aliasname)));
2902 }
2903 break;
2904 case RTE_JOIN:
2905 {
2906 /*
2907 * Join RTE --- get type info from join RTE's alias variable
2908 */
2909 Node *aliasvar;
2910
2911 Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
2912 aliasvar = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
2913 Assert(aliasvar != NULL);
2914 *vartype = exprType(aliasvar);
2915 *vartypmod = exprTypmod(aliasvar);
2916 *varcollid = exprCollation(aliasvar);
2917 }
2918 break;
2919 case RTE_TABLEFUNC:
2920 case RTE_VALUES:
2921 case RTE_CTE:
2922 case RTE_NAMEDTUPLESTORE:
2923 {
2924 /*
2925 * tablefunc, VALUES, CTE, or ENR RTE --- get type info from
2926 * lists in the RTE
2927 */
2928 Assert(attnum > 0 && attnum <= list_length(rte->coltypes));
2929 *vartype = list_nth_oid(rte->coltypes, attnum - 1);
2930 *vartypmod = list_nth_int(rte->coltypmods, attnum - 1);
2931 *varcollid = list_nth_oid(rte->colcollations, attnum - 1);
2932
2933 /* For ENR, better check for dropped column */
2934 if (!OidIsValid(*vartype))
2935 ereport(ERROR,
2936 (errcode(ERRCODE_UNDEFINED_COLUMN),
2937 errmsg("column %d of relation \"%s\" does not exist",
2938 attnum,
2939 rte->eref->aliasname)));
2940 }
2941 break;
2942 case RTE_RESULT:
2943 /* this probably can't happen ... */
2944 ereport(ERROR,
2945 (errcode(ERRCODE_UNDEFINED_COLUMN),
2946 errmsg("column %d of relation \"%s\" does not exist",
2947 attnum,
2948 rte->eref->aliasname)));
2949 break;
2950 default:
2951 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
2952 }
2953 }
2954
2955 /*
2956 * get_rte_attribute_is_dropped
2957 * Check whether attempted attribute ref is to a dropped column
2958 */
2959 bool
get_rte_attribute_is_dropped(RangeTblEntry * rte,AttrNumber attnum)2960 get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
2961 {
2962 bool result;
2963
2964 switch (rte->rtekind)
2965 {
2966 case RTE_RELATION:
2967 {
2968 /*
2969 * Plain relation RTE --- get the attribute's catalog entry
2970 */
2971 HeapTuple tp;
2972 Form_pg_attribute att_tup;
2973
2974 tp = SearchSysCache2(ATTNUM,
2975 ObjectIdGetDatum(rte->relid),
2976 Int16GetDatum(attnum));
2977 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
2978 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2979 attnum, rte->relid);
2980 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
2981 result = att_tup->attisdropped;
2982 ReleaseSysCache(tp);
2983 }
2984 break;
2985 case RTE_SUBQUERY:
2986 case RTE_TABLEFUNC:
2987 case RTE_VALUES:
2988 case RTE_CTE:
2989
2990 /*
2991 * Subselect, Table Functions, Values, CTE RTEs never have dropped
2992 * columns
2993 */
2994 result = false;
2995 break;
2996 case RTE_NAMEDTUPLESTORE:
2997 {
2998 /* Check dropped-ness by testing for valid coltype */
2999 if (attnum <= 0 ||
3000 attnum > list_length(rte->coltypes))
3001 elog(ERROR, "invalid varattno %d", attnum);
3002 result = !OidIsValid((list_nth_oid(rte->coltypes, attnum - 1)));
3003 }
3004 break;
3005 case RTE_JOIN:
3006 {
3007 /*
3008 * A join RTE would not have dropped columns when constructed,
3009 * but one in a stored rule might contain columns that were
3010 * dropped from the underlying tables, if said columns are
3011 * nowhere explicitly referenced in the rule. This will be
3012 * signaled to us by a null pointer in the joinaliasvars list.
3013 */
3014 Var *aliasvar;
3015
3016 if (attnum <= 0 ||
3017 attnum > list_length(rte->joinaliasvars))
3018 elog(ERROR, "invalid varattno %d", attnum);
3019 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
3020
3021 result = (aliasvar == NULL);
3022 }
3023 break;
3024 case RTE_FUNCTION:
3025 {
3026 /* Function RTE */
3027 ListCell *lc;
3028 int atts_done = 0;
3029
3030 /*
3031 * Dropped attributes are only possible with functions that
3032 * return named composite types. In such a case we have to
3033 * look up the result type to see if it currently has this
3034 * column dropped. So first, loop over the funcs until we
3035 * find the one that covers the requested column.
3036 */
3037 foreach(lc, rte->functions)
3038 {
3039 RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
3040
3041 if (attnum > atts_done &&
3042 attnum <= atts_done + rtfunc->funccolcount)
3043 {
3044 TupleDesc tupdesc;
3045
3046 tupdesc = get_expr_result_tupdesc(rtfunc->funcexpr,
3047 true);
3048 if (tupdesc)
3049 {
3050 /* Composite data type, e.g. a table's row type */
3051 Form_pg_attribute att_tup;
3052
3053 Assert(tupdesc);
3054 Assert(attnum - atts_done <= tupdesc->natts);
3055 att_tup = TupleDescAttr(tupdesc,
3056 attnum - atts_done - 1);
3057 return att_tup->attisdropped;
3058 }
3059 /* Otherwise, it can't have any dropped columns */
3060 return false;
3061 }
3062 atts_done += rtfunc->funccolcount;
3063 }
3064
3065 /* If we get here, must be looking for the ordinality column */
3066 if (rte->funcordinality && attnum == atts_done + 1)
3067 return false;
3068
3069 /* this probably can't happen ... */
3070 ereport(ERROR,
3071 (errcode(ERRCODE_UNDEFINED_COLUMN),
3072 errmsg("column %d of relation \"%s\" does not exist",
3073 attnum,
3074 rte->eref->aliasname)));
3075 result = false; /* keep compiler quiet */
3076 }
3077 break;
3078 case RTE_RESULT:
3079 /* this probably can't happen ... */
3080 ereport(ERROR,
3081 (errcode(ERRCODE_UNDEFINED_COLUMN),
3082 errmsg("column %d of relation \"%s\" does not exist",
3083 attnum,
3084 rte->eref->aliasname)));
3085 result = false; /* keep compiler quiet */
3086 break;
3087 default:
3088 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
3089 result = false; /* keep compiler quiet */
3090 }
3091
3092 return result;
3093 }
3094
3095 /*
3096 * Given a targetlist and a resno, return the matching TargetEntry
3097 *
3098 * Returns NULL if resno is not present in list.
3099 *
3100 * Note: we need to search, rather than just indexing with list_nth(),
3101 * because not all tlists are sorted by resno.
3102 */
3103 TargetEntry *
get_tle_by_resno(List * tlist,AttrNumber resno)3104 get_tle_by_resno(List *tlist, AttrNumber resno)
3105 {
3106 ListCell *l;
3107
3108 foreach(l, tlist)
3109 {
3110 TargetEntry *tle = (TargetEntry *) lfirst(l);
3111
3112 if (tle->resno == resno)
3113 return tle;
3114 }
3115 return NULL;
3116 }
3117
3118 /*
3119 * Given a Query and rangetable index, return relation's RowMarkClause if any
3120 *
3121 * Returns NULL if relation is not selected FOR UPDATE/SHARE
3122 */
3123 RowMarkClause *
get_parse_rowmark(Query * qry,Index rtindex)3124 get_parse_rowmark(Query *qry, Index rtindex)
3125 {
3126 ListCell *l;
3127
3128 foreach(l, qry->rowMarks)
3129 {
3130 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
3131
3132 if (rc->rti == rtindex)
3133 return rc;
3134 }
3135 return NULL;
3136 }
3137
3138 /*
3139 * given relation and att name, return attnum of variable
3140 *
3141 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
3142 *
3143 * This should only be used if the relation is already
3144 * table_open()'ed. Use the cache version get_attnum()
3145 * for access to non-opened relations.
3146 */
3147 int
attnameAttNum(Relation rd,const char * attname,bool sysColOK)3148 attnameAttNum(Relation rd, const char *attname, bool sysColOK)
3149 {
3150 int i;
3151
3152 for (i = 0; i < RelationGetNumberOfAttributes(rd); i++)
3153 {
3154 Form_pg_attribute att = TupleDescAttr(rd->rd_att, i);
3155
3156 if (namestrcmp(&(att->attname), attname) == 0 && !att->attisdropped)
3157 return i + 1;
3158 }
3159
3160 if (sysColOK)
3161 {
3162 if ((i = specialAttNum(attname)) != InvalidAttrNumber)
3163 return i;
3164 }
3165
3166 /* on failure */
3167 return InvalidAttrNumber;
3168 }
3169
3170 /* specialAttNum()
3171 *
3172 * Check attribute name to see if it is "special", e.g. "xmin".
3173 * - thomas 2000-02-07
3174 *
3175 * Note: this only discovers whether the name could be a system attribute.
3176 * Caller needs to ensure that it really is an attribute of the rel.
3177 */
3178 static int
specialAttNum(const char * attname)3179 specialAttNum(const char *attname)
3180 {
3181 const FormData_pg_attribute *sysatt;
3182
3183 sysatt = SystemAttributeByName(attname);
3184 if (sysatt != NULL)
3185 return sysatt->attnum;
3186 return InvalidAttrNumber;
3187 }
3188
3189
3190 /*
3191 * given attribute id, return name of that attribute
3192 *
3193 * This should only be used if the relation is already
3194 * table_open()'ed. Use the cache version get_atttype()
3195 * for access to non-opened relations.
3196 */
3197 const NameData *
attnumAttName(Relation rd,int attid)3198 attnumAttName(Relation rd, int attid)
3199 {
3200 if (attid <= 0)
3201 {
3202 const FormData_pg_attribute *sysatt;
3203
3204 sysatt = SystemAttributeDefinition(attid);
3205 return &sysatt->attname;
3206 }
3207 if (attid > rd->rd_att->natts)
3208 elog(ERROR, "invalid attribute number %d", attid);
3209 return &TupleDescAttr(rd->rd_att, attid - 1)->attname;
3210 }
3211
3212 /*
3213 * given attribute id, return type of that attribute
3214 *
3215 * This should only be used if the relation is already
3216 * table_open()'ed. Use the cache version get_atttype()
3217 * for access to non-opened relations.
3218 */
3219 Oid
attnumTypeId(Relation rd,int attid)3220 attnumTypeId(Relation rd, int attid)
3221 {
3222 if (attid <= 0)
3223 {
3224 const FormData_pg_attribute *sysatt;
3225
3226 sysatt = SystemAttributeDefinition(attid);
3227 return sysatt->atttypid;
3228 }
3229 if (attid > rd->rd_att->natts)
3230 elog(ERROR, "invalid attribute number %d", attid);
3231 return TupleDescAttr(rd->rd_att, attid - 1)->atttypid;
3232 }
3233
3234 /*
3235 * given attribute id, return collation of that attribute
3236 *
3237 * This should only be used if the relation is already table_open()'ed.
3238 */
3239 Oid
attnumCollationId(Relation rd,int attid)3240 attnumCollationId(Relation rd, int attid)
3241 {
3242 if (attid <= 0)
3243 {
3244 /* All system attributes are of noncollatable types. */
3245 return InvalidOid;
3246 }
3247 if (attid > rd->rd_att->natts)
3248 elog(ERROR, "invalid attribute number %d", attid);
3249 return TupleDescAttr(rd->rd_att, attid - 1)->attcollation;
3250 }
3251
3252 /*
3253 * Generate a suitable error about a missing RTE.
3254 *
3255 * Since this is a very common type of error, we work rather hard to
3256 * produce a helpful message.
3257 */
3258 void
errorMissingRTE(ParseState * pstate,RangeVar * relation)3259 errorMissingRTE(ParseState *pstate, RangeVar *relation)
3260 {
3261 RangeTblEntry *rte;
3262 int sublevels_up;
3263 const char *badAlias = NULL;
3264
3265 /*
3266 * Check to see if there are any potential matches in the query's
3267 * rangetable. (Note: cases involving a bad schema name in the RangeVar
3268 * will throw error immediately here. That seems OK.)
3269 */
3270 rte = searchRangeTableForRel(pstate, relation);
3271
3272 /*
3273 * If we found a match that has an alias and the alias is visible in the
3274 * namespace, then the problem is probably use of the relation's real name
3275 * instead of its alias, ie "SELECT foo.* FROM foo f". This mistake is
3276 * common enough to justify a specific hint.
3277 *
3278 * If we found a match that doesn't meet those criteria, assume the
3279 * problem is illegal use of a relation outside its scope, as in the
3280 * MySQL-ism "SELECT ... FROM a, b LEFT JOIN c ON (a.x = c.y)".
3281 */
3282 if (rte && rte->alias &&
3283 strcmp(rte->eref->aliasname, relation->relname) != 0 &&
3284 refnameRangeTblEntry(pstate, NULL, rte->eref->aliasname,
3285 relation->location,
3286 &sublevels_up) == rte)
3287 badAlias = rte->eref->aliasname;
3288
3289 if (rte)
3290 ereport(ERROR,
3291 (errcode(ERRCODE_UNDEFINED_TABLE),
3292 errmsg("invalid reference to FROM-clause entry for table \"%s\"",
3293 relation->relname),
3294 (badAlias ?
3295 errhint("Perhaps you meant to reference the table alias \"%s\".",
3296 badAlias) :
3297 errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.",
3298 rte->eref->aliasname)),
3299 parser_errposition(pstate, relation->location)));
3300 else
3301 ereport(ERROR,
3302 (errcode(ERRCODE_UNDEFINED_TABLE),
3303 errmsg("missing FROM-clause entry for table \"%s\"",
3304 relation->relname),
3305 parser_errposition(pstate, relation->location)));
3306 }
3307
3308 /*
3309 * Generate a suitable error about a missing column.
3310 *
3311 * Since this is a very common type of error, we work rather hard to
3312 * produce a helpful message.
3313 */
3314 void
errorMissingColumn(ParseState * pstate,const char * relname,const char * colname,int location)3315 errorMissingColumn(ParseState *pstate,
3316 const char *relname, const char *colname, int location)
3317 {
3318 FuzzyAttrMatchState *state;
3319 char *closestfirst = NULL;
3320
3321 /*
3322 * Search the entire rtable looking for possible matches. If we find one,
3323 * emit a hint about it.
3324 *
3325 * TODO: improve this code (and also errorMissingRTE) to mention using
3326 * LATERAL if appropriate.
3327 */
3328 state = searchRangeTableForCol(pstate, relname, colname, location);
3329
3330 /*
3331 * Extract closest col string for best match, if any.
3332 *
3333 * Infer an exact match referenced despite not being visible from the fact
3334 * that an attribute number was not present in state passed back -- this
3335 * is what is reported when !closestfirst. There might also be an exact
3336 * match that was qualified with an incorrect alias, in which case
3337 * closestfirst will be set (so hint is the same as generic fuzzy case).
3338 */
3339 if (state->rfirst && AttributeNumberIsValid(state->first))
3340 closestfirst = strVal(list_nth(state->rfirst->eref->colnames,
3341 state->first - 1));
3342
3343 if (!state->rsecond)
3344 {
3345 /*
3346 * Handle case where there is zero or one column suggestions to hint,
3347 * including exact matches referenced but not visible.
3348 */
3349 ereport(ERROR,
3350 (errcode(ERRCODE_UNDEFINED_COLUMN),
3351 relname ?
3352 errmsg("column %s.%s does not exist", relname, colname) :
3353 errmsg("column \"%s\" does not exist", colname),
3354 state->rfirst ? closestfirst ?
3355 errhint("Perhaps you meant to reference the column \"%s.%s\".",
3356 state->rfirst->eref->aliasname, closestfirst) :
3357 errhint("There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query.",
3358 colname, state->rfirst->eref->aliasname) : 0,
3359 parser_errposition(pstate, location)));
3360 }
3361 else
3362 {
3363 /* Handle case where there are two equally useful column hints */
3364 char *closestsecond;
3365
3366 closestsecond = strVal(list_nth(state->rsecond->eref->colnames,
3367 state->second - 1));
3368
3369 ereport(ERROR,
3370 (errcode(ERRCODE_UNDEFINED_COLUMN),
3371 relname ?
3372 errmsg("column %s.%s does not exist", relname, colname) :
3373 errmsg("column \"%s\" does not exist", colname),
3374 errhint("Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\".",
3375 state->rfirst->eref->aliasname, closestfirst,
3376 state->rsecond->eref->aliasname, closestsecond),
3377 parser_errposition(pstate, location)));
3378 }
3379 }
3380
3381
3382 /*
3383 * Examine a fully-parsed query, and return true iff any relation underlying
3384 * the query is a temporary relation (table, view, or materialized view).
3385 */
3386 bool
isQueryUsingTempRelation(Query * query)3387 isQueryUsingTempRelation(Query *query)
3388 {
3389 return isQueryUsingTempRelation_walker((Node *) query, NULL);
3390 }
3391
3392 static bool
isQueryUsingTempRelation_walker(Node * node,void * context)3393 isQueryUsingTempRelation_walker(Node *node, void *context)
3394 {
3395 if (node == NULL)
3396 return false;
3397
3398 if (IsA(node, Query))
3399 {
3400 Query *query = (Query *) node;
3401 ListCell *rtable;
3402
3403 foreach(rtable, query->rtable)
3404 {
3405 RangeTblEntry *rte = lfirst(rtable);
3406
3407 if (rte->rtekind == RTE_RELATION)
3408 {
3409 Relation rel = table_open(rte->relid, AccessShareLock);
3410 char relpersistence = rel->rd_rel->relpersistence;
3411
3412 table_close(rel, AccessShareLock);
3413 if (relpersistence == RELPERSISTENCE_TEMP)
3414 return true;
3415 }
3416 }
3417
3418 return query_tree_walker(query,
3419 isQueryUsingTempRelation_walker,
3420 context,
3421 QTW_IGNORE_JOINALIASES);
3422 }
3423
3424 return expression_tree_walker(node,
3425 isQueryUsingTempRelation_walker,
3426 context);
3427 }
3428