PostgreSQL Source Code git master
Loading...
Searching...
No Matches
parse_relation.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * parse_relation.c
4 * parser support routines dealing with relations
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/parser/parse_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/table.h"
22#include "catalog/heap.h"
23#include "catalog/namespace.h"
24#include "funcapi.h"
25#include "nodes/makefuncs.h"
26#include "nodes/nodeFuncs.h"
27#include "parser/parse_enr.h"
29#include "parser/parse_type.h"
30#include "parser/parsetree.h"
31#include "storage/lmgr.h"
32#include "utils/builtins.h"
33#include "utils/lsyscache.h"
34#include "utils/syscache.h"
35#include "utils/varlena.h"
36
37
38/*
39 * Support for fuzzily matching columns.
40 *
41 * This is for building diagnostic messages, where multiple or non-exact
42 * matching attributes are of interest.
43 *
44 * "distance" is the current best fuzzy-match distance if rfirst isn't NULL,
45 * otherwise it is the maximum acceptable distance plus 1.
46 *
47 * rfirst/first record the closest non-exact match so far, and distance
48 * is its distance from the target name. If we have found a second non-exact
49 * match of exactly the same distance, rsecond/second record that. (If
50 * we find three of the same distance, we conclude that "distance" is not
51 * a tight enough bound for a useful hint and clear rfirst/rsecond again.
52 * Only if we later find something closer will we re-populate rfirst.)
53 *
54 * rexact1/exact1 record the location of the first exactly-matching column,
55 * if any. If we find multiple exact matches then rexact2/exact2 record
56 * another one (we don't especially care which). Currently, these get
57 * populated independently of the fuzzy-match fields.
58 */
59typedef struct
60{
61 int distance; /* Current or limit distance */
62 RangeTblEntry *rfirst; /* RTE of closest non-exact match, or NULL */
63 AttrNumber first; /* Col index in rfirst */
64 RangeTblEntry *rsecond; /* RTE of another non-exact match w/same dist */
65 AttrNumber second; /* Col index in rsecond */
66 RangeTblEntry *rexact1; /* RTE of first exact match, or NULL */
67 AttrNumber exact1; /* Col index in rexact1 */
68 RangeTblEntry *rexact2; /* RTE of second exact match, or NULL */
69 AttrNumber exact2; /* Col index in rexact2 */
71
72#define MAX_FUZZY_DISTANCE 3
73
74
76 const char *refname,
77 int location);
79 int location);
81 int location);
82static int scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
83 Alias *eref,
84 const char *colname, int location,
87static void markRTEForSelectPriv(ParseState *pstate,
88 int rtindex, AttrNumber col);
89static void expandRelation(Oid relid, Alias *eref,
90 int rtindex, int sublevels_up,
91 VarReturningType returning_type,
92 int location, bool include_dropped,
93 List **colnames, List **colvars);
94static void expandTupleDesc(TupleDesc tupdesc, Alias *eref,
95 int count, int offset,
96 int rtindex, int sublevels_up,
97 VarReturningType returning_type,
98 int location, bool include_dropped,
99 List **colnames, List **colvars);
100static int specialAttNum(const char *attname);
103
104
105/*
106 * refnameNamespaceItem
107 * Given a possibly-qualified refname, look to see if it matches any visible
108 * namespace item. If so, return a pointer to the nsitem; else return NULL.
109 *
110 * Optionally get nsitem's nesting depth (0 = current) into *sublevels_up.
111 * If sublevels_up is NULL, only consider items at the current nesting
112 * level.
113 *
114 * An unqualified refname (schemaname == NULL) can match any item with matching
115 * alias, or matching unqualified relname in the case of alias-less relation
116 * items. It is possible that such a refname matches multiple items in the
117 * nearest nesting level that has a match; if so, we report an error via
118 * ereport().
119 *
120 * A qualified refname (schemaname != NULL) can only match a relation item
121 * that (a) has no alias and (b) is for the same relation identified by
122 * schemaname.refname. In this case we convert schemaname.refname to a
123 * relation OID and search by relid, rather than by alias name. This is
124 * peculiar, but it's what SQL says to do. While processing a query's
125 * RETURNING list, there may be additional namespace items for OLD and NEW,
126 * with the same relation OID as the target namespace item. These are
127 * ignored in the search, since they don't match by schemaname.refname.
128 */
131 const char *schemaname,
132 const char *refname,
133 int location,
134 int *sublevels_up)
135{
136 Oid relId = InvalidOid;
137
138 if (sublevels_up)
139 *sublevels_up = 0;
140
141 if (schemaname != NULL)
142 {
144
145 /*
146 * We can use LookupNamespaceNoError() here because we are only
147 * interested in finding existing RTEs. Checking USAGE permission on
148 * the schema is unnecessary since it would have already been checked
149 * when the RTE was made. Furthermore, we want to report "RTE not
150 * found", not "no permissions for schema", if the name happens to
151 * match a schema name the user hasn't got access to.
152 */
155 return NULL;
156 relId = get_relname_relid(refname, namespaceId);
157 if (!OidIsValid(relId))
158 return NULL;
159 }
160
161 while (pstate != NULL)
162 {
164
165 if (OidIsValid(relId))
166 result = scanNameSpaceForRelid(pstate, relId, location);
167 else
168 result = scanNameSpaceForRefname(pstate, refname, location);
169
170 if (result)
171 return result;
172
173 if (sublevels_up)
174 (*sublevels_up)++;
175 else
176 break;
177
178 pstate = pstate->parentParseState;
179 }
180 return NULL;
181}
182
183/*
184 * Search the query's table namespace for an item matching the
185 * given unqualified refname. Return the nsitem if a unique match, or NULL
186 * if no match. Raise error if multiple matches.
187 *
188 * Note: it might seem that we shouldn't have to worry about the possibility
189 * of multiple matches; after all, the SQL standard disallows duplicate table
190 * aliases within a given SELECT level. Historically, however, Postgres has
191 * been laxer than that. For example, we allow
192 * SELECT ... FROM tab1 x CROSS JOIN (tab2 x CROSS JOIN tab3 y) z
193 * on the grounds that the aliased join (z) hides the aliases within it,
194 * therefore there is no conflict between the two RTEs named "x". However,
195 * if tab3 is a LATERAL subquery, then from within the subquery both "x"es
196 * are visible. Rather than rejecting queries that used to work, we allow
197 * this situation, and complain only if there's actually an ambiguous
198 * reference to "x".
199 */
200static ParseNamespaceItem *
201scanNameSpaceForRefname(ParseState *pstate, const char *refname, int location)
202{
204 ListCell *l;
205
206 foreach(l, pstate->p_namespace)
207 {
209
210 /* Ignore columns-only items */
211 if (!nsitem->p_rel_visible)
212 continue;
213 /* If not inside LATERAL, ignore lateral-only items */
214 if (nsitem->p_lateral_only && !pstate->p_lateral_active)
215 continue;
216
217 if (strcmp(nsitem->p_names->aliasname, refname) == 0)
218 {
219 if (result)
222 errmsg("table reference \"%s\" is ambiguous",
223 refname),
224 parser_errposition(pstate, location)));
225 check_lateral_ref_ok(pstate, nsitem, location);
226 result = nsitem;
227 }
228 }
229 return result;
230}
231
232/*
233 * Search the query's table namespace for a relation item matching the
234 * given relation OID. Return the nsitem if a unique match, or NULL
235 * if no match. Raise error if multiple matches.
236 *
237 * See the comments for refnameNamespaceItem to understand why this
238 * acts the way it does.
239 */
240static ParseNamespaceItem *
241scanNameSpaceForRelid(ParseState *pstate, Oid relid, int location)
242{
244 ListCell *l;
245
246 foreach(l, pstate->p_namespace)
247 {
249 RangeTblEntry *rte = nsitem->p_rte;
250
251 /* Ignore columns-only items */
252 if (!nsitem->p_rel_visible)
253 continue;
254 /* If not inside LATERAL, ignore lateral-only items */
255 if (nsitem->p_lateral_only && !pstate->p_lateral_active)
256 continue;
257 /* Ignore OLD/NEW namespace items that can appear in RETURNING */
258 if (nsitem->p_returning_type != VAR_RETURNING_DEFAULT)
259 continue;
260
261 /* yes, the test for alias == NULL should be there... */
262 if (rte->rtekind == RTE_RELATION &&
263 rte->relid == relid &&
264 rte->alias == NULL)
265 {
266 if (result)
269 errmsg("table reference %u is ambiguous",
270 relid),
271 parser_errposition(pstate, location)));
272 check_lateral_ref_ok(pstate, nsitem, location);
273 result = nsitem;
274 }
275 }
276 return result;
277}
278
279/*
280 * Search the query's CTE namespace for a CTE matching the given unqualified
281 * refname. Return the CTE (and its levelsup count) if a match, or NULL
282 * if no match. We need not worry about multiple matches, since parse_cte.c
283 * rejects WITH lists containing duplicate CTE names.
284 */
286scanNameSpaceForCTE(ParseState *pstate, const char *refname,
287 Index *ctelevelsup)
288{
289 Index levelsup;
290
291 for (levelsup = 0;
292 pstate != NULL;
293 pstate = pstate->parentParseState, levelsup++)
294 {
295 ListCell *lc;
296
297 foreach(lc, pstate->p_ctenamespace)
298 {
300
301 if (strcmp(cte->ctename, refname) == 0)
302 {
303 *ctelevelsup = levelsup;
304 return cte;
305 }
306 }
307 }
308 return NULL;
309}
310
311/*
312 * Search for a possible "future CTE", that is one that is not yet in scope
313 * according to the WITH scoping rules. This has nothing to do with valid
314 * SQL semantics, but it's important for error reporting purposes.
315 */
316static bool
317isFutureCTE(ParseState *pstate, const char *refname)
318{
319 for (; pstate != NULL; pstate = pstate->parentParseState)
320 {
321 ListCell *lc;
322
323 foreach(lc, pstate->p_future_ctes)
324 {
326
327 if (strcmp(cte->ctename, refname) == 0)
328 return true;
329 }
330 }
331 return false;
332}
333
334/*
335 * Search the query's ephemeral named relation namespace for a relation
336 * matching the given unqualified refname.
337 */
338bool
339scanNameSpaceForENR(ParseState *pstate, const char *refname)
340{
341 return name_matches_visible_ENR(pstate, refname);
342}
343
344/*
345 * searchRangeTableForRel
346 * See if any RangeTblEntry could possibly match the RangeVar.
347 * If so, return a pointer to the RangeTblEntry; else return NULL.
348 *
349 * This is different from refnameNamespaceItem in that it considers every
350 * entry in the ParseState's rangetable(s), not only those that are currently
351 * visible in the p_namespace list(s). This behavior is invalid per the SQL
352 * spec, and it may give ambiguous results (there might be multiple equally
353 * valid matches, but only one will be returned). This must be used ONLY
354 * as a heuristic in giving suitable error messages. See errorMissingRTE.
355 *
356 * Notice that we consider both matches on actual relation (or CTE) name
357 * and matches on alias.
358 */
359static RangeTblEntry *
361{
362 const char *refname = relation->relname;
363 Oid relId = InvalidOid;
364 CommonTableExpr *cte = NULL;
365 bool isenr = false;
366 Index ctelevelsup = 0;
367 Index levelsup;
368
369 /*
370 * If it's an unqualified name, check for possible CTE matches. A CTE
371 * hides any real relation matches. If no CTE, look for a matching
372 * relation.
373 *
374 * NB: It's not critical that RangeVarGetRelid return the correct answer
375 * here in the face of concurrent DDL. If it doesn't, the worst case
376 * scenario is a less-clear error message. Also, the tables involved in
377 * the query are already locked, which reduces the number of cases in
378 * which surprising behavior can occur. So we do the name lookup
379 * unlocked.
380 */
381 if (!relation->schemaname)
382 {
383 cte = scanNameSpaceForCTE(pstate, refname, &ctelevelsup);
384 if (!cte)
385 isenr = scanNameSpaceForENR(pstate, refname);
386 }
387
388 if (!cte && !isenr)
389 relId = RangeVarGetRelid(relation, NoLock, true);
390
391 /* Now look for RTEs matching either the relation/CTE/ENR or the alias */
392 for (levelsup = 0;
393 pstate != NULL;
394 pstate = pstate->parentParseState, levelsup++)
395 {
396 ListCell *l;
397
398 foreach(l, pstate->p_rtable)
399 {
401
402 if (rte->rtekind == RTE_RELATION &&
403 OidIsValid(relId) &&
404 rte->relid == relId)
405 return rte;
406 if (rte->rtekind == RTE_CTE &&
407 cte != NULL &&
408 rte->ctelevelsup + levelsup == ctelevelsup &&
409 strcmp(rte->ctename, refname) == 0)
410 return rte;
411 if (rte->rtekind == RTE_NAMEDTUPLESTORE &&
412 isenr &&
413 strcmp(rte->enrname, refname) == 0)
414 return rte;
415 if (strcmp(rte->eref->aliasname, refname) == 0)
416 return rte;
417 }
418 }
419 return NULL;
420}
421
422/*
423 * Check for relation-name conflicts between two namespace lists.
424 * Raise an error if any is found.
425 *
426 * Note: we assume that each given argument does not contain conflicts
427 * itself; we just want to know if the two can be merged together.
428 *
429 * Per SQL, two alias-less plain relation RTEs do not conflict even if
430 * they have the same eref->aliasname (ie, same relation name), if they
431 * are for different relation OIDs (implying they are in different schemas).
432 *
433 * We ignore the lateral-only flags in the namespace items: the lists must
434 * not conflict, even when all items are considered visible. However,
435 * columns-only items should be ignored.
436 */
437void
440{
441 ListCell *l1;
442
443 foreach(l1, namespace1)
444 {
446 RangeTblEntry *rte1 = nsitem1->p_rte;
447 const char *aliasname1 = nsitem1->p_names->aliasname;
448 ListCell *l2;
449
450 if (!nsitem1->p_rel_visible)
451 continue;
452
453 foreach(l2, namespace2)
454 {
456 RangeTblEntry *rte2 = nsitem2->p_rte;
457 const char *aliasname2 = nsitem2->p_names->aliasname;
458
459 if (!nsitem2->p_rel_visible)
460 continue;
461 if (strcmp(aliasname2, aliasname1) != 0)
462 continue; /* definitely no conflict */
463 if (rte1->rtekind == RTE_RELATION && rte1->alias == NULL &&
464 rte2->rtekind == RTE_RELATION && rte2->alias == NULL &&
465 rte1->relid != rte2->relid)
466 continue; /* no conflict per SQL rule */
469 errmsg("table name \"%s\" specified more than once",
470 aliasname1)));
471 }
472 }
473}
474
475/*
476 * Complain if a namespace item is currently disallowed as a LATERAL reference.
477 * This enforces both SQL:2008's rather odd idea of what to do with a LATERAL
478 * reference to the wrong side of an outer join, and our own prohibition on
479 * referencing the target table of an UPDATE or DELETE as a lateral reference
480 * in a FROM/USING clause.
481 *
482 * Note: the pstate should be the same query level the nsitem was found in.
483 *
484 * Convenience subroutine to avoid multiple copies of a rather ugly ereport.
485 */
486static void
488 int location)
489{
490 if (nsitem->p_lateral_only && !nsitem->p_lateral_ok)
491 {
492 /* SQL:2008 demands this be an error, not an invisible item */
493 RangeTblEntry *rte = nsitem->p_rte;
494 char *refname = nsitem->p_names->aliasname;
495
498 errmsg("invalid reference to FROM-clause entry for table \"%s\"",
499 refname),
500 (pstate->p_target_nsitem != NULL &&
501 rte == pstate->p_target_nsitem->p_rte) ?
502 errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.",
503 refname) :
504 errdetail("The combining JOIN type must be INNER or LEFT for a LATERAL reference."),
505 parser_errposition(pstate, location)));
506 }
507}
508
509/*
510 * Given an RT index and nesting depth, find the corresponding
511 * ParseNamespaceItem (there must be one).
512 *
513 * NB: Callers starting from a Var should consider using GetNSItemByVar()
514 * instead, to find the namespace item with matching varreturningtype.
515 */
518 int varno,
519 int sublevels_up)
520{
521 ListCell *lc;
522
523 while (sublevels_up-- > 0)
524 {
525 pstate = pstate->parentParseState;
526 Assert(pstate != NULL);
527 }
528 foreach(lc, pstate->p_namespace)
529 {
531
532 if (nsitem->p_rtindex == varno)
533 return nsitem;
534 }
535 elog(ERROR, "nsitem not found (internal error)");
536 return NULL; /* keep compiler quiet */
537}
538
539/*
540 * Given a Var, find the corresponding ParseNamespaceItem (there must be one).
541 *
542 * Like GetNSItemByRangeTablePosn(), but uses the Var's varreturningtype in
543 * addition to its varno and varlevelsup to find the namespace item.
544 */
547{
548 int sublevels_up = var->varlevelsup;
549 ListCell *lc;
550
551 while (sublevels_up-- > 0)
552 {
553 pstate = pstate->parentParseState;
554 Assert(pstate != NULL);
555 }
556 foreach(lc, pstate->p_namespace)
557 {
559
560 if (nsitem->p_rtindex == var->varno &&
561 nsitem->p_returning_type == var->varreturningtype)
562 return nsitem;
563 }
564 elog(ERROR, "nsitem not found (internal error)");
565 return NULL; /* keep compiler quiet */
566}
567
568/*
569 * Given an RT index and nesting depth, find the corresponding RTE.
570 * (Note that the RTE need not be in the query's namespace.)
571 */
574 int varno,
575 int sublevels_up)
576{
577 while (sublevels_up-- > 0)
578 {
579 pstate = pstate->parentParseState;
580 Assert(pstate != NULL);
581 }
582 Assert(varno > 0 && varno <= list_length(pstate->p_rtable));
583 return rt_fetch(varno, pstate->p_rtable);
584}
585
586/*
587 * Fetch the CTE for a CTE-reference RTE.
588 *
589 * rtelevelsup is the number of query levels above the given pstate that the
590 * RTE came from.
591 */
594{
595 Index levelsup;
596 ListCell *lc;
597
598 Assert(rte->rtekind == RTE_CTE);
599 levelsup = rte->ctelevelsup + rtelevelsup;
600 while (levelsup-- > 0)
601 {
602 pstate = pstate->parentParseState;
603 if (!pstate) /* shouldn't happen */
604 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
605 }
606 foreach(lc, pstate->p_ctenamespace)
607 {
609
610 if (strcmp(cte->ctename, rte->ctename) == 0)
611 return cte;
612 }
613 /* shouldn't happen */
614 elog(ERROR, "could not find CTE \"%s\"", rte->ctename);
615 return NULL; /* keep compiler quiet */
616}
617
618/*
619 * updateFuzzyAttrMatchState
620 * Using Levenshtein distance, consider if column is best fuzzy match.
621 */
622static void
625 const char *actual, const char *match, int attnum)
626{
627 int columndistance;
628 int matchlen;
629
630 /* Bail before computing the Levenshtein distance if there's no hope. */
631 if (fuzzy_rte_penalty > fuzzystate->distance)
632 return;
633
634 /*
635 * Outright reject dropped columns, which can appear here with apparent
636 * empty actual names, per remarks within scanRTEForColumn().
637 */
638 if (actual[0] == '\0')
639 return;
640
641 /* Use Levenshtein to compute match distance. */
642 matchlen = strlen(match);
645 1, 1, 1,
646 fuzzystate->distance + 1
648 true);
649
650 /*
651 * If more than half the characters are different, don't treat it as a
652 * match, to avoid making ridiculous suggestions.
653 */
654 if (columndistance > matchlen / 2)
655 return;
656
657 /*
658 * From this point on, we can ignore the distinction between the RTE-name
659 * distance and the column-name distance.
660 */
662
663 /*
664 * If the new distance is less than or equal to that of the best match
665 * found so far, update fuzzystate.
666 */
668 {
669 /* Store new lowest observed distance as first/only match */
670 fuzzystate->distance = columndistance;
671 fuzzystate->rfirst = rte;
672 fuzzystate->first = attnum;
673 fuzzystate->rsecond = NULL;
674 }
675 else if (columndistance == fuzzystate->distance)
676 {
677 /* If we already have a match of this distance, update state */
678 if (fuzzystate->rsecond != NULL)
679 {
680 /*
681 * Too many matches at same distance. Clearly, this value of
682 * distance is too low a bar, so drop these entries while keeping
683 * the current distance value, so that only smaller distances will
684 * be considered interesting. Only if we find something of lower
685 * distance will we re-populate rfirst (via the stanza above).
686 */
687 fuzzystate->rfirst = NULL;
688 fuzzystate->rsecond = NULL;
689 }
690 else if (fuzzystate->rfirst != NULL)
691 {
692 /* Record as provisional second match */
693 fuzzystate->rsecond = rte;
694 fuzzystate->second = attnum;
695 }
696 else
697 {
698 /*
699 * Do nothing. When rfirst is NULL, distance is more than what we
700 * want to consider acceptable, so we should ignore this match.
701 */
702 }
703 }
704}
705
706/*
707 * scanNSItemForColumn
708 * Search the column names of a single namespace item for the given name.
709 * If found, return an appropriate Var node, else return NULL.
710 * If the name proves ambiguous within this nsitem, raise error.
711 *
712 * Side effect: if we find a match, mark the corresponding RTE as requiring
713 * read access for the column.
714 */
715Node *
717 int sublevels_up, const char *colname, int location)
718{
719 RangeTblEntry *rte = nsitem->p_rte;
720 int attnum;
721 Var *var;
722
723 /*
724 * Scan the nsitem's column names (or aliases) for a match. Complain if
725 * multiple matches.
726 */
727 attnum = scanRTEForColumn(pstate, rte, nsitem->p_names,
728 colname, location,
729 0, NULL);
730
732 return NULL; /* Return NULL if no match */
733
734 /* In constraint check, no system column is allowed except tableOid */
739 errmsg("system column \"%s\" reference in check constraint is invalid",
740 colname),
741 parser_errposition(pstate, location)));
742
743 /*
744 * In generated column, no system column is allowed except tableOid.
745 * (Required for stored generated, but we also do it for virtual generated
746 * for now for consistency.)
747 */
752 errmsg("cannot use system column \"%s\" in column generation expression",
753 colname),
754 parser_errposition(pstate, location)));
755
756 /*
757 * In a MERGE WHEN condition, no system column is allowed except tableOid
758 */
759 if (pstate->p_expr_kind == EXPR_KIND_MERGE_WHEN &&
763 errmsg("cannot use system column \"%s\" in MERGE WHEN condition",
764 colname),
765 parser_errposition(pstate, location)));
766
767 /* Found a valid match, so build a Var */
769 {
770 /* Get attribute data from the ParseNamespaceColumn array */
771 ParseNamespaceColumn *nscol = &nsitem->p_nscolumns[attnum - 1];
772
773 /* Complain if dropped column. See notes in scanRTEForColumn. */
774 if (nscol->p_varno == 0)
777 errmsg("column \"%s\" of relation \"%s\" does not exist",
778 colname,
779 nsitem->p_names->aliasname)));
780
781 var = makeVar(nscol->p_varno,
782 nscol->p_varattno,
783 nscol->p_vartype,
784 nscol->p_vartypmod,
785 nscol->p_varcollid,
786 sublevels_up);
787 /* makeVar doesn't offer parameters for these, so set them by hand: */
788 var->varnosyn = nscol->p_varnosyn;
789 var->varattnosyn = nscol->p_varattnosyn;
790 }
791 else
792 {
793 /* System column, so use predetermined type data */
795
797 var = makeVar(nsitem->p_rtindex,
798 attnum,
799 sysatt->atttypid,
800 sysatt->atttypmod,
801 sysatt->attcollation,
802 sublevels_up);
803 }
804 var->location = location;
805
806 /* Mark Var for RETURNING OLD/NEW, as necessary */
807 var->varreturningtype = nsitem->p_returning_type;
808
809 /* Mark Var if it's nulled by any outer joins */
810 markNullableIfNeeded(pstate, var);
811
812 /* Require read access to the column */
813 markVarForSelectPriv(pstate, var);
814
815 return (Node *) var;
816}
817
818/*
819 * scanRTEForColumn
820 * Search the column names of a single RTE for the given name.
821 * If found, return the attnum (possibly negative, for a system column);
822 * else return InvalidAttrNumber.
823 * If the name proves ambiguous within this RTE, raise error.
824 *
825 * Actually, we only search the names listed in "eref". This can be either
826 * rte->eref, in which case we are indeed searching all the column names,
827 * or for a join it can be rte->join_using_alias, in which case we are only
828 * considering the common column names (which are the first N columns of the
829 * join, so everything works).
830 *
831 * pstate and location are passed only for error-reporting purposes.
832 *
833 * Side effect: if fuzzystate is non-NULL, check non-system columns
834 * for an approximate match and update fuzzystate accordingly.
835 *
836 * Note: this is factored out of scanNSItemForColumn because error message
837 * creation may want to check RTEs that are not in the namespace. To support
838 * that usage, minimize the number of validity checks performed here. It's
839 * okay to complain about ambiguous-name cases, though, since if we are
840 * working to complain about an invalid name, we've already eliminated that.
841 */
842static int
844 Alias *eref,
845 const char *colname, int location,
848{
850 int attnum = 0;
851 ListCell *c;
852
853 /*
854 * Scan the user column names (or aliases) for a match. Complain if
855 * multiple matches.
856 *
857 * Note: eref->colnames may include entries for dropped columns, but those
858 * will be empty strings that cannot match any legal SQL identifier, so we
859 * don't bother to test for that case here.
860 *
861 * Should this somehow go wrong and we try to access a dropped column,
862 * we'll still catch it by virtue of the check in scanNSItemForColumn().
863 * Callers interested in finding match with shortest distance need to
864 * defend against this directly, though.
865 */
866 foreach(c, eref->colnames)
867 {
868 const char *attcolname = strVal(lfirst(c));
869
870 attnum++;
871 if (strcmp(attcolname, colname) == 0)
872 {
873 if (result)
876 errmsg("column reference \"%s\" is ambiguous",
877 colname),
878 parser_errposition(pstate, location)));
879 result = attnum;
880 }
881
882 /* Update fuzzy match state, if provided. */
883 if (fuzzystate != NULL)
885 rte, attcolname, colname, attnum);
886 }
887
888 /*
889 * If we have a unique match, return it. Note that this allows a user
890 * alias to override a system column name (such as OID) without error.
891 */
892 if (result)
893 return result;
894
895 /*
896 * If the RTE represents a real relation, consider system column names.
897 * Composites are only used for pseudo-relations like ON CONFLICT's
898 * excluded.
899 */
900 if (rte->rtekind == RTE_RELATION &&
901 rte->relkind != RELKIND_COMPOSITE_TYPE)
902 {
903 /* quick check to see if name could be a system column */
904 attnum = specialAttNum(colname);
906 {
907 /* now check to see if column actually is defined */
909 ObjectIdGetDatum(rte->relid),
911 result = attnum;
912 }
913 }
914
915 return result;
916}
917
918/*
919 * colNameToVar
920 * Search for an unqualified column name.
921 * If found, return the appropriate Var node (or expression).
922 * If not found, return NULL. If the name proves ambiguous, raise error.
923 * If localonly is true, only names in the innermost query are considered.
924 */
925Node *
926colNameToVar(ParseState *pstate, const char *colname, bool localonly,
927 int location)
928{
929 Node *result = NULL;
930 int sublevels_up = 0;
931 ParseState *orig_pstate = pstate;
932
933 while (pstate != NULL)
934 {
935 ListCell *l;
936
937 foreach(l, pstate->p_namespace)
938 {
941
942 /* Ignore table-only items */
943 if (!nsitem->p_cols_visible)
944 continue;
945 /* If not inside LATERAL, ignore lateral-only items */
946 if (nsitem->p_lateral_only && !pstate->p_lateral_active)
947 continue;
948
949 /* use orig_pstate here for consistency with other callers */
951 colname, location);
952
953 if (newresult)
954 {
955 if (result)
958 errmsg("column reference \"%s\" is ambiguous",
959 colname),
960 parser_errposition(pstate, location)));
961 check_lateral_ref_ok(pstate, nsitem, location);
963 }
964 }
965
966 if (result != NULL || localonly)
967 break; /* found, or don't want to look at parent */
968
969 pstate = pstate->parentParseState;
970 sublevels_up++;
971 }
972
973 return result;
974}
975
976/*
977 * searchRangeTableForCol
978 * See if any RangeTblEntry could possibly provide the given column name (or
979 * find the best match available). Returns state with relevant details.
980 *
981 * This is different from colNameToVar in that it considers every entry in
982 * the ParseState's rangetable(s), not only those that are currently visible
983 * in the p_namespace list(s). This behavior is invalid per the SQL spec,
984 * and it may give ambiguous results (since there might be multiple equally
985 * valid matches). This must be used ONLY as a heuristic in giving suitable
986 * error messages. See errorMissingColumn.
987 *
988 * This function is also different in that it will consider approximate
989 * matches -- if the user entered an alias/column pair that is only slightly
990 * different from a valid pair, we may be able to infer what they meant to
991 * type and provide a reasonable hint. We return a FuzzyAttrMatchState
992 * struct providing information about both exact and approximate matches.
993 */
994static FuzzyAttrMatchState *
995searchRangeTableForCol(ParseState *pstate, const char *alias, const char *colname,
996 int location)
997{
998 ParseState *orig_pstate = pstate;
1000
1001 fuzzystate->distance = MAX_FUZZY_DISTANCE + 1;
1002 fuzzystate->rfirst = NULL;
1003 fuzzystate->rsecond = NULL;
1004 fuzzystate->rexact1 = NULL;
1005 fuzzystate->rexact2 = NULL;
1006
1007 while (pstate != NULL)
1008 {
1009 ListCell *l;
1010
1011 foreach(l, pstate->p_rtable)
1012 {
1014 int fuzzy_rte_penalty = 0;
1015 int attnum;
1016
1017 /*
1018 * Typically, it is not useful to look for matches within join
1019 * RTEs; they effectively duplicate other RTEs for our purposes,
1020 * and if a match is chosen from a join RTE, an unhelpful alias is
1021 * displayed in the final diagnostic message.
1022 */
1023 if (rte->rtekind == RTE_JOIN)
1024 continue;
1025
1026 /*
1027 * If the user didn't specify an alias, then matches against one
1028 * RTE are as good as another. But if the user did specify an
1029 * alias, then we want at least a fuzzy - and preferably an exact
1030 * - match for the range table entry.
1031 */
1032 if (alias != NULL)
1035 rte->eref->aliasname,
1036 strlen(rte->eref->aliasname),
1037 1, 1, 1,
1039 true);
1040
1041 /*
1042 * Scan for a matching column, and update fuzzystate. Non-exact
1043 * matches are dealt with inside scanRTEForColumn, but exact
1044 * matches are handled here. (There won't be more than one exact
1045 * match in the same RTE, else we'd have thrown error earlier.)
1046 */
1048 colname, location,
1051 {
1052 if (fuzzystate->rexact1 == NULL)
1053 {
1054 fuzzystate->rexact1 = rte;
1055 fuzzystate->exact1 = attnum;
1056 }
1057 else
1058 {
1059 /* Needn't worry about overwriting previous rexact2 */
1060 fuzzystate->rexact2 = rte;
1061 fuzzystate->exact2 = attnum;
1062 }
1063 }
1064 }
1065
1066 pstate = pstate->parentParseState;
1067 }
1068
1069 return fuzzystate;
1070}
1071
1072/*
1073 * markNullableIfNeeded
1074 * If the RTE referenced by the Var is nullable by outer join(s)
1075 * at this point in the query, set var->varnullingrels to show that.
1076 */
1077void
1079{
1080 int rtindex = var->varno;
1081 Bitmapset *relids;
1082
1083 /* Find the appropriate pstate */
1084 for (int lv = 0; lv < var->varlevelsup; lv++)
1085 pstate = pstate->parentParseState;
1086
1087 /* Find currently-relevant join relids for the Var's rel */
1088 if (rtindex > 0 && rtindex <= list_length(pstate->p_nullingrels))
1089 relids = (Bitmapset *) list_nth(pstate->p_nullingrels, rtindex - 1);
1090 else
1091 relids = NULL;
1092
1093 /*
1094 * Merge with any already-declared nulling rels. (Typically there won't
1095 * be any, but let's get it right if there are.)
1096 */
1097 if (relids != NULL)
1098 var->varnullingrels = bms_union(var->varnullingrels, relids);
1099}
1100
1101/*
1102 * markRTEForSelectPriv
1103 * Mark the specified column of the RTE with index rtindex
1104 * as requiring SELECT privilege
1105 *
1106 * col == InvalidAttrNumber means a "whole row" reference
1107 */
1108static void
1110{
1111 RangeTblEntry *rte = rt_fetch(rtindex, pstate->p_rtable);
1112
1113 if (rte->rtekind == RTE_RELATION)
1114 {
1116
1117 /* Make sure the rel as a whole is marked for SELECT access */
1119 perminfo->requiredPerms |= ACL_SELECT;
1120 /* Must offset the attnum to fit in a bitmapset */
1121 perminfo->selectedCols =
1122 bms_add_member(perminfo->selectedCols,
1124 }
1125 else if (rte->rtekind == RTE_JOIN)
1126 {
1127 if (col == InvalidAttrNumber)
1128 {
1129 /*
1130 * A whole-row reference to a join has to be treated as whole-row
1131 * references to the two inputs.
1132 */
1133 JoinExpr *j;
1134
1135 if (rtindex > 0 && rtindex <= list_length(pstate->p_joinexprs))
1136 j = list_nth_node(JoinExpr, pstate->p_joinexprs, rtindex - 1);
1137 else
1138 j = NULL;
1139 if (j == NULL)
1140 elog(ERROR, "could not find JoinExpr for whole-row reference");
1141
1142 /* Note: we can't see FromExpr here */
1143 if (IsA(j->larg, RangeTblRef))
1144 {
1145 int varno = ((RangeTblRef *) j->larg)->rtindex;
1146
1148 }
1149 else if (IsA(j->larg, JoinExpr))
1150 {
1151 int varno = ((JoinExpr *) j->larg)->rtindex;
1152
1154 }
1155 else
1156 elog(ERROR, "unrecognized node type: %d",
1157 (int) nodeTag(j->larg));
1158 if (IsA(j->rarg, RangeTblRef))
1159 {
1160 int varno = ((RangeTblRef *) j->rarg)->rtindex;
1161
1163 }
1164 else if (IsA(j->rarg, JoinExpr))
1165 {
1166 int varno = ((JoinExpr *) j->rarg)->rtindex;
1167
1169 }
1170 else
1171 elog(ERROR, "unrecognized node type: %d",
1172 (int) nodeTag(j->rarg));
1173 }
1174 else
1175 {
1176 /*
1177 * Join alias Vars for ordinary columns must refer to merged JOIN
1178 * USING columns. We don't need to do anything here, because the
1179 * join input columns will also be referenced in the join's qual
1180 * clause, and will get marked for select privilege there.
1181 */
1182 }
1183 }
1184 /* other RTE types don't require privilege marking */
1185}
1186
1187/*
1188 * markVarForSelectPriv
1189 * Mark the RTE referenced by the Var as requiring SELECT privilege
1190 * for the Var's column (the Var could be a whole-row Var, too)
1191 */
1192void
1194{
1195 Index lv;
1196
1197 Assert(IsA(var, Var));
1198 /* Find the appropriate pstate if it's an uplevel Var */
1199 for (lv = 0; lv < var->varlevelsup; lv++)
1200 pstate = pstate->parentParseState;
1201 markRTEForSelectPriv(pstate, var->varno, var->varattno);
1202}
1203
1204/*
1205 * buildRelationAliases
1206 * Construct the eref column name list for a relation RTE.
1207 * This code is also used for function RTEs.
1208 *
1209 * tupdesc: the physical column information
1210 * alias: the user-supplied alias, or NULL if none
1211 * eref: the eref Alias to store column names in
1212 *
1213 * eref->colnames is filled in. Also, alias->colnames is rebuilt to insert
1214 * empty strings for any dropped columns, so that it will be one-to-one with
1215 * physical column numbers.
1216 *
1217 * It is an error for there to be more aliases present than required.
1218 */
1219static void
1221{
1222 int maxattrs = tupdesc->natts;
1223 List *aliaslist;
1225 int numaliases;
1226 int varattno;
1227 int numdropped = 0;
1228
1229 Assert(eref->colnames == NIL);
1230
1231 if (alias)
1232 {
1233 aliaslist = alias->colnames;
1236 /* We'll rebuild the alias colname list */
1237 alias->colnames = NIL;
1238 }
1239 else
1240 {
1241 aliaslist = NIL;
1242 aliaslc = NULL;
1243 numaliases = 0;
1244 }
1245
1246 for (varattno = 0; varattno < maxattrs; varattno++)
1247 {
1248 Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
1250
1251 if (attr->attisdropped)
1252 {
1253 /* Always insert an empty string for a dropped column */
1255 if (aliaslc)
1256 alias->colnames = lappend(alias->colnames, attrname);
1257 numdropped++;
1258 }
1259 else if (aliaslc)
1260 {
1261 /* Use the next user-supplied alias */
1264 alias->colnames = lappend(alias->colnames, attrname);
1265 }
1266 else
1267 {
1268 attrname = makeString(pstrdup(NameStr(attr->attname)));
1269 /* we're done with the alias if any */
1270 }
1271
1272 eref->colnames = lappend(eref->colnames, attrname);
1273 }
1274
1275 /* Too many user-supplied aliases? */
1276 if (aliaslc)
1277 ereport(ERROR,
1279 errmsg("table \"%s\" has %d columns available but %d columns specified",
1280 eref->aliasname, maxattrs - numdropped, numaliases)));
1281}
1282
1283/*
1284 * chooseScalarFunctionAlias
1285 * Select the column alias for a function in a function RTE,
1286 * when the function returns a scalar type (not composite or RECORD).
1287 *
1288 * funcexpr: transformed expression tree for the function call
1289 * funcname: function name (as determined by FigureColname)
1290 * alias: the user-supplied alias for the RTE, or NULL if none
1291 * nfuncs: the number of functions appearing in the function RTE
1292 *
1293 * Note that the name we choose might be overridden later, if the user-given
1294 * alias includes column alias names. That's of no concern here.
1295 */
1296static char *
1298 Alias *alias, int nfuncs)
1299{
1300 char *pname;
1301
1302 /*
1303 * If the expression is a simple function call, and the function has a
1304 * single OUT parameter that is named, use the parameter's name.
1305 */
1306 if (funcexpr && IsA(funcexpr, FuncExpr))
1307 {
1308 pname = get_func_result_name(((FuncExpr *) funcexpr)->funcid);
1309 if (pname)
1310 return pname;
1311 }
1312
1313 /*
1314 * If there's just one function in the RTE, and the user gave an RTE alias
1315 * name, use that name. (This makes FROM func() AS foo use "foo" as the
1316 * column name as well as the table alias.)
1317 */
1318 if (nfuncs == 1 && alias)
1319 return alias->aliasname;
1320
1321 /*
1322 * Otherwise use the function name.
1323 */
1324 return funcname;
1325}
1326
1327/*
1328 * buildNSItemFromTupleDesc
1329 * Build a ParseNamespaceItem, given a tupdesc describing the columns.
1330 *
1331 * rte: the new RangeTblEntry for the rel
1332 * rtindex: its index in the rangetable list
1333 * perminfo: permission list entry for the rel
1334 * tupdesc: the physical column information
1335 */
1336static ParseNamespaceItem *
1339 TupleDesc tupdesc)
1340{
1343 int maxattrs = tupdesc->natts;
1344 int varattno;
1345
1346 /* colnames must have the same number of entries as the nsitem */
1347 Assert(maxattrs == list_length(rte->eref->colnames));
1348
1349 /* extract per-column data from the tupdesc */
1352
1353 for (varattno = 0; varattno < maxattrs; varattno++)
1354 {
1355 Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
1356
1357 /* For a dropped column, just leave the entry as zeroes */
1358 if (attr->attisdropped)
1359 continue;
1360
1361 nscolumns[varattno].p_varno = rtindex;
1362 nscolumns[varattno].p_varattno = varattno + 1;
1363 nscolumns[varattno].p_vartype = attr->atttypid;
1364 nscolumns[varattno].p_vartypmod = attr->atttypmod;
1365 nscolumns[varattno].p_varcollid = attr->attcollation;
1366 nscolumns[varattno].p_varnosyn = rtindex;
1367 nscolumns[varattno].p_varattnosyn = varattno + 1;
1368 }
1369
1370 /* ... and build the nsitem */
1372 nsitem->p_names = rte->eref;
1373 nsitem->p_rte = rte;
1374 nsitem->p_rtindex = rtindex;
1375 nsitem->p_perminfo = perminfo;
1376 nsitem->p_nscolumns = nscolumns;
1377 /* set default visibility flags; might get changed later */
1378 nsitem->p_rel_visible = true;
1379 nsitem->p_cols_visible = true;
1380 nsitem->p_lateral_only = false;
1381 nsitem->p_lateral_ok = true;
1382 nsitem->p_returning_type = VAR_RETURNING_DEFAULT;
1383
1384 return nsitem;
1385}
1386
1387/*
1388 * buildNSItemFromLists
1389 * Build a ParseNamespaceItem, given column type information in lists.
1390 *
1391 * rte: the new RangeTblEntry for the rel
1392 * rtindex: its index in the rangetable list
1393 * coltypes: per-column datatype OIDs
1394 * coltypmods: per-column type modifiers
1395 * colcollation: per-column collation OIDs
1396 */
1397static ParseNamespaceItem *
1400{
1404 int varattno;
1405 ListCell *lct;
1406 ListCell *lcm;
1407 ListCell *lcc;
1408
1409 /* colnames must have the same number of entries as the nsitem */
1410 Assert(maxattrs == list_length(rte->eref->colnames));
1411
1414
1415 /* extract per-column data from the lists */
1418
1419 varattno = 0;
1421 lcm, coltypmods,
1423 {
1424 nscolumns[varattno].p_varno = rtindex;
1425 nscolumns[varattno].p_varattno = varattno + 1;
1426 nscolumns[varattno].p_vartype = lfirst_oid(lct);
1427 nscolumns[varattno].p_vartypmod = lfirst_int(lcm);
1428 nscolumns[varattno].p_varcollid = lfirst_oid(lcc);
1429 nscolumns[varattno].p_varnosyn = rtindex;
1430 nscolumns[varattno].p_varattnosyn = varattno + 1;
1431 varattno++;
1432 }
1433
1434 /* ... and build the nsitem */
1436 nsitem->p_names = rte->eref;
1437 nsitem->p_rte = rte;
1438 nsitem->p_rtindex = rtindex;
1439 nsitem->p_perminfo = NULL;
1440 nsitem->p_nscolumns = nscolumns;
1441 /* set default visibility flags; might get changed later */
1442 nsitem->p_rel_visible = true;
1443 nsitem->p_cols_visible = true;
1444 nsitem->p_lateral_only = false;
1445 nsitem->p_lateral_ok = true;
1446 nsitem->p_returning_type = VAR_RETURNING_DEFAULT;
1447
1448 return nsitem;
1449}
1450
1451/*
1452 * Open a table during parse analysis
1453 *
1454 * This is essentially just the same as table_openrv(), except that it caters
1455 * to some parser-specific error reporting needs, notably that it arranges
1456 * to include the RangeVar's parse location in any resulting error.
1457 */
1459parserOpenTable(ParseState *pstate, const RangeVar *relation, LOCKMODE lockmode)
1460{
1461 Relation rel;
1463
1465 rel = table_openrv_extended(relation, lockmode, true);
1466 if (rel == NULL)
1467 {
1468 if (relation->schemaname)
1469 ereport(ERROR,
1471 errmsg("relation \"%s.%s\" does not exist",
1472 relation->schemaname, relation->relname)));
1473 else
1474 {
1475 /*
1476 * An unqualified name might have been meant as a reference to
1477 * some not-yet-in-scope CTE. The bare "does not exist" message
1478 * has proven remarkably unhelpful for figuring out such problems,
1479 * so we take pains to offer a specific hint.
1480 */
1481 if (isFutureCTE(pstate, relation->relname))
1482 ereport(ERROR,
1484 errmsg("relation \"%s\" does not exist",
1485 relation->relname),
1486 errdetail("There is a WITH item named \"%s\", but it cannot be referenced from this part of the query.",
1487 relation->relname),
1488 errhint("Use WITH RECURSIVE, or re-order the WITH items to remove forward references.")));
1489 else
1490 ereport(ERROR,
1492 errmsg("relation \"%s\" does not exist",
1493 relation->relname)));
1494 }
1495 }
1497 return rel;
1498}
1499
1500/*
1501 * Add an entry for a relation to the pstate's range table (p_rtable).
1502 * Then, construct and return a ParseNamespaceItem for the new RTE.
1503 *
1504 * We do not link the ParseNamespaceItem into the pstate here; it's the
1505 * caller's job to do that in the appropriate way.
1506 *
1507 * Note: formerly this checked for refname conflicts, but that's wrong.
1508 * Caller is responsible for checking for conflicts in the appropriate scope.
1509 */
1512 RangeVar *relation,
1513 Alias *alias,
1514 bool inh,
1515 bool inFromCl)
1516{
1519 char *refname = alias ? alias->aliasname : relation->relname;
1520 LOCKMODE lockmode;
1521 Relation rel;
1523
1524 Assert(pstate != NULL);
1525
1526 rte->rtekind = RTE_RELATION;
1527 rte->alias = alias;
1528
1529 /*
1530 * Identify the type of lock we'll need on this relation. It's not the
1531 * query's target table (that case is handled elsewhere), so we need
1532 * either RowShareLock if it's locked by FOR UPDATE/SHARE, or plain
1533 * AccessShareLock otherwise.
1534 */
1535 lockmode = isLockedRefname(pstate, refname) ? RowShareLock : AccessShareLock;
1536
1537 /*
1538 * Get the rel's OID. This access also ensures that we have an up-to-date
1539 * relcache entry for the rel. Since this is typically the first access
1540 * to a rel in a statement, we must open the rel with the proper lockmode.
1541 */
1542 rel = parserOpenTable(pstate, relation, lockmode);
1543 rte->relid = RelationGetRelid(rel);
1544 rte->inh = inh;
1545 rte->relkind = rel->rd_rel->relkind;
1546 rte->rellockmode = lockmode;
1547
1548 /*
1549 * Build the list of effective column names using user-supplied aliases
1550 * and/or actual column names.
1551 */
1552 rte->eref = makeAlias(refname, NIL);
1553 buildRelationAliases(rel->rd_att, alias, rte->eref);
1554
1555 /*
1556 * Set flags and initialize access permissions.
1557 *
1558 * The initial default on access checks is always check-for-READ-access,
1559 * which is the right thing for all except target tables.
1560 */
1561 rte->lateral = false;
1562 rte->inFromCl = inFromCl;
1563
1565 perminfo->requiredPerms = ACL_SELECT;
1566
1567 /*
1568 * Add completed RTE to pstate's range table list, so that we know its
1569 * index. But we don't add it to the join list --- caller must do that if
1570 * appropriate.
1571 */
1572 pstate->p_rtable = lappend(pstate->p_rtable, rte);
1573
1574 /*
1575 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
1576 * list --- caller must do that if appropriate.
1577 */
1579 perminfo, rel->rd_att);
1580
1581 /*
1582 * Drop the rel refcount, but keep the access lock till end of transaction
1583 * so that the table can't be deleted or have its schema modified
1584 * underneath us.
1585 */
1586 table_close(rel, NoLock);
1587
1588 return nsitem;
1589}
1590
1591/*
1592 * Add an entry for a relation to the pstate's range table (p_rtable).
1593 * Then, construct and return a ParseNamespaceItem for the new RTE.
1594 *
1595 * This is just like addRangeTableEntry() except that it makes an RTE
1596 * given an already-open relation instead of a RangeVar reference.
1597 *
1598 * lockmode is the lock type required for query execution; it must be one
1599 * of AccessShareLock, RowShareLock, or RowExclusiveLock depending on the
1600 * RTE's role within the query. The caller must hold that lock mode
1601 * or a stronger one.
1602 */
1605 Relation rel,
1606 LOCKMODE lockmode,
1607 Alias *alias,
1608 bool inh,
1609 bool inFromCl)
1610{
1613 char *refname = alias ? alias->aliasname : RelationGetRelationName(rel);
1614
1615 Assert(pstate != NULL);
1616
1617 Assert(lockmode == AccessShareLock ||
1618 lockmode == RowShareLock ||
1619 lockmode == RowExclusiveLock);
1620 Assert(CheckRelationLockedByMe(rel, lockmode, true));
1621
1622 rte->rtekind = RTE_RELATION;
1623 rte->alias = alias;
1624 rte->relid = RelationGetRelid(rel);
1625 rte->inh = inh;
1626 rte->relkind = rel->rd_rel->relkind;
1627 rte->rellockmode = lockmode;
1628
1629 /*
1630 * Build the list of effective column names using user-supplied aliases
1631 * and/or actual column names.
1632 */
1633 rte->eref = makeAlias(refname, NIL);
1634 buildRelationAliases(rel->rd_att, alias, rte->eref);
1635
1636 /*
1637 * Set flags and initialize access permissions.
1638 *
1639 * The initial default on access checks is always check-for-READ-access,
1640 * which is the right thing for all except target tables.
1641 */
1642 rte->lateral = false;
1643 rte->inFromCl = inFromCl;
1644
1646 perminfo->requiredPerms = ACL_SELECT;
1647
1648 /*
1649 * Add completed RTE to pstate's range table list, so that we know its
1650 * index. But we don't add it to the join list --- caller must do that if
1651 * appropriate.
1652 */
1653 pstate->p_rtable = lappend(pstate->p_rtable, rte);
1654
1655 /*
1656 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
1657 * list --- caller must do that if appropriate.
1658 */
1660 perminfo, rel->rd_att);
1661}
1662
1663/*
1664 * Add an entry for a subquery to the pstate's range table (p_rtable).
1665 * Then, construct and return a ParseNamespaceItem for the new RTE.
1666 *
1667 * This is much like addRangeTableEntry() except that it makes a subquery RTE.
1668 *
1669 * If the subquery does not have an alias, the auto-generated relation name in
1670 * the returned ParseNamespaceItem will be marked as not visible, and so only
1671 * unqualified references to the subquery columns will be allowed, and the
1672 * relation name will not conflict with others in the pstate's namespace list.
1673 */
1676 Query *subquery,
1677 Alias *alias,
1678 bool lateral,
1679 bool inFromCl)
1680{
1682 Alias *eref;
1683 int numaliases;
1684 List *coltypes,
1685 *coltypmods,
1687 int varattno;
1690
1691 Assert(pstate != NULL);
1692
1693 rte->rtekind = RTE_SUBQUERY;
1694 rte->subquery = subquery;
1695 rte->alias = alias;
1696
1697 eref = alias ? copyObject(alias) : makeAlias("unnamed_subquery", NIL);
1698 numaliases = list_length(eref->colnames);
1699
1700 /* fill in any unspecified alias columns, and extract column type info */
1702 varattno = 0;
1703 foreach(tlistitem, subquery->targetList)
1704 {
1706
1707 if (te->resjunk)
1708 continue;
1709 varattno++;
1710 Assert(varattno == te->resno);
1711 if (varattno > numaliases)
1712 {
1713 char *attrname;
1714
1715 attrname = pstrdup(te->resname);
1716 eref->colnames = lappend(eref->colnames, makeString(attrname));
1717 }
1719 exprType((Node *) te->expr));
1721 exprTypmod((Node *) te->expr));
1723 exprCollation((Node *) te->expr));
1724 }
1725 if (varattno < numaliases)
1726 ereport(ERROR,
1728 errmsg("table \"%s\" has %d columns available but %d columns specified",
1729 eref->aliasname, varattno, numaliases)));
1730
1731 rte->eref = eref;
1732
1733 /*
1734 * Set flags.
1735 *
1736 * Subqueries are never checked for access rights, so no need to perform
1737 * addRTEPermissionInfo().
1738 */
1739 rte->lateral = lateral;
1740 rte->inFromCl = inFromCl;
1741
1742 /*
1743 * Add completed RTE to pstate's range table list, so that we know its
1744 * index. But we don't add it to the join list --- caller must do that if
1745 * appropriate.
1746 */
1747 pstate->p_rtable = lappend(pstate->p_rtable, rte);
1748
1749 /*
1750 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
1751 * list --- caller must do that if appropriate.
1752 */
1755
1756 /*
1757 * Mark it visible as a relation name only if it had a user-written alias.
1758 */
1759 nsitem->p_rel_visible = (alias != NULL);
1760
1761 return nsitem;
1762}
1763
1764/*
1765 * Add an entry for a function (or functions) to the pstate's range table
1766 * (p_rtable). Then, construct and return a ParseNamespaceItem for the new RTE.
1767 *
1768 * This is much like addRangeTableEntry() except that it makes a function RTE.
1769 */
1772 List *funcnames,
1773 List *funcexprs,
1776 bool lateral,
1777 bool inFromCl)
1778{
1780 Alias *alias = rangefunc->alias;
1781 Alias *eref;
1782 char *aliasname;
1783 int nfuncs = list_length(funcexprs);
1785 TupleDesc tupdesc;
1786 ListCell *lc1,
1787 *lc2,
1788 *lc3;
1789 int i;
1790 int j;
1791 int funcno;
1792 int natts,
1793 totalatts;
1794
1795 Assert(pstate != NULL);
1796
1797 rte->rtekind = RTE_FUNCTION;
1798 rte->relid = InvalidOid;
1799 rte->subquery = NULL;
1800 rte->functions = NIL; /* we'll fill this list below */
1801 rte->funcordinality = rangefunc->ordinality;
1802 rte->alias = alias;
1803
1804 /*
1805 * Choose the RTE alias name. We default to using the first function's
1806 * name even when there's more than one; which is maybe arguable but beats
1807 * using something constant like "table".
1808 */
1809 if (alias)
1810 aliasname = alias->aliasname;
1811 else
1812 aliasname = linitial(funcnames);
1813
1814 eref = makeAlias(aliasname, NIL);
1815 rte->eref = eref;
1816
1817 /* Process each function ... */
1819
1820 totalatts = 0;
1821 funcno = 0;
1823 {
1824 Node *funcexpr = (Node *) lfirst(lc1);
1825 char *funcname = (char *) lfirst(lc2);
1826 List *coldeflist = (List *) lfirst(lc3);
1830
1831 /* Initialize RangeTblFunction node */
1832 rtfunc->funcexpr = funcexpr;
1833 rtfunc->funccolnames = NIL;
1834 rtfunc->funccoltypes = NIL;
1835 rtfunc->funccoltypmods = NIL;
1836 rtfunc->funccolcollations = NIL;
1837 rtfunc->funcparams = NULL; /* not set until planning */
1838
1839 /*
1840 * Now determine if the function returns a simple or composite type.
1841 */
1843 &funcrettype,
1844 &tupdesc);
1845
1846 /*
1847 * A coldeflist is required if the function returns RECORD and hasn't
1848 * got a predetermined record type, and is prohibited otherwise. This
1849 * can be a bit confusing, so we expend some effort on delivering a
1850 * relevant error message.
1851 */
1852 if (coldeflist != NIL)
1853 {
1854 switch (functypclass)
1855 {
1856 case TYPEFUNC_RECORD:
1857 /* ok */
1858 break;
1859 case TYPEFUNC_COMPOSITE:
1861
1862 /*
1863 * If the function's raw result type is RECORD, we must
1864 * have resolved it using its OUT parameters. Otherwise,
1865 * it must have a named composite type.
1866 */
1867 if (exprType(funcexpr) == RECORDOID)
1868 ereport(ERROR,
1870 errmsg("a column definition list is redundant for a function with OUT parameters"),
1871 parser_errposition(pstate,
1872 exprLocation((Node *) coldeflist))));
1873 else
1874 ereport(ERROR,
1876 errmsg("a column definition list is redundant for a function returning a named composite type"),
1877 parser_errposition(pstate,
1878 exprLocation((Node *) coldeflist))));
1879 break;
1880 default:
1881 ereport(ERROR,
1883 errmsg("a column definition list is only allowed for functions returning \"record\""),
1884 parser_errposition(pstate,
1885 exprLocation((Node *) coldeflist))));
1886 break;
1887 }
1888 }
1889 else
1890 {
1892 ereport(ERROR,
1894 errmsg("a column definition list is required for functions returning \"record\""),
1895 parser_errposition(pstate, exprLocation(funcexpr))));
1896 }
1897
1900 {
1901 /* Composite data type, e.g. a table's row type */
1902 Assert(tupdesc);
1903 }
1904 else if (functypclass == TYPEFUNC_SCALAR)
1905 {
1906 /* Base data type, i.e. scalar */
1907 tupdesc = CreateTemplateTupleDesc(1);
1908 TupleDescInitEntry(tupdesc,
1909 (AttrNumber) 1,
1911 alias, nfuncs),
1913 exprTypmod(funcexpr),
1914 0);
1916 (AttrNumber) 1,
1917 exprCollation(funcexpr));
1918 TupleDescFinalize(tupdesc);
1919 }
1920 else if (functypclass == TYPEFUNC_RECORD)
1921 {
1922 ListCell *col;
1923
1924 /*
1925 * Use the column definition list to construct a tupdesc and fill
1926 * in the RangeTblFunction's lists. Limit number of columns to
1927 * MaxHeapAttributeNumber, because CheckAttributeNamesTypes will.
1928 */
1929 if (list_length(coldeflist) > MaxHeapAttributeNumber)
1930 ereport(ERROR,
1932 errmsg("column definition lists can have at most %d entries",
1934 parser_errposition(pstate,
1935 exprLocation((Node *) coldeflist))));
1936 tupdesc = CreateTemplateTupleDesc(list_length(coldeflist));
1937 i = 1;
1938 foreach(col, coldeflist)
1939 {
1940 ColumnDef *n = (ColumnDef *) lfirst(col);
1941 char *attrname;
1942 Oid attrtype;
1943 int32 attrtypmod;
1945
1946 attrname = n->colname;
1947 if (n->typeName->setof)
1948 ereport(ERROR,
1950 errmsg("column \"%s\" cannot be declared SETOF",
1951 attrname),
1952 parser_errposition(pstate, n->location)));
1953 typenameTypeIdAndMod(pstate, n->typeName,
1954 &attrtype, &attrtypmod);
1955 attrcollation = GetColumnDefCollation(pstate, n, attrtype);
1956 TupleDescInitEntry(tupdesc,
1957 (AttrNumber) i,
1958 attrname,
1959 attrtype,
1960 attrtypmod,
1961 0);
1963 (AttrNumber) i,
1965 rtfunc->funccolnames = lappend(rtfunc->funccolnames,
1967 rtfunc->funccoltypes = lappend_oid(rtfunc->funccoltypes,
1968 attrtype);
1969 rtfunc->funccoltypmods = lappend_int(rtfunc->funccoltypmods,
1970 attrtypmod);
1971 rtfunc->funccolcollations = lappend_oid(rtfunc->funccolcollations,
1973
1974 i++;
1975 }
1976 TupleDescFinalize(tupdesc);
1977
1978 /*
1979 * Ensure that the coldeflist defines a legal set of names (no
1980 * duplicates, but we needn't worry about system column names) and
1981 * datatypes. Although we mostly can't allow pseudo-types, it
1982 * seems safe to allow RECORD and RECORD[], since values within
1983 * those type classes are self-identifying at runtime, and the
1984 * coldeflist doesn't represent anything that will be visible to
1985 * other sessions.
1986 */
1989 }
1990 else
1991 ereport(ERROR,
1993 errmsg("function \"%s\" in FROM has unsupported return type %s",
1995 parser_errposition(pstate, exprLocation(funcexpr))));
1996
1997 /* Finish off the RangeTblFunction and add it to the RTE's list */
1998 rtfunc->funccolcount = tupdesc->natts;
1999 rte->functions = lappend(rte->functions, rtfunc);
2000
2001 /* Save the tupdesc for use below */
2002 functupdescs[funcno] = tupdesc;
2003 totalatts += tupdesc->natts;
2004 funcno++;
2005 }
2006
2007 /*
2008 * If there's more than one function, or we want an ordinality column, we
2009 * have to produce a merged tupdesc.
2010 */
2011 if (nfuncs > 1 || rangefunc->ordinality)
2012 {
2013 if (rangefunc->ordinality)
2014 totalatts++;
2015
2016 /* Disallow more columns than will fit in a tuple */
2018 ereport(ERROR,
2020 errmsg("functions in FROM can return at most %d columns",
2022 parser_errposition(pstate,
2023 exprLocation((Node *) funcexprs))));
2024
2025 /* Merge the tuple descs of each function into a composite one */
2027 natts = 0;
2028 for (i = 0; i < nfuncs; i++)
2029 {
2030 for (j = 1; j <= functupdescs[i]->natts; j++)
2031 TupleDescCopyEntry(tupdesc, ++natts, functupdescs[i], j);
2032 }
2033
2034 /* Add the ordinality column if needed */
2035 if (rangefunc->ordinality)
2036 {
2037 TupleDescInitEntry(tupdesc,
2038 (AttrNumber) ++natts,
2039 "ordinality",
2040 INT8OID,
2041 -1,
2042 0);
2043 /* no need to set collation */
2044 }
2045 TupleDescFinalize(tupdesc);
2046 Assert(natts == totalatts);
2047 }
2048 else
2049 {
2050 /* We can just use the single function's tupdesc as-is */
2051 tupdesc = functupdescs[0];
2052 }
2053
2054 /* Use the tupdesc while assigning column aliases for the RTE */
2055 buildRelationAliases(tupdesc, alias, eref);
2056
2057 /*
2058 * Set flags and access permissions.
2059 *
2060 * Functions are never checked for access rights (at least, not by
2061 * ExecCheckPermissions()), so no need to perform addRTEPermissionInfo().
2062 */
2063 rte->lateral = lateral;
2064 rte->inFromCl = inFromCl;
2065
2066 /*
2067 * Add completed RTE to pstate's range table list, so that we know its
2068 * index. But we don't add it to the join list --- caller must do that if
2069 * appropriate.
2070 */
2071 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2072
2073 /*
2074 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2075 * list --- caller must do that if appropriate.
2076 */
2078 tupdesc);
2079}
2080
2081/*
2082 * Add an entry for a table function to the pstate's range table (p_rtable).
2083 * Then, construct and return a ParseNamespaceItem for the new RTE.
2084 *
2085 * This is much like addRangeTableEntry() except that it makes a tablefunc RTE.
2086 */
2089 TableFunc *tf,
2090 Alias *alias,
2091 bool lateral,
2092 bool inFromCl)
2093{
2095 char *refname;
2096 Alias *eref;
2097 int numaliases;
2098
2099 Assert(pstate != NULL);
2100
2101 /* Disallow more columns than will fit in a tuple */
2102 if (list_length(tf->colnames) > MaxTupleAttributeNumber)
2103 ereport(ERROR,
2105 errmsg("functions in FROM can return at most %d columns",
2107 parser_errposition(pstate,
2108 exprLocation((Node *) tf))));
2109 Assert(list_length(tf->coltypes) == list_length(tf->colnames));
2110 Assert(list_length(tf->coltypmods) == list_length(tf->colnames));
2111 Assert(list_length(tf->colcollations) == list_length(tf->colnames));
2112
2113 rte->rtekind = RTE_TABLEFUNC;
2114 rte->relid = InvalidOid;
2115 rte->subquery = NULL;
2116 rte->tablefunc = tf;
2117 rte->coltypes = tf->coltypes;
2118 rte->coltypmods = tf->coltypmods;
2119 rte->colcollations = tf->colcollations;
2120 rte->alias = alias;
2121
2122 refname = alias ? alias->aliasname :
2123 pstrdup(tf->functype == TFT_XMLTABLE ? "xmltable" : "json_table");
2124 eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
2125 numaliases = list_length(eref->colnames);
2126
2127 /* fill in any unspecified alias columns */
2128 if (numaliases < list_length(tf->colnames))
2129 eref->colnames = list_concat(eref->colnames,
2130 list_copy_tail(tf->colnames, numaliases));
2131
2132 if (numaliases > list_length(tf->colnames))
2133 ereport(ERROR,
2135 errmsg("%s function has %d columns available but %d columns specified",
2136 tf->functype == TFT_XMLTABLE ? "XMLTABLE" : "JSON_TABLE",
2137 list_length(tf->colnames), numaliases)));
2138
2139 rte->eref = eref;
2140
2141 /*
2142 * Set flags and access permissions.
2143 *
2144 * Tablefuncs are never checked for access rights (at least, not by
2145 * ExecCheckPermissions()), so no need to perform addRTEPermissionInfo().
2146 */
2147 rte->lateral = lateral;
2148 rte->inFromCl = inFromCl;
2149
2150 /*
2151 * Add completed RTE to pstate's range table list, so that we know its
2152 * index. But we don't add it to the join list --- caller must do that if
2153 * appropriate.
2154 */
2155 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2156
2157 /*
2158 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2159 * list --- caller must do that if appropriate.
2160 */
2162 rte->coltypes, rte->coltypmods,
2163 rte->colcollations);
2164}
2165
2168 Oid graphid,
2169 GraphPattern *graph_pattern,
2170 List *columns,
2171 List *colnames,
2172 Alias *alias,
2173 bool lateral,
2174 bool inFromCl)
2175{
2177 char *refname = alias ? alias->aliasname : pstrdup("graph_table");
2178 Alias *eref;
2179 int numaliases;
2180 int varattno;
2181 ListCell *lc;
2182 List *coltypes = NIL;
2183 List *coltypmods = NIL;
2187
2188 Assert(pstate != NULL);
2189
2190 rte->rtekind = RTE_GRAPH_TABLE;
2191 rte->relid = graphid;
2192 rte->relkind = RELKIND_PROPGRAPH;
2193 rte->graph_pattern = graph_pattern;
2194 rte->graph_table_columns = columns;
2195 rte->alias = alias;
2196 rte->rellockmode = AccessShareLock;
2197
2198 eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
2199
2200 if (!eref->colnames)
2201 eref->colnames = colnames;
2202
2203 numaliases = list_length(eref->colnames);
2204
2205 /* fill in any unspecified alias columns */
2206 varattno = 0;
2207 foreach(lc, colnames)
2208 {
2209 varattno++;
2210 if (varattno > numaliases)
2211 eref->colnames = lappend(eref->colnames, lfirst(lc));
2212 }
2213 if (varattno < numaliases)
2214 ereport(ERROR,
2216 errmsg("GRAPH_TABLE \"%s\" has %d columns available but %d columns specified",
2217 refname, varattno, numaliases)));
2218
2219 rte->eref = eref;
2220
2221 foreach(lc, columns)
2222 {
2224 Node *colexpr = (Node *) te->expr;
2225
2229 }
2230
2231 /*
2232 * Set flags and access permissions.
2233 */
2234 rte->lateral = lateral;
2235 rte->inFromCl = inFromCl;
2236
2238 perminfo->requiredPerms = ACL_SELECT;
2239
2240 /*
2241 * Add completed RTE to pstate's range table list, so that we know its
2242 * index. But we don't add it to the join list --- caller must do that if
2243 * appropriate.
2244 */
2245 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2246
2247 /*
2248 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2249 * list --- caller must do that if appropriate.
2250 */
2253
2254 nsitem->p_perminfo = perminfo;
2255
2256 return nsitem;
2257}
2258
2259/*
2260 * Add an entry for a VALUES list to the pstate's range table (p_rtable).
2261 * Then, construct and return a ParseNamespaceItem for the new RTE.
2262 *
2263 * This is much like addRangeTableEntry() except that it makes a values RTE.
2264 */
2267 List *exprs,
2268 List *coltypes,
2271 Alias *alias,
2272 bool lateral,
2273 bool inFromCl)
2274{
2276 char *refname = alias ? alias->aliasname : pstrdup("*VALUES*");
2277 Alias *eref;
2278 int numaliases;
2279 int numcolumns;
2280
2281 Assert(pstate != NULL);
2282
2283 rte->rtekind = RTE_VALUES;
2284 rte->relid = InvalidOid;
2285 rte->subquery = NULL;
2286 rte->values_lists = exprs;
2287 rte->coltypes = coltypes;
2288 rte->coltypmods = coltypmods;
2289 rte->colcollations = colcollations;
2290 rte->alias = alias;
2291
2292 eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
2293
2294 /* fill in any unspecified alias columns */
2295 numcolumns = list_length((List *) linitial(exprs));
2296 numaliases = list_length(eref->colnames);
2297 while (numaliases < numcolumns)
2298 {
2299 char attrname[64];
2300
2301 numaliases++;
2302 snprintf(attrname, sizeof(attrname), "column%d", numaliases);
2303 eref->colnames = lappend(eref->colnames,
2305 }
2306 if (numcolumns < numaliases)
2307 ereport(ERROR,
2309 errmsg("VALUES lists \"%s\" have %d columns available but %d columns specified",
2310 refname, numcolumns, numaliases)));
2311
2312 rte->eref = eref;
2313
2314 /*
2315 * Set flags and access permissions.
2316 *
2317 * Subqueries are never checked for access rights, so no need to perform
2318 * addRTEPermissionInfo().
2319 */
2320 rte->lateral = lateral;
2321 rte->inFromCl = inFromCl;
2322
2323 /*
2324 * Add completed RTE to pstate's range table list, so that we know its
2325 * index. But we don't add it to the join list --- caller must do that if
2326 * appropriate.
2327 */
2328 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2329
2330 /*
2331 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2332 * list --- caller must do that if appropriate.
2333 */
2335 rte->coltypes, rte->coltypmods,
2336 rte->colcollations);
2337}
2338
2339/*
2340 * Add an entry for a join to the pstate's range table (p_rtable).
2341 * Then, construct and return a ParseNamespaceItem for the new RTE.
2342 *
2343 * This is much like addRangeTableEntry() except that it makes a join RTE.
2344 * Also, it's more convenient for the caller to construct the
2345 * ParseNamespaceColumn array, so we pass that in.
2346 */
2349 List *colnames,
2351 JoinType jointype,
2352 int nummergedcols,
2353 List *aliasvars,
2354 List *leftcols,
2355 List *rightcols,
2357 Alias *alias,
2358 bool inFromCl)
2359{
2361 Alias *eref;
2362 int numaliases;
2364
2365 Assert(pstate != NULL);
2366
2367 /*
2368 * Fail if join has too many columns --- we must be able to reference any
2369 * of the columns with an AttrNumber.
2370 */
2372 ereport(ERROR,
2374 errmsg("joins can have at most %d columns",
2375 MaxAttrNumber)));
2376
2377 rte->rtekind = RTE_JOIN;
2378 rte->relid = InvalidOid;
2379 rte->subquery = NULL;
2380 rte->jointype = jointype;
2381 rte->joinmergedcols = nummergedcols;
2382 rte->joinaliasvars = aliasvars;
2383 rte->joinleftcols = leftcols;
2384 rte->joinrightcols = rightcols;
2385 rte->join_using_alias = join_using_alias;
2386 rte->alias = alias;
2387
2388 eref = alias ? copyObject(alias) : makeAlias("unnamed_join", NIL);
2389 numaliases = list_length(eref->colnames);
2390
2391 /* fill in any unspecified alias columns */
2392 if (numaliases < list_length(colnames))
2393 eref->colnames = list_concat(eref->colnames,
2394 list_copy_tail(colnames, numaliases));
2395
2396 if (numaliases > list_length(colnames))
2397 ereport(ERROR,
2399 errmsg("join expression \"%s\" has %d columns available but %d columns specified",
2400 eref->aliasname, list_length(colnames), numaliases)));
2401
2402 rte->eref = eref;
2403
2404 /*
2405 * Set flags and access permissions.
2406 *
2407 * Joins are never checked for access rights, so no need to perform
2408 * addRTEPermissionInfo().
2409 */
2410 rte->lateral = false;
2411 rte->inFromCl = inFromCl;
2412
2413 /*
2414 * Add completed RTE to pstate's range table list, so that we know its
2415 * index. But we don't add it to the join list --- caller must do that if
2416 * appropriate.
2417 */
2418 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2419
2420 /*
2421 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2422 * list --- caller must do that if appropriate.
2423 */
2425 nsitem->p_names = rte->eref;
2426 nsitem->p_rte = rte;
2427 nsitem->p_perminfo = NULL;
2428 nsitem->p_rtindex = list_length(pstate->p_rtable);
2429 nsitem->p_nscolumns = nscolumns;
2430 /* set default visibility flags; might get changed later */
2431 nsitem->p_rel_visible = true;
2432 nsitem->p_cols_visible = true;
2433 nsitem->p_lateral_only = false;
2434 nsitem->p_lateral_ok = true;
2435 nsitem->p_returning_type = VAR_RETURNING_DEFAULT;
2436
2437 return nsitem;
2438}
2439
2440/*
2441 * Add an entry for a CTE reference to the pstate's range table (p_rtable).
2442 * Then, construct and return a ParseNamespaceItem for the new RTE.
2443 *
2444 * This is much like addRangeTableEntry() except that it makes a CTE RTE.
2445 */
2448 CommonTableExpr *cte,
2449 Index levelsup,
2450 RangeVar *rv,
2451 bool inFromCl)
2452{
2454 Alias *alias = rv->alias;
2455 char *refname = alias ? alias->aliasname : cte->ctename;
2456 Alias *eref;
2457 int numaliases;
2458 int varattno;
2459 ListCell *lc;
2460 int n_dontexpand_columns = 0;
2462
2463 Assert(pstate != NULL);
2464
2465 rte->rtekind = RTE_CTE;
2466 rte->ctename = cte->ctename;
2467 rte->ctelevelsup = levelsup;
2468
2469 /* Self-reference if and only if CTE's parse analysis isn't completed */
2470 rte->self_reference = !IsA(cte->ctequery, Query);
2471 Assert(cte->cterecursive || !rte->self_reference);
2472 /* Bump the CTE's refcount if this isn't a self-reference */
2473 if (!rte->self_reference)
2474 cte->cterefcount++;
2475
2476 /*
2477 * We throw error if the CTE is INSERT/UPDATE/DELETE/MERGE without
2478 * RETURNING. This won't get checked in case of a self-reference, but
2479 * that's OK because data-modifying CTEs aren't allowed to be recursive
2480 * anyhow.
2481 */
2482 if (IsA(cte->ctequery, Query))
2483 {
2484 Query *ctequery = (Query *) cte->ctequery;
2485
2486 if (ctequery->commandType != CMD_SELECT &&
2487 ctequery->returningList == NIL)
2488 ereport(ERROR,
2490 errmsg("WITH query \"%s\" does not have a RETURNING clause",
2491 cte->ctename),
2492 parser_errposition(pstate, rv->location)));
2493 }
2494
2495 rte->coltypes = list_copy(cte->ctecoltypes);
2496 rte->coltypmods = list_copy(cte->ctecoltypmods);
2497 rte->colcollations = list_copy(cte->ctecolcollations);
2498
2499 rte->alias = alias;
2500 if (alias)
2501 eref = copyObject(alias);
2502 else
2503 eref = makeAlias(refname, NIL);
2504 numaliases = list_length(eref->colnames);
2505
2506 /* fill in any unspecified alias columns */
2507 varattno = 0;
2508 foreach(lc, cte->ctecolnames)
2509 {
2510 varattno++;
2511 if (varattno > numaliases)
2512 eref->colnames = lappend(eref->colnames, lfirst(lc));
2513 }
2514 if (varattno < numaliases)
2515 ereport(ERROR,
2517 errmsg("table \"%s\" has %d columns available but %d columns specified",
2518 refname, varattno, numaliases)));
2519
2520 rte->eref = eref;
2521
2522 if (cte->search_clause)
2523 {
2524 rte->eref->colnames = lappend(rte->eref->colnames, makeString(cte->search_clause->search_seq_column));
2525 if (cte->search_clause->search_breadth_first)
2526 rte->coltypes = lappend_oid(rte->coltypes, RECORDOID);
2527 else
2528 rte->coltypes = lappend_oid(rte->coltypes, RECORDARRAYOID);
2529 rte->coltypmods = lappend_int(rte->coltypmods, -1);
2530 rte->colcollations = lappend_oid(rte->colcollations, InvalidOid);
2531
2533 }
2534
2535 if (cte->cycle_clause)
2536 {
2537 rte->eref->colnames = lappend(rte->eref->colnames, makeString(cte->cycle_clause->cycle_mark_column));
2538 rte->coltypes = lappend_oid(rte->coltypes, cte->cycle_clause->cycle_mark_type);
2539 rte->coltypmods = lappend_int(rte->coltypmods, cte->cycle_clause->cycle_mark_typmod);
2540 rte->colcollations = lappend_oid(rte->colcollations, cte->cycle_clause->cycle_mark_collation);
2541
2542 rte->eref->colnames = lappend(rte->eref->colnames, makeString(cte->cycle_clause->cycle_path_column));
2543 rte->coltypes = lappend_oid(rte->coltypes, RECORDARRAYOID);
2544 rte->coltypmods = lappend_int(rte->coltypmods, -1);
2545 rte->colcollations = lappend_oid(rte->colcollations, InvalidOid);
2546
2548 }
2549
2550 /*
2551 * Set flags and access permissions.
2552 *
2553 * Subqueries are never checked for access rights, so no need to perform
2554 * addRTEPermissionInfo().
2555 */
2556 rte->lateral = false;
2557 rte->inFromCl = inFromCl;
2558
2559 /*
2560 * Add completed RTE to pstate's range table list, so that we know its
2561 * index. But we don't add it to the join list --- caller must do that if
2562 * appropriate.
2563 */
2564 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2565
2566 /*
2567 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2568 * list --- caller must do that if appropriate.
2569 */
2571 rte->coltypes, rte->coltypmods,
2572 rte->colcollations);
2573
2574 /*
2575 * The columns added by search and cycle clauses are not included in star
2576 * expansion in queries contained in the CTE.
2577 */
2578 if (rte->ctelevelsup > 0)
2579 for (int i = 0; i < n_dontexpand_columns; i++)
2580 psi->p_nscolumns[list_length(psi->p_names->colnames) - 1 - i].p_dontexpand = true;
2581
2582 return psi;
2583}
2584
2585/*
2586 * Add an entry for an ephemeral named relation reference to the pstate's
2587 * range table (p_rtable).
2588 * Then, construct and return a ParseNamespaceItem for the new RTE.
2589 *
2590 * It is expected that the RangeVar, which up until now is only known to be an
2591 * ephemeral named relation, will (in conjunction with the QueryEnvironment in
2592 * the ParseState), create a RangeTblEntry for a specific *kind* of ephemeral
2593 * named relation, based on enrtype.
2594 *
2595 * This is much like addRangeTableEntry() except that it makes an RTE for an
2596 * ephemeral named relation.
2597 */
2600 RangeVar *rv,
2601 bool inFromCl)
2602{
2604 Alias *alias = rv->alias;
2605 char *refname = alias ? alias->aliasname : rv->relname;
2607 TupleDesc tupdesc;
2608 int attno;
2609
2610 Assert(pstate != NULL);
2611 enrmd = get_visible_ENR(pstate, rv->relname);
2612 Assert(enrmd != NULL);
2613
2614 switch (enrmd->enrtype)
2615 {
2617 rte->rtekind = RTE_NAMEDTUPLESTORE;
2618 break;
2619
2620 default:
2621 elog(ERROR, "unexpected enrtype: %d", enrmd->enrtype);
2622 return NULL; /* for fussy compilers */
2623 }
2624
2625 /*
2626 * Record dependency on a relation. This allows plans to be invalidated
2627 * if they access transition tables linked to a table that is altered.
2628 */
2629 rte->relid = enrmd->reliddesc;
2630
2631 /*
2632 * Build the list of effective column names using user-supplied aliases
2633 * and/or actual column names.
2634 */
2635 tupdesc = ENRMetadataGetTupDesc(enrmd);
2636 rte->eref = makeAlias(refname, NIL);
2637 buildRelationAliases(tupdesc, alias, rte->eref);
2638
2639 /* Record additional data for ENR, including column type info */
2640 rte->enrname = enrmd->name;
2641 rte->enrtuples = enrmd->enrtuples;
2642 rte->coltypes = NIL;
2643 rte->coltypmods = NIL;
2644 rte->colcollations = NIL;
2645 for (attno = 1; attno <= tupdesc->natts; ++attno)
2646 {
2647 Form_pg_attribute att = TupleDescAttr(tupdesc, attno - 1);
2648
2649 if (att->attisdropped)
2650 {
2651 /* Record zeroes for a dropped column */
2652 rte->coltypes = lappend_oid(rte->coltypes, InvalidOid);
2653 rte->coltypmods = lappend_int(rte->coltypmods, 0);
2654 rte->colcollations = lappend_oid(rte->colcollations, InvalidOid);
2655 }
2656 else
2657 {
2658 /* Let's just make sure we can tell this isn't dropped */
2659 if (att->atttypid == InvalidOid)
2660 elog(ERROR, "atttypid is invalid for non-dropped column in \"%s\"",
2661 rv->relname);
2662 rte->coltypes = lappend_oid(rte->coltypes, att->atttypid);
2663 rte->coltypmods = lappend_int(rte->coltypmods, att->atttypmod);
2664 rte->colcollations = lappend_oid(rte->colcollations,
2665 att->attcollation);
2666 }
2667 }
2668
2669 /*
2670 * Set flags and access permissions.
2671 *
2672 * ENRs are never checked for access rights, so no need to perform
2673 * addRTEPermissionInfo().
2674 */
2675 rte->lateral = false;
2676 rte->inFromCl = inFromCl;
2677
2678 /*
2679 * Add completed RTE to pstate's range table list, so that we know its
2680 * index. But we don't add it to the join list --- caller must do that if
2681 * appropriate.
2682 */
2683 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2684
2685 /*
2686 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2687 * list --- caller must do that if appropriate.
2688 */
2690 tupdesc);
2691}
2692
2693/*
2694 * Add an entry for grouping step to the pstate's range table (p_rtable).
2695 * Then, construct and return a ParseNamespaceItem for the new RTE.
2696 */
2699 List *groupClauses)
2700{
2702 Alias *eref;
2703 List *groupexprs;
2704 List *coltypes,
2705 *coltypmods,
2707 ListCell *lc;
2709
2710 Assert(pstate != NULL);
2711
2712 rte->rtekind = RTE_GROUP;
2713 rte->alias = NULL;
2714
2715 eref = makeAlias("*GROUP*", NIL);
2716
2717 /* fill in any unspecified alias columns, and extract column type info */
2718 groupexprs = NIL;
2720 foreach(lc, groupClauses)
2721 {
2722 TargetEntry *te = (TargetEntry *) lfirst(lc);
2723 char *colname = te->resname ? pstrdup(te->resname) : "?column?";
2724
2725 eref->colnames = lappend(eref->colnames, makeString(colname));
2726
2727 groupexprs = lappend(groupexprs, copyObject(te->expr));
2728
2730 exprType((Node *) te->expr));
2732 exprTypmod((Node *) te->expr));
2734 exprCollation((Node *) te->expr));
2735 }
2736
2737 rte->eref = eref;
2738 rte->groupexprs = groupexprs;
2739
2740 /*
2741 * Set flags.
2742 *
2743 * The grouping step is never checked for access rights, so no need to
2744 * perform addRTEPermissionInfo().
2745 */
2746 rte->lateral = false;
2747 rte->inFromCl = false;
2748
2749 /*
2750 * Add completed RTE to pstate's range table list, so that we know its
2751 * index. But we don't add it to the join list --- caller must do that if
2752 * appropriate.
2753 */
2754 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2755
2756 /*
2757 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2758 * list --- caller must do that if appropriate.
2759 */
2762
2763 return nsitem;
2764}
2765
2766
2767/*
2768 * Has the specified refname been selected FOR UPDATE/FOR SHARE?
2769 *
2770 * This is used when we have not yet done transformLockingClause, but need
2771 * to know the correct lock to take during initial opening of relations.
2772 *
2773 * Note that refname may be NULL (for a subquery without an alias), in which
2774 * case the relation can't be locked by name, but it might still be locked if
2775 * a locking clause requests that all tables be locked.
2776 *
2777 * Note: we pay no attention to whether it's FOR UPDATE vs FOR SHARE,
2778 * since the table-level lock is the same either way.
2779 */
2780bool
2781isLockedRefname(ParseState *pstate, const char *refname)
2782{
2783 ListCell *l;
2784
2785 /*
2786 * If we are in a subquery specified as locked FOR UPDATE/SHARE from
2787 * parent level, then act as though there's a generic FOR UPDATE here.
2788 */
2789 if (pstate->p_locked_from_parent)
2790 return true;
2791
2792 foreach(l, pstate->p_locking_clause)
2793 {
2795
2796 if (lc->lockedRels == NIL)
2797 {
2798 /* all tables used in query */
2799 return true;
2800 }
2801 else if (refname != NULL)
2802 {
2803 /* just the named tables */
2804 ListCell *l2;
2805
2806 foreach(l2, lc->lockedRels)
2807 {
2808 RangeVar *thisrel = (RangeVar *) lfirst(l2);
2809
2810 if (strcmp(refname, thisrel->relname) == 0)
2811 return true;
2812 }
2813 }
2814 }
2815 return false;
2816}
2817
2818/*
2819 * Add the given nsitem/RTE as a top-level entry in the pstate's join list
2820 * and/or namespace list. (We assume caller has checked for any
2821 * namespace conflicts.) The nsitem is always marked as unconditionally
2822 * visible, that is, not LATERAL-only.
2823 */
2824void
2826 bool addToJoinList,
2828{
2829 if (addToJoinList)
2830 {
2832
2833 rtr->rtindex = nsitem->p_rtindex;
2834 pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
2835 }
2837 {
2838 /* Set the new nsitem's visibility flags correctly */
2839 nsitem->p_rel_visible = addToRelNameSpace;
2840 nsitem->p_cols_visible = addToVarNameSpace;
2841 nsitem->p_lateral_only = false;
2842 nsitem->p_lateral_ok = true;
2843 pstate->p_namespace = lappend(pstate->p_namespace, nsitem);
2844 }
2845}
2846
2847/*
2848 * expandRTE -- expand the columns of a rangetable entry
2849 *
2850 * This creates lists of an RTE's column names (aliases if provided, else
2851 * real names) and Vars for each column. Only user columns are considered.
2852 * If include_dropped is false then dropped columns are omitted from the
2853 * results. If include_dropped is true then empty strings and NULL constants
2854 * (not Vars!) are returned for dropped columns.
2855 *
2856 * rtindex, sublevels_up, returning_type, and location are the varno,
2857 * varlevelsup, varreturningtype, and location values to use in the created
2858 * Vars. Ordinarily rtindex should match the actual position of the RTE in
2859 * its rangetable.
2860 *
2861 * The output lists go into *colnames and *colvars.
2862 * If only one of the two kinds of output list is needed, pass NULL for the
2863 * output pointer for the unwanted one.
2864 */
2865void
2866expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
2867 VarReturningType returning_type,
2868 int location, bool include_dropped,
2869 List **colnames, List **colvars)
2870{
2871 int varattno;
2872
2873 if (colnames)
2874 *colnames = NIL;
2875 if (colvars)
2876 *colvars = NIL;
2877
2878 switch (rte->rtekind)
2879 {
2880 case RTE_RELATION:
2881 /* Ordinary relation RTE */
2882 expandRelation(rte->relid, rte->eref,
2883 rtindex, sublevels_up, returning_type, location,
2884 include_dropped, colnames, colvars);
2885 break;
2886 case RTE_SUBQUERY:
2887 {
2888 /* Subquery RTE */
2889 ListCell *aliasp_item = list_head(rte->eref->colnames);
2891
2892 varattno = 0;
2893 foreach(tlistitem, rte->subquery->targetList)
2894 {
2896
2897 if (te->resjunk)
2898 continue;
2899 varattno++;
2900 Assert(varattno == te->resno);
2901
2902 /*
2903 * Formerly it was possible for the subquery tlist to have
2904 * more non-junk entries than the colnames list does (if
2905 * this RTE has been expanded from a view that has more
2906 * columns than it did when the current query was parsed).
2907 * Now that ApplyRetrieveRule cleans up such cases, we
2908 * shouldn't see that anymore, but let's just check.
2909 */
2910 if (!aliasp_item)
2911 elog(ERROR, "too few column names for subquery %s",
2912 rte->eref->aliasname);
2913
2914 if (colnames)
2915 {
2916 char *label = strVal(lfirst(aliasp_item));
2917
2918 *colnames = lappend(*colnames, makeString(pstrdup(label)));
2919 }
2920
2921 if (colvars)
2922 {
2923 Var *varnode;
2924
2925 varnode = makeVar(rtindex, varattno,
2926 exprType((Node *) te->expr),
2927 exprTypmod((Node *) te->expr),
2928 exprCollation((Node *) te->expr),
2929 sublevels_up);
2930 varnode->varreturningtype = returning_type;
2931 varnode->location = location;
2932
2934 }
2935
2936 aliasp_item = lnext(rte->eref->colnames, aliasp_item);
2937 }
2938 }
2939 break;
2940 case RTE_FUNCTION:
2941 {
2942 /* Function RTE */
2943 int atts_done = 0;
2944 ListCell *lc;
2945
2946 foreach(lc, rte->functions)
2947 {
2951 TupleDesc tupdesc = NULL;
2952
2953 /* If it has a coldeflist, it returns RECORD */
2954 if (rtfunc->funccolnames != NIL)
2956 else
2958 &funcrettype,
2959 &tupdesc);
2960
2963 {
2964 /* Composite data type, e.g. a table's row type */
2965 Assert(tupdesc);
2966 expandTupleDesc(tupdesc, rte->eref,
2967 rtfunc->funccolcount, atts_done,
2968 rtindex, sublevels_up,
2969 returning_type, location,
2970 include_dropped, colnames, colvars);
2971 }
2972 else if (functypclass == TYPEFUNC_SCALAR)
2973 {
2974 /* Base data type, i.e. scalar */
2975 if (colnames)
2976 *colnames = lappend(*colnames,
2977 list_nth(rte->eref->colnames,
2978 atts_done));
2979
2980 if (colvars)
2981 {
2982 Var *varnode;
2983
2984 varnode = makeVar(rtindex, atts_done + 1,
2986 exprTypmod(rtfunc->funcexpr),
2987 exprCollation(rtfunc->funcexpr),
2988 sublevels_up);
2989 varnode->varreturningtype = returning_type;
2990 varnode->location = location;
2991
2993 }
2994 }
2995 else if (functypclass == TYPEFUNC_RECORD)
2996 {
2997 if (colnames)
2998 {
2999 List *namelist;
3000
3001 /* extract appropriate subset of column list */
3002 namelist = list_copy_tail(rte->eref->colnames,
3003 atts_done);
3005 rtfunc->funccolcount);
3006 *colnames = list_concat(*colnames, namelist);
3007 }
3008
3009 if (colvars)
3010 {
3011 ListCell *l1;
3012 ListCell *l2;
3013 ListCell *l3;
3014 int attnum = atts_done;
3015
3016 forthree(l1, rtfunc->funccoltypes,
3017 l2, rtfunc->funccoltypmods,
3018 l3, rtfunc->funccolcollations)
3019 {
3020 Oid attrtype = lfirst_oid(l1);
3021 int32 attrtypmod = lfirst_int(l2);
3023 Var *varnode;
3024
3025 attnum++;
3026 varnode = makeVar(rtindex,
3027 attnum,
3028 attrtype,
3029 attrtypmod,
3031 sublevels_up);
3032 varnode->varreturningtype = returning_type;
3033 varnode->location = location;
3035 }
3036 }
3037 }
3038 else
3039 {
3040 /* addRangeTableEntryForFunction should've caught this */
3041 elog(ERROR, "function in FROM has unsupported return type");
3042 }
3043 atts_done += rtfunc->funccolcount;
3044 }
3045
3046 /* Append the ordinality column if any */
3047 if (rte->funcordinality)
3048 {
3049 if (colnames)
3050 *colnames = lappend(*colnames,
3051 llast(rte->eref->colnames));
3052
3053 if (colvars)
3054 {
3055 Var *varnode = makeVar(rtindex,
3056 atts_done + 1,
3057 INT8OID,
3058 -1,
3059 InvalidOid,
3060 sublevels_up);
3061
3062 varnode->varreturningtype = returning_type;
3064 }
3065 }
3066 }
3067 break;
3068 case RTE_JOIN:
3069 {
3070 /* Join RTE */
3071 ListCell *colname;
3073
3074 Assert(list_length(rte->eref->colnames) == list_length(rte->joinaliasvars));
3075
3076 varattno = 0;
3077 forboth(colname, rte->eref->colnames, aliasvar, rte->joinaliasvars)
3078 {
3079 Node *avar = (Node *) lfirst(aliasvar);
3080
3081 varattno++;
3082
3083 /*
3084 * During ordinary parsing, there will never be any
3085 * deleted columns in the join. While this function is
3086 * also used by the rewriter and planner, they do not
3087 * currently call it on any JOIN RTEs. Therefore, this
3088 * next bit is dead code, but it seems prudent to handle
3089 * the case correctly anyway.
3090 */
3091 if (avar == NULL)
3092 {
3093 if (include_dropped)
3094 {
3095 if (colnames)
3096 *colnames = lappend(*colnames,
3097 makeString(pstrdup("")));
3098 if (colvars)
3099 {
3100 /*
3101 * Can't use join's column type here (it might
3102 * be dropped!); but it doesn't really matter
3103 * what type the Const claims to be.
3104 */
3107 InvalidOid));
3108 }
3109 }
3110 continue;
3111 }
3112
3113 if (colnames)
3114 {
3115 char *label = strVal(lfirst(colname));
3116
3117 *colnames = lappend(*colnames,
3119 }
3120
3121 if (colvars)
3122 {
3123 Var *varnode;
3124
3125 /*
3126 * If the joinaliasvars entry is a simple Var, just
3127 * copy it (with adjustment of varlevelsup and
3128 * location); otherwise it is a JOIN USING column and
3129 * we must generate a join alias Var. This matches
3130 * the results that expansion of "join.*" by
3131 * expandNSItemVars would have produced, if we had
3132 * access to the ParseNamespaceItem for the join.
3133 */
3134 if (IsA(avar, Var))
3135 {
3136 varnode = copyObject((Var *) avar);
3137 varnode->varlevelsup = sublevels_up;
3138 }
3139 else
3140 varnode = makeVar(rtindex, varattno,
3141 exprType(avar),
3144 sublevels_up);
3145 varnode->varreturningtype = returning_type;
3146 varnode->location = location;
3147
3149 }
3150 }
3151 }
3152 break;
3153 case RTE_TABLEFUNC:
3154 case RTE_VALUES:
3155 case RTE_CTE:
3157 case RTE_GRAPH_TABLE:
3158 {
3159 /* Tablefunc, Values, CTE, or ENR RTE */
3160 ListCell *aliasp_item = list_head(rte->eref->colnames);
3161 ListCell *lct;
3162 ListCell *lcm;
3163 ListCell *lcc;
3164
3165 varattno = 0;
3166 forthree(lct, rte->coltypes,
3167 lcm, rte->coltypmods,
3168 lcc, rte->colcollations)
3169 {
3170 Oid coltype = lfirst_oid(lct);
3173
3174 varattno++;
3175
3176 if (colnames)
3177 {
3178 /* Assume there is one alias per output column */
3179 if (OidIsValid(coltype))
3180 {
3181 char *label = strVal(lfirst(aliasp_item));
3182
3183 *colnames = lappend(*colnames,
3185 }
3186 else if (include_dropped)
3187 *colnames = lappend(*colnames,
3188 makeString(pstrdup("")));
3189
3190 aliasp_item = lnext(rte->eref->colnames, aliasp_item);
3191 }
3192
3193 if (colvars)
3194 {
3195 if (OidIsValid(coltype))
3196 {
3197 Var *varnode;
3198
3199 varnode = makeVar(rtindex, varattno,
3200 coltype, coltypmod, colcoll,
3201 sublevels_up);
3202 varnode->varreturningtype = returning_type;
3203 varnode->location = location;
3204
3206 }
3207 else if (include_dropped)
3208 {
3209 /*
3210 * It doesn't really matter what type the Const
3211 * claims to be.
3212 */
3215 InvalidOid));
3216 }
3217 }
3218 }
3219 }
3220 break;
3221 case RTE_RESULT:
3222 case RTE_GROUP:
3223 /* These expose no columns, so nothing to do */
3224 break;
3225 default:
3226 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
3227 }
3228}
3229
3230/*
3231 * expandRelation -- expandRTE subroutine
3232 */
3233static void
3234expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up,
3235 VarReturningType returning_type,
3236 int location, bool include_dropped,
3237 List **colnames, List **colvars)
3238{
3239 Relation rel;
3240
3241 /* Get the tupledesc and turn it over to expandTupleDesc */
3242 rel = relation_open(relid, AccessShareLock);
3243 expandTupleDesc(rel->rd_att, eref, rel->rd_att->natts, 0,
3244 rtindex, sublevels_up, returning_type,
3245 location, include_dropped,
3246 colnames, colvars);
3248}
3249
3250/*
3251 * expandTupleDesc -- expandRTE subroutine
3252 *
3253 * Generate names and/or Vars for the first "count" attributes of the tupdesc,
3254 * and append them to colnames/colvars. "offset" is added to the varattno
3255 * that each Var would otherwise have, and we also skip the first "offset"
3256 * entries in eref->colnames. (These provisions allow use of this code for
3257 * an individual composite-returning function in an RTE_FUNCTION RTE.)
3258 */
3259static void
3260expandTupleDesc(TupleDesc tupdesc, Alias *eref, int count, int offset,
3261 int rtindex, int sublevels_up,
3262 VarReturningType returning_type,
3263 int location, bool include_dropped,
3264 List **colnames, List **colvars)
3265{
3267 int varattno;
3268
3269 aliascell = (offset < list_length(eref->colnames)) ?
3270 list_nth_cell(eref->colnames, offset) : NULL;
3271
3273 for (varattno = 0; varattno < count; varattno++)
3274 {
3275 Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
3276
3277 if (attr->attisdropped)
3278 {
3279 if (include_dropped)
3280 {
3281 if (colnames)
3282 *colnames = lappend(*colnames, makeString(pstrdup("")));
3283 if (colvars)
3284 {
3285 /*
3286 * can't use atttypid here, but it doesn't really matter
3287 * what type the Const claims to be.
3288 */
3291 }
3292 }
3293 if (aliascell)
3294 aliascell = lnext(eref->colnames, aliascell);
3295 continue;
3296 }
3297
3298 if (colnames)
3299 {
3300 char *label;
3301
3302 if (aliascell)
3303 {
3305 aliascell = lnext(eref->colnames, aliascell);
3306 }
3307 else
3308 {
3309 /* If we run out of aliases, use the underlying name */
3310 label = NameStr(attr->attname);
3311 }
3312 *colnames = lappend(*colnames, makeString(pstrdup(label)));
3313 }
3314
3315 if (colvars)
3316 {
3317 Var *varnode;
3318
3319 varnode = makeVar(rtindex, varattno + offset + 1,
3320 attr->atttypid, attr->atttypmod,
3321 attr->attcollation,
3322 sublevels_up);
3323 varnode->varreturningtype = returning_type;
3324 varnode->location = location;
3325
3327 }
3328 }
3329}
3330
3331/*
3332 * expandNSItemVars
3333 * Produce a list of Vars, and optionally a list of column names,
3334 * for the non-dropped columns of the nsitem.
3335 *
3336 * The emitted Vars are marked with the given sublevels_up and location.
3337 *
3338 * If colnames isn't NULL, a list of String items for the columns is stored
3339 * there; note that it's just a subset of the RTE's eref list, and hence
3340 * the list elements mustn't be modified.
3341 */
3342List *
3344 int sublevels_up, int location,
3345 List **colnames)
3346{
3347 List *result = NIL;
3348 int colindex;
3349 ListCell *lc;
3350
3351 if (colnames)
3352 *colnames = NIL;
3353 colindex = 0;
3354 foreach(lc, nsitem->p_names->colnames)
3355 {
3357 const char *colname = strVal(colnameval);
3358 ParseNamespaceColumn *nscol = nsitem->p_nscolumns + colindex;
3359
3360 if (nscol->p_dontexpand)
3361 {
3362 /* skip */
3363 }
3364 else if (colname[0])
3365 {
3366 Var *var;
3367
3368 Assert(nscol->p_varno > 0);
3369 var = makeVar(nscol->p_varno,
3370 nscol->p_varattno,
3371 nscol->p_vartype,
3372 nscol->p_vartypmod,
3373 nscol->p_varcollid,
3374 sublevels_up);
3375 /* makeVar doesn't offer parameters for these, so set by hand: */
3376 var->varreturningtype = nscol->p_varreturningtype;
3377 var->varnosyn = nscol->p_varnosyn;
3378 var->varattnosyn = nscol->p_varattnosyn;
3379 var->location = location;
3380
3381 /* ... and update varnullingrels */
3382 markNullableIfNeeded(pstate, var);
3383
3384 result = lappend(result, var);
3385 if (colnames)
3386 *colnames = lappend(*colnames, colnameval);
3387 }
3388 else
3389 {
3390 /* dropped column, ignore */
3391 Assert(nscol->p_varno == 0);
3392 }
3393 colindex++;
3394 }
3395 return result;
3396}
3397
3398/*
3399 * expandNSItemAttrs -
3400 * Workhorse for "*" expansion: produce a list of targetentries
3401 * for the attributes of the nsitem
3402 *
3403 * pstate->p_next_resno determines the resnos assigned to the TLEs.
3404 * The referenced columns are marked as requiring SELECT access, if
3405 * caller requests that.
3406 */
3407List *
3409 int sublevels_up, bool require_col_privs, int location)
3410{
3411 RangeTblEntry *rte = nsitem->p_rte;
3412 RTEPermissionInfo *perminfo = nsitem->p_perminfo;
3413 List *names,
3414 *vars;
3415 ListCell *name,
3416 *var;
3417 List *te_list = NIL;
3418
3419 vars = expandNSItemVars(pstate, nsitem, sublevels_up, location, &names);
3420
3421 /*
3422 * Require read access to the table. This is normally redundant with the
3423 * markVarForSelectPriv calls below, but not if the table has zero
3424 * columns. We need not do anything if the nsitem is for a join: its
3425 * component tables will have been marked ACL_SELECT when they were added
3426 * to the rangetable. (This step changes things only for the target
3427 * relation of UPDATE/DELETE, which cannot be under a join.)
3428 */
3429 if (rte->rtekind == RTE_RELATION)
3430 {
3431 Assert(perminfo != NULL);
3432 perminfo->requiredPerms |= ACL_SELECT;
3433 }
3434
3435 forboth(name, names, var, vars)
3436 {
3437 char *label = strVal(lfirst(name));
3438 Var *varnode = (Var *) lfirst(var);
3439 TargetEntry *te;
3440
3441 te = makeTargetEntry((Expr *) varnode,
3442 (AttrNumber) pstate->p_next_resno++,
3443 label,
3444 false);
3445 te_list = lappend(te_list, te);
3446
3448 {
3449 /* Require read access to each column */
3451 }
3452 }
3453
3454 Assert(name == NULL && var == NULL); /* lists not the same length? */
3455
3456 return te_list;
3457}
3458
3459/*
3460 * get_rte_attribute_name
3461 * Get an attribute name from a RangeTblEntry
3462 *
3463 * This is unlike get_attname() because we use aliases if available.
3464 * In particular, it will work on an RTE for a subselect or join, whereas
3465 * get_attname() only works on real relations.
3466 *
3467 * "*" is returned if the given attnum is InvalidAttrNumber --- this case
3468 * occurs when a Var represents a whole tuple of a relation.
3469 *
3470 * It is caller's responsibility to not call this on a dropped attribute.
3471 * (You will get some answer for such cases, but it might not be sensible.)
3472 */
3473char *
3475{
3477 return "*";
3478
3479 /*
3480 * If there is a user-written column alias, use it.
3481 */
3482 if (rte->alias &&
3483 attnum > 0 && attnum <= list_length(rte->alias->colnames))
3484 return strVal(list_nth(rte->alias->colnames, attnum - 1));
3485
3486 /*
3487 * If the RTE is a relation, go to the system catalogs not the
3488 * eref->colnames list. This is a little slower but it will give the
3489 * right answer if the column has been renamed since the eref list was
3490 * built (which can easily happen for rules).
3491 */
3492 if (rte->rtekind == RTE_RELATION)
3493 return get_attname(rte->relid, attnum, false);
3494
3495 /*
3496 * Otherwise use the column name from eref. There should always be one.
3497 */
3498 if (attnum > 0 && attnum <= list_length(rte->eref->colnames))
3499 return strVal(list_nth(rte->eref->colnames, attnum - 1));
3500
3501 /* else caller gave us a bogus attnum */
3502 elog(ERROR, "invalid attnum %d for rangetable entry %s",
3503 attnum, rte->eref->aliasname);
3504 return NULL; /* keep compiler quiet */
3505}
3506
3507/*
3508 * get_rte_attribute_is_dropped
3509 * Check whether attempted attribute ref is to a dropped column
3510 */
3511bool
3513{
3514 bool result;
3515
3516 switch (rte->rtekind)
3517 {
3518 case RTE_RELATION:
3519 {
3520 /*
3521 * Plain relation RTE --- get the attribute's catalog entry
3522 */
3523 HeapTuple tp;
3525
3527 ObjectIdGetDatum(rte->relid),
3529 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
3530 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
3531 attnum, rte->relid);
3533 result = att_tup->attisdropped;
3534 ReleaseSysCache(tp);
3535 }
3536 break;
3537 case RTE_SUBQUERY:
3538 case RTE_TABLEFUNC:
3539 case RTE_VALUES:
3540 case RTE_CTE:
3541 case RTE_GROUP:
3542 case RTE_GRAPH_TABLE:
3543
3544 /*
3545 * Subselect, Table Functions, Values, CTE, GROUP RTEs, Property
3546 * graph references never have dropped columns
3547 */
3548 result = false;
3549 break;
3551 {
3552 /* Check dropped-ness by testing for valid coltype */
3553 if (attnum <= 0 ||
3554 attnum > list_length(rte->coltypes))
3555 elog(ERROR, "invalid varattno %d", attnum);
3556 result = !OidIsValid((list_nth_oid(rte->coltypes, attnum - 1)));
3557 }
3558 break;
3559 case RTE_JOIN:
3560 {
3561 /*
3562 * A join RTE would not have dropped columns when constructed,
3563 * but one in a stored rule might contain columns that were
3564 * dropped from the underlying tables, if said columns are
3565 * nowhere explicitly referenced in the rule. This will be
3566 * signaled to us by a null pointer in the joinaliasvars list.
3567 */
3568 Var *aliasvar;
3569
3570 if (attnum <= 0 ||
3571 attnum > list_length(rte->joinaliasvars))
3572 elog(ERROR, "invalid varattno %d", attnum);
3573 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
3574
3575 result = (aliasvar == NULL);
3576 }
3577 break;
3578 case RTE_FUNCTION:
3579 {
3580 /* Function RTE */
3581 ListCell *lc;
3582 int atts_done = 0;
3583
3584 /*
3585 * Dropped attributes are only possible with functions that
3586 * return named composite types. In such a case we have to
3587 * look up the result type to see if it currently has this
3588 * column dropped. So first, loop over the funcs until we
3589 * find the one that covers the requested column.
3590 */
3591 foreach(lc, rte->functions)
3592 {
3594
3595 if (attnum > atts_done &&
3597 {
3598 TupleDesc tupdesc;
3599
3600 /* If it has a coldeflist, it returns RECORD */
3601 if (rtfunc->funccolnames != NIL)
3602 return false; /* can't have any dropped columns */
3603
3604 tupdesc = get_expr_result_tupdesc(rtfunc->funcexpr,
3605 true);
3606 if (tupdesc)
3607 {
3608 /* Composite data type, e.g. a table's row type */
3609 CompactAttribute *att;
3610
3611 Assert(tupdesc);
3613 att = TupleDescCompactAttr(tupdesc,
3614 attnum - atts_done - 1);
3615 return att->attisdropped;
3616 }
3617 /* Otherwise, it can't have any dropped columns */
3618 return false;
3619 }
3620 atts_done += rtfunc->funccolcount;
3621 }
3622
3623 /* If we get here, must be looking for the ordinality column */
3624 if (rte->funcordinality && attnum == atts_done + 1)
3625 return false;
3626
3627 /* this probably can't happen ... */
3628 ereport(ERROR,
3630 errmsg("column %d of relation \"%s\" does not exist",
3631 attnum,
3632 rte->eref->aliasname)));
3633 result = false; /* keep compiler quiet */
3634 }
3635 break;
3636 case RTE_RESULT:
3637 /* this probably can't happen ... */
3638 ereport(ERROR,
3640 errmsg("column %d of relation \"%s\" does not exist",
3641 attnum,
3642 rte->eref->aliasname)));
3643 result = false; /* keep compiler quiet */
3644 break;
3645 default:
3646 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
3647 result = false; /* keep compiler quiet */
3648 }
3649
3650 return result;
3651}
3652
3653/*
3654 * Given a targetlist and a resno, return the matching TargetEntry
3655 *
3656 * Returns NULL if resno is not present in list.
3657 *
3658 * Note: we need to search, rather than just indexing with list_nth(),
3659 * because not all tlists are sorted by resno.
3660 */
3663{
3664 ListCell *l;
3665
3666 foreach(l, tlist)
3667 {
3669
3670 if (tle->resno == resno)
3671 return tle;
3672 }
3673 return NULL;
3674}
3675
3676/*
3677 * Given a Query and rangetable index, return relation's RowMarkClause if any
3678 *
3679 * Returns NULL if relation is not selected FOR UPDATE/SHARE
3680 */
3683{
3684 ListCell *l;
3685
3686 foreach(l, qry->rowMarks)
3687 {
3688 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
3689
3690 if (rc->rti == rtindex)
3691 return rc;
3692 }
3693 return NULL;
3694}
3695
3696/*
3697 * given relation and att name, return attnum of variable
3698 *
3699 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
3700 *
3701 * This should only be used if the relation is already
3702 * table_open()'ed. Use the cache version get_attnum()
3703 * for access to non-opened relations.
3704 */
3705int
3707{
3708 int i;
3709
3710 for (i = 0; i < RelationGetNumberOfAttributes(rd); i++)
3711 {
3712 Form_pg_attribute att = TupleDescAttr(rd->rd_att, i);
3713
3714 if (namestrcmp(&(att->attname), attname) == 0 && !att->attisdropped)
3715 return i + 1;
3716 }
3717
3718 if (sysColOK)
3719 {
3721 return i;
3722 }
3723
3724 /* on failure */
3725 return InvalidAttrNumber;
3726}
3727
3728/*
3729 * specialAttNum()
3730 *
3731 * Check attribute name to see if it is "special", e.g. "xmin".
3732 * - thomas 2000-02-07
3733 *
3734 * Note: this only discovers whether the name could be a system attribute.
3735 * Caller needs to ensure that it really is an attribute of the rel.
3736 */
3737static int
3739{
3741
3743 if (sysatt != NULL)
3744 return sysatt->attnum;
3745 return InvalidAttrNumber;
3746}
3747
3748
3749/*
3750 * given attribute id, return name of that attribute
3751 *
3752 * This should only be used if the relation is already
3753 * table_open()'ed. Use the cache version get_atttype()
3754 * for access to non-opened relations.
3755 */
3756const NameData *
3758{
3759 if (attid <= 0)
3760 {
3762
3764 return &sysatt->attname;
3765 }
3766 if (attid > rd->rd_att->natts)
3767 elog(ERROR, "invalid attribute number %d", attid);
3768 return &TupleDescAttr(rd->rd_att, attid - 1)->attname;
3769}
3770
3771/*
3772 * given attribute id, return type of that attribute
3773 *
3774 * This should only be used if the relation is already
3775 * table_open()'ed. Use the cache version get_atttype()
3776 * for access to non-opened relations.
3777 */
3778Oid
3780{
3781 if (attid <= 0)
3782 {
3784
3786 return sysatt->atttypid;
3787 }
3788 if (attid > rd->rd_att->natts)
3789 elog(ERROR, "invalid attribute number %d", attid);
3790 return TupleDescAttr(rd->rd_att, attid - 1)->atttypid;
3791}
3792
3793/*
3794 * given attribute id, return collation of that attribute
3795 *
3796 * This should only be used if the relation is already table_open()'ed.
3797 */
3798Oid
3800{
3801 if (attid <= 0)
3802 {
3803 /* All system attributes are of noncollatable types. */
3804 return InvalidOid;
3805 }
3806 if (attid > rd->rd_att->natts)
3807 elog(ERROR, "invalid attribute number %d", attid);
3808 return TupleDescAttr(rd->rd_att, attid - 1)->attcollation;
3809}
3810
3811/*
3812 * Generate a suitable error about a missing RTE.
3813 *
3814 * Since this is a very common type of error, we work rather hard to
3815 * produce a helpful message.
3816 */
3817void
3819{
3821 const char *badAlias = NULL;
3822
3823 /*
3824 * Check to see if there are any potential matches in the query's
3825 * rangetable. (Note: cases involving a bad schema name in the RangeVar
3826 * will throw error immediately here. That seems OK.)
3827 */
3828 rte = searchRangeTableForRel(pstate, relation);
3829
3830 /*
3831 * If we found a match that has an alias and the alias is visible in the
3832 * namespace, then the problem is probably use of the relation's real name
3833 * instead of its alias, ie "SELECT foo.* FROM foo f". This mistake is
3834 * common enough to justify a specific hint.
3835 *
3836 * If we found a match that doesn't meet those criteria, assume the
3837 * problem is illegal use of a relation outside its scope, as in the
3838 * MySQL-ism "SELECT ... FROM a, b LEFT JOIN c ON (a.x = c.y)".
3839 */
3840 if (rte && rte->alias &&
3841 strcmp(rte->eref->aliasname, relation->relname) != 0)
3842 {
3844 int sublevels_up;
3845
3846 nsitem = refnameNamespaceItem(pstate, NULL, rte->eref->aliasname,
3847 relation->location,
3848 &sublevels_up);
3849 if (nsitem && nsitem->p_rte == rte)
3850 badAlias = rte->eref->aliasname;
3851 }
3852
3853 /* If it looks like the user forgot to use an alias, hint about that */
3854 if (badAlias)
3855 ereport(ERROR,
3857 errmsg("invalid reference to FROM-clause entry for table \"%s\"",
3858 relation->relname),
3859 errhint("Perhaps you meant to reference the table alias \"%s\".",
3860 badAlias),
3861 parser_errposition(pstate, relation->location)));
3862 /* Hint about case where we found an (inaccessible) exact match */
3863 else if (rte)
3864 ereport(ERROR,
3866 errmsg("invalid reference to FROM-clause entry for table \"%s\"",
3867 relation->relname),
3868 errdetail("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.",
3869 rte->eref->aliasname),
3870 rte_visible_if_lateral(pstate, rte) ?
3871 errhint("To reference that table, you must mark this subquery with LATERAL.") : 0,
3872 parser_errposition(pstate, relation->location)));
3873 /* Else, we have nothing to offer but the bald statement of error */
3874 else
3875 ereport(ERROR,
3877 errmsg("missing FROM-clause entry for table \"%s\"",
3878 relation->relname),
3879 parser_errposition(pstate, relation->location)));
3880}
3881
3882/*
3883 * Generate a suitable error about a missing column.
3884 *
3885 * Since this is a very common type of error, we work rather hard to
3886 * produce a helpful message.
3887 */
3888void
3890 const char *relname, const char *colname, int location)
3891{
3893
3894 /*
3895 * Search the entire rtable looking for possible matches. If we find one,
3896 * emit a hint about it.
3897 */
3898 state = searchRangeTableForCol(pstate, relname, colname, location);
3899
3900 /*
3901 * If there are exact match(es), they must be inaccessible for some
3902 * reason.
3903 */
3904 if (state->rexact1)
3905 {
3906 /*
3907 * We don't try too hard when there's multiple inaccessible exact
3908 * matches, but at least be sure that we don't misleadingly suggest
3909 * that there's only one.
3910 */
3911 if (state->rexact2)
3912 ereport(ERROR,
3914 relname ?
3915 errmsg("column %s.%s does not exist", relname, colname) :
3916 errmsg("column \"%s\" does not exist", colname),
3917 errdetail("There are columns named \"%s\", but they are in tables that cannot be referenced from this part of the query.",
3918 colname),
3919 !relname ? errhint("Try using a table-qualified name.") : 0,
3920 parser_errposition(pstate, location)));
3921 /* Single exact match, so try to determine why it's inaccessible. */
3922 ereport(ERROR,
3924 relname ?
3925 errmsg("column %s.%s does not exist", relname, colname) :
3926 errmsg("column \"%s\" does not exist", colname),
3927 errdetail("There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query.",
3928 colname, state->rexact1->eref->aliasname),
3929 rte_visible_if_lateral(pstate, state->rexact1) ?
3930 errhint("To reference that column, you must mark this subquery with LATERAL.") :
3931 (!relname && rte_visible_if_qualified(pstate, state->rexact1)) ?
3932 errhint("To reference that column, you must use a table-qualified name.") : 0,
3933 parser_errposition(pstate, location)));
3934 }
3935
3936 if (!state->rsecond)
3937 {
3938 /* If we found no match at all, we have little to report */
3939 if (!state->rfirst)
3940 ereport(ERROR,
3942 relname ?
3943 errmsg("column %s.%s does not exist", relname, colname) :
3944 errmsg("column \"%s\" does not exist", colname),
3945 parser_errposition(pstate, location)));
3946 /* Handle case where we have a single alternative spelling to offer */
3947 ereport(ERROR,
3949 relname ?
3950 errmsg("column %s.%s does not exist", relname, colname) :
3951 errmsg("column \"%s\" does not exist", colname),
3952 errhint("Perhaps you meant to reference the column \"%s.%s\".",
3953 state->rfirst->eref->aliasname,
3954 strVal(list_nth(state->rfirst->eref->colnames,
3955 state->first - 1))),
3956 parser_errposition(pstate, location)));
3957 }
3958 else
3959 {
3960 /* Handle case where there are two equally useful column hints */
3961 ereport(ERROR,
3963 relname ?
3964 errmsg("column %s.%s does not exist", relname, colname) :
3965 errmsg("column \"%s\" does not exist", colname),
3966 errhint("Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\".",
3967 state->rfirst->eref->aliasname,
3968 strVal(list_nth(state->rfirst->eref->colnames,
3969 state->first - 1)),
3970 state->rsecond->eref->aliasname,
3971 strVal(list_nth(state->rsecond->eref->colnames,
3972 state->second - 1))),
3973 parser_errposition(pstate, location)));
3974 }
3975}
3976
3977/*
3978 * Find ParseNamespaceItem for RTE, if it's visible at all.
3979 * We assume an RTE couldn't appear more than once in the namespace lists.
3980 */
3981static ParseNamespaceItem *
3983{
3984 while (pstate != NULL)
3985 {
3986 ListCell *l;
3987
3988 foreach(l, pstate->p_namespace)
3989 {
3991
3992 if (nsitem->p_rte == rte)
3993 return nsitem;
3994 }
3995 pstate = pstate->parentParseState;
3996 }
3997 return NULL;
3998}
3999
4000/*
4001 * Would this RTE be visible, if only the user had written LATERAL?
4002 *
4003 * This is a helper for deciding whether to issue a HINT about LATERAL.
4004 * As such, it doesn't need to be 100% accurate; the HINT could be useful
4005 * even if it's not quite right. Hence, we don't delve into fine points
4006 * about whether a found nsitem has the appropriate one of p_rel_visible or
4007 * p_cols_visible set.
4008 */
4009static bool
4011{
4013
4014 /* If LATERAL *is* active, we're clearly barking up the wrong tree */
4015 if (pstate->p_lateral_active)
4016 return false;
4017 nsitem = findNSItemForRTE(pstate, rte);
4018 if (nsitem)
4019 {
4020 /* Found it, report whether it's LATERAL-only */
4021 return nsitem->p_lateral_only && nsitem->p_lateral_ok;
4022 }
4023 return false;
4024}
4025
4026/*
4027 * Would columns in this RTE be visible if qualified?
4028 */
4029static bool
4031{
4033
4034 if (nsitem)
4035 {
4036 /* Found it, report whether it's relation-only */
4037 return nsitem->p_rel_visible && !nsitem->p_cols_visible;
4038 }
4039 return false;
4040}
4041
4042
4043/*
4044 * addRTEPermissionInfo
4045 * Creates RTEPermissionInfo for a given RTE and adds it into the
4046 * provided list.
4047 *
4048 * Returns the RTEPermissionInfo and sets rte->perminfoindex.
4049 */
4052{
4054
4055 Assert(OidIsValid(rte->relid));
4056 Assert(rte->perminfoindex == 0);
4057
4058 /* Nope, so make one and add to the list. */
4060 perminfo->relid = rte->relid;
4061 perminfo->inh = rte->inh;
4062 /* Other information is set by fetching the node as and where needed. */
4063
4064 *rteperminfos = lappend(*rteperminfos, perminfo);
4065
4066 /* Note its index (1-based!) */
4067 rte->perminfoindex = list_length(*rteperminfos);
4068
4069 return perminfo;
4070}
4071
4072/*
4073 * getRTEPermissionInfo
4074 * Find RTEPermissionInfo for a given relation in the provided list.
4075 *
4076 * This is a simple list_nth() operation, though it's good to have the
4077 * function for the various sanity checks.
4078 */
4081{
4083
4084 if (rte->perminfoindex == 0 ||
4085 rte->perminfoindex > list_length(rteperminfos))
4086 elog(ERROR, "invalid perminfoindex %u in RTE with relid %u",
4087 rte->perminfoindex, rte->relid);
4089 rte->perminfoindex - 1);
4090 if (perminfo->relid != rte->relid)
4091 elog(ERROR, "permission info at index %u (with relid=%u) does not match provided RTE (with relid=%u)",
4092 rte->perminfoindex, perminfo->relid, rte->relid);
4093
4094 return perminfo;
4095}
int16 AttrNumber
Definition attnum.h:21
#define MaxAttrNumber
Definition attnum.h:24
#define InvalidAttrNumber
Definition attnum.h:23
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:251
#define NameStr(name)
Definition c.h:891
#define Assert(condition)
Definition c.h:999
int32_t int32
Definition c.h:676
unsigned int Index
Definition c.h:754
#define OidIsValid(objectId)
Definition c.h:914
uint32 result
int errcode(int sqlerrcode)
Definition elog.c:875
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
#define palloc_object(type)
Definition fe_memutils.h:89
#define palloc_array(type, count)
Definition fe_memutils.h:91
char * format_type_be(Oid type_oid)
char * get_func_result_name(Oid functionId)
Definition funcapi.c:1610
TupleDesc get_expr_result_tupdesc(Node *expr, bool noError)
Definition funcapi.c:553
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition funcapi.c:299
TypeFuncClass
Definition funcapi.h:147
@ TYPEFUNC_SCALAR
Definition funcapi.h:148
@ TYPEFUNC_COMPOSITE
Definition funcapi.h:149
@ TYPEFUNC_RECORD
Definition funcapi.h:151
@ TYPEFUNC_COMPOSITE_DOMAIN
Definition funcapi.h:150
const FormData_pg_attribute * SystemAttributeByName(const char *attname)
Definition heap.c:248
void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, int flags)
Definition heap.c:453
const FormData_pg_attribute * SystemAttributeDefinition(AttrNumber attno)
Definition heap.c:236
#define CHKATYPE_ANYRECORD
Definition heap.h:24
#define HeapTupleIsValid(tuple)
Definition htup.h:78
#define MaxTupleAttributeNumber
static void * GETSTRUCT(const HeapTupleData *tuple)
#define MaxHeapAttributeNumber
#define funcname
int j
Definition isn.c:78
int i
Definition isn.c:77
List * lappend(List *list, void *datum)
Definition list.c:339
List * list_copy_tail(const List *oldlist, int nskip)
Definition list.c:1613
List * list_concat(List *list1, const List *list2)
Definition list.c:561
List * list_copy(const List *oldlist)
Definition list.c:1573
List * lappend_int(List *list, int datum)
Definition list.c:357
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
List * list_truncate(List *list, int new_size)
Definition list.c:631
bool CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger)
Definition lmgr.c:334
int LOCKMODE
Definition lockdefs.h:26
#define NoLock
Definition lockdefs.h:34
#define AccessShareLock
Definition lockdefs.h:36
#define RowShareLock
Definition lockdefs.h:37
#define RowExclusiveLock
Definition lockdefs.h:38
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:1045
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition lsyscache.c:2191
Alias * makeAlias(const char *aliasname, List *colnames)
Definition makefuncs.c:438
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition makefuncs.c:66
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition makefuncs.c:388
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition makefuncs.c:289
char * pstrdup(const char *in)
Definition mcxt.c:1910
void * palloc0(Size size)
Definition mcxt.c:1420
int namestrcmp(Name name, const char *str)
Definition name.c:247
Oid LookupNamespaceNoError(const char *nspname)
Definition namespace.c:3427
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition namespace.h:98
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:304
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
int exprLocation(const Node *expr)
Definition nodeFuncs.c:1403
#define IsA(nodeptr, _type_)
Definition nodes.h:162
#define copyObject(obj)
Definition nodes.h:230
#define nodeTag(nodeptr)
Definition nodes.h:137
@ CMD_SELECT
Definition nodes.h:273
#define makeNode(_type_)
Definition nodes.h:159
JoinType
Definition nodes.h:296
static char * errmsg
EphemeralNamedRelationMetadata get_visible_ENR(ParseState *pstate, const char *refname)
Definition parse_enr.c:26
bool name_matches_visible_ENR(ParseState *pstate, const char *refname)
Definition parse_enr.c:20
void cancel_parser_errposition_callback(ParseCallbackState *pcbstate)
Definition parse_node.c:156
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106
void setup_parser_errposition_callback(ParseCallbackState *pcbstate, ParseState *pstate, int location)
Definition parse_node.c:140
@ EXPR_KIND_MERGE_WHEN
Definition parse_node.h:58
@ EXPR_KIND_GENERATED_COLUMN
Definition parse_node.h:84
@ EXPR_KIND_CHECK_CONSTRAINT
Definition parse_node.h:69
static bool rte_visible_if_lateral(ParseState *pstate, RangeTblEntry *rte)
void markNullableIfNeeded(ParseState *pstate, Var *var)
Relation parserOpenTable(ParseState *pstate, const RangeVar *relation, LOCKMODE lockmode)
CommonTableExpr * scanNameSpaceForCTE(ParseState *pstate, const char *refname, Index *ctelevelsup)
static FuzzyAttrMatchState * searchRangeTableForCol(ParseState *pstate, const char *alias, const char *colname, int location)
void errorMissingColumn(ParseState *pstate, const char *relname, const char *colname, int location)
static int specialAttNum(const char *attname)
Node * colNameToVar(ParseState *pstate, const char *colname, bool localonly, int location)
static ParseNamespaceItem * buildNSItemFromTupleDesc(RangeTblEntry *rte, Index rtindex, RTEPermissionInfo *perminfo, TupleDesc tupdesc)
static ParseNamespaceItem * scanNameSpaceForRelid(ParseState *pstate, Oid relid, int location)
CommonTableExpr * GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte, int rtelevelsup)
Oid attnumCollationId(Relation rd, int attid)
static RangeTblEntry * searchRangeTableForRel(ParseState *pstate, RangeVar *relation)
static void expandTupleDesc(TupleDesc tupdesc, Alias *eref, int count, int offset, int rtindex, int sublevels_up, VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars)
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
ParseNamespaceItem * addRangeTableEntryForENR(ParseState *pstate, RangeVar *rv, bool inFromCl)
void markVarForSelectPriv(ParseState *pstate, Var *var)
ParseNamespaceItem * addRangeTableEntry(ParseState *pstate, RangeVar *relation, Alias *alias, bool inh, bool inFromCl)
RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)
char * get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
static ParseNamespaceItem * scanNameSpaceForRefname(ParseState *pstate, const char *refname, int location)
void errorMissingRTE(ParseState *pstate, RangeVar *relation)
ParseNamespaceItem * addRangeTableEntryForGraphTable(ParseState *pstate, Oid graphid, GraphPattern *graph_pattern, List *columns, List *colnames, Alias *alias, bool lateral, bool inFromCl)
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
static bool isFutureCTE(ParseState *pstate, const char *refname)
ParseNamespaceItem * addRangeTableEntryForTableFunc(ParseState *pstate, TableFunc *tf, Alias *alias, bool lateral, bool inFromCl)
List * expandNSItemVars(ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, int location, List **colnames)
bool get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
static void updateFuzzyAttrMatchState(int fuzzy_rte_penalty, FuzzyAttrMatchState *fuzzystate, RangeTblEntry *rte, const char *actual, const char *match, int attnum)
static ParseNamespaceItem * buildNSItemFromLists(RangeTblEntry *rte, Index rtindex, List *coltypes, List *coltypmods, List *colcollations)
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
static int scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, Alias *eref, const char *colname, int location, int fuzzy_rte_penalty, FuzzyAttrMatchState *fuzzystate)
#define MAX_FUZZY_DISTANCE
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, LOCKMODE lockmode, Alias *alias, bool inh, bool inFromCl)
void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars)
ParseNamespaceItem * GetNSItemByRangeTablePosn(ParseState *pstate, int varno, int sublevels_up)
bool scanNameSpaceForENR(ParseState *pstate, const char *refname)
Node * scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, const char *colname, int location)
ParseNamespaceItem * addRangeTableEntryForFunction(ParseState *pstate, List *funcnames, List *funcexprs, List *coldeflists, RangeFunction *rangefunc, bool lateral, bool inFromCl)
bool isLockedRefname(ParseState *pstate, const char *refname)
Oid attnumTypeId(Relation rd, int attid)
RTEPermissionInfo * addRTEPermissionInfo(List **rteperminfos, RangeTblEntry *rte)
const NameData * attnumAttName(Relation rd, int attid)
ParseNamespaceItem * addRangeTableEntryForSubquery(ParseState *pstate, Query *subquery, Alias *alias, bool lateral, bool inFromCl)
static void expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up, VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars)
ParseNamespaceItem * addRangeTableEntryForCTE(ParseState *pstate, CommonTableExpr *cte, Index levelsup, RangeVar *rv, bool inFromCl)
static bool rte_visible_if_qualified(ParseState *pstate, RangeTblEntry *rte)
ParseNamespaceItem * addRangeTableEntryForGroup(ParseState *pstate, List *groupClauses)
static void markRTEForSelectPriv(ParseState *pstate, int rtindex, AttrNumber col)
ParseNamespaceItem * addRangeTableEntryForJoin(ParseState *pstate, List *colnames, ParseNamespaceColumn *nscolumns, JoinType jointype, int nummergedcols, List *aliasvars, List *leftcols, List *rightcols, Alias *join_using_alias, Alias *alias, bool inFromCl)
List * expandNSItemAttrs(ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, bool require_col_privs, int location)
ParseNamespaceItem * refnameNamespaceItem(ParseState *pstate, const char *schemaname, const char *refname, int location, int *sublevels_up)
ParseNamespaceItem * GetNSItemByVar(ParseState *pstate, Var *var)
RangeTblEntry * GetRTEByRangeTablePosn(ParseState *pstate, int varno, int sublevels_up)
static void buildRelationAliases(TupleDesc tupdesc, Alias *alias, Alias *eref)
int attnameAttNum(Relation rd, const char *attname, bool sysColOK)
void checkNameSpaceConflicts(ParseState *pstate, List *namespace1, List *namespace2)
static char * chooseScalarFunctionAlias(Node *funcexpr, char *funcname, Alias *alias, int nfuncs)
static ParseNamespaceItem * findNSItemForRTE(ParseState *pstate, RangeTblEntry *rte)
static void check_lateral_ref_ok(ParseState *pstate, ParseNamespaceItem *nsitem, int location)
ParseNamespaceItem * addRangeTableEntryForValues(ParseState *pstate, List *exprs, List *coltypes, List *coltypmods, List *colcollations, Alias *alias, bool lateral, bool inFromCl)
void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
Definition parse_type.c:310
Oid GetColumnDefCollation(ParseState *pstate, const ColumnDef *coldef, Oid typeOid)
Definition parse_type.c:540
@ RTE_JOIN
@ RTE_CTE
@ RTE_NAMEDTUPLESTORE
@ RTE_VALUES
@ RTE_SUBQUERY
@ RTE_RESULT
@ RTE_FUNCTION
@ RTE_TABLEFUNC
@ RTE_GROUP
@ RTE_GRAPH_TABLE
@ RTE_RELATION
#define ACL_SELECT
Definition parsenodes.h:77
#define rt_fetch(rangetable_index, rangetable)
Definition parsetree.h:31
FormData_pg_attribute
NameData attname
int16 attnum
FormData_pg_attribute * Form_pg_attribute
static char * label
NameData relname
Definition pg_class.h:40
#define lfirst(lc)
Definition pg_list.h:172
#define llast(l)
Definition pg_list.h:198
#define lfirst_node(type, lc)
Definition pg_list.h:176
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition pg_list.h:550
static Oid list_nth_oid(const List *list, int n)
Definition pg_list.h:353
#define lfirst_int(lc)
Definition pg_list.h:173
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition pg_list.h:595
static void * list_nth(const List *list, int n)
Definition pg_list.h:331
#define linitial(l)
Definition pg_list.h:178
static ListCell * list_nth_cell(const List *list, int n)
Definition pg_list.h:309
static ListCell * list_head(const List *l)
Definition pg_list.h:128
#define list_nth_node(type, list, n)
Definition pg_list.h:359
static ListCell * lnext(const List *l, const ListCell *c)
Definition pg_list.h:375
#define lfirst_oid(lc)
Definition pg_list.h:174
#define ERRCODE_UNDEFINED_TABLE
Definition pgbench.c:79
#define snprintf
Definition port.h:261
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
#define InvalidOid
unsigned int Oid
char * c
static int fb(int x)
@ TFT_XMLTABLE
Definition primnodes.h:101
VarReturningType
Definition primnodes.h:256
@ VAR_RETURNING_DEFAULT
Definition primnodes.h:257
TupleDesc ENRMetadataGetTupDesc(EphemeralNamedRelationMetadata enrmd)
@ ENR_NAMED_TUPLESTORE
#define RelationGetRelid(relation)
Definition rel.h:516
#define RelationGetNumberOfAttributes(relation)
Definition rel.h:522
#define RelationGetRelationName(relation)
Definition rel.h:550
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:206
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:48
char * aliasname
Definition primnodes.h:52
List * colnames
Definition primnodes.h:53
char * colname
Definition parsenodes.h:772
TypeName * typeName
Definition parsenodes.h:773
ParseLoc location
Definition parsenodes.h:791
bool attisdropped
Definition tupdesc.h:78
RangeTblEntry * rfirst
RangeTblEntry * rexact1
RangeTblEntry * rexact2
RangeTblEntry * rsecond
Definition pg_list.h:54
Definition nodes.h:133
RangeTblEntry * p_rte
Definition parse_node.h:315
ParseState * parentParseState
Definition parse_node.h:213
List * p_ctenamespace
Definition parse_node.h:225
ParseNamespaceItem * p_target_nsitem
Definition parse_node.h:229
ParseExprKind p_expr_kind
Definition parse_node.h:232
bool p_locked_from_parent
Definition parse_node.h:236
List * p_nullingrels
Definition parse_node.h:219
List * p_namespace
Definition parse_node.h:222
int p_next_resno
Definition parse_node.h:233
List * p_rteperminfos
Definition parse_node.h:216
List * p_joinexprs
Definition parse_node.h:218
List * p_future_ctes
Definition parse_node.h:226
List * p_joinlist
Definition parse_node.h:220
List * p_locking_clause
Definition parse_node.h:235
bool p_lateral_active
Definition parse_node.h:224
List * p_rtable
Definition parse_node.h:215
List * rowMarks
Definition parsenodes.h:239
List * returningList
Definition parsenodes.h:219
CmdType commandType
Definition parsenodes.h:124
List * targetList
Definition parsenodes.h:203
char * relname
Definition primnodes.h:84
Alias * alias
Definition primnodes.h:93
ParseLoc location
Definition primnodes.h:96
char * schemaname
Definition primnodes.h:81
TupleDesc rd_att
Definition rel.h:112
Form_pg_class rd_rel
Definition rel.h:111
Definition value.h:64
TableFuncType functype
Definition primnodes.h:115
Expr * expr
Definition primnodes.h:2259
AttrNumber resno
Definition primnodes.h:2261
bool setof
Definition parsenodes.h:292
ParseLoc location
Definition primnodes.h:311
AttrNumber varattno
Definition primnodes.h:275
int varno
Definition primnodes.h:270
VarReturningType varreturningtype
Definition primnodes.h:298
Index varlevelsup
Definition primnodes.h:295
Definition c.h:886
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27
#define TableOidAttributeNumber
Definition sysattr.h:26
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:231
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition syscache.h:102
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_openrv_extended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok)
Definition table.c:103
TupleDesc CreateTemplateTupleDesc(int natts)
Definition tupdesc.c:165
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:511
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition tupdesc.c:1093
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:909
void TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno, TupleDesc src, AttrNumber srcAttno)
Definition tupdesc.c:472
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:195
String * makeString(char *str)
Definition value.c:63
#define strVal(v)
Definition value.h:82
int varstr_levenshtein_less_equal(const char *source, int slen, const char *target, int tlen, int ins_c, int del_c, int sub_c, int max_d, bool trusted)
const char * name