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