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