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