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