diff options
author | Dean Rasheed <dean.a.rasheed@gmail.com> | 2022-07-20 09:29:42 +0100 |
---|---|---|
committer | Dean Rasheed <dean.a.rasheed@gmail.com> | 2022-07-20 09:29:42 +0100 |
commit | bcedd8f5fce0b69970cf0cee7bca560833d05869 (patch) | |
tree | c37888d24735977b7a0463b0277c1cbe459ac69f /src/backend/parser/parse_relation.c | |
parent | 1caf915ff31e91031f0a0b8e1016df2b59d6f9de (diff) |
Make subquery aliases optional in the FROM clause.
This allows aliases for sub-SELECTs and VALUES clauses in the FROM
clause to be omitted.
This is an extension of the SQL standard, supported by some other
database systems, and so eases the transition from such systems, as
well as removing the minor inconvenience caused by requiring these
aliases.
Patch by me, reviewed by Tom Lane.
Discussion: https://postgr.es/m/CAEZATCUCGCf82=hxd9N5n6xGHPyYpQnxW8HneeH+uP7yNALkWA@mail.gmail.com
Diffstat (limited to 'src/backend/parser/parse_relation.c')
-rw-r--r-- | src/backend/parser/parse_relation.c | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 926dcbf30e2..4e635561aaf 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -1577,7 +1577,11 @@ addRangeTableEntryForRelation(ParseState *pstate, * Then, construct and return a ParseNamespaceItem for the new RTE. * * This is much like addRangeTableEntry() except that it makes a subquery RTE. - * Note that an alias clause *must* be supplied. + * + * If the subquery does not have an alias, the auto-generated relation name in + * the returned ParseNamespaceItem will be marked as not visible, and so only + * unqualified references to the subquery columns will be allowed, and the + * relation name will not conflict with others in the pstate's namespace list. */ ParseNamespaceItem * addRangeTableEntryForSubquery(ParseState *pstate, @@ -1587,7 +1591,6 @@ addRangeTableEntryForSubquery(ParseState *pstate, bool inFromCl) { RangeTblEntry *rte = makeNode(RangeTblEntry); - char *refname = alias->aliasname; Alias *eref; int numaliases; List *coltypes, @@ -1595,6 +1598,7 @@ addRangeTableEntryForSubquery(ParseState *pstate, *colcollations; int varattno; ListCell *tlistitem; + ParseNamespaceItem *nsitem; Assert(pstate != NULL); @@ -1602,7 +1606,7 @@ addRangeTableEntryForSubquery(ParseState *pstate, rte->subquery = subquery; rte->alias = alias; - eref = copyObject(alias); + eref = alias ? copyObject(alias) : makeAlias("unnamed_subquery", NIL); numaliases = list_length(eref->colnames); /* fill in any unspecified alias columns, and extract column type info */ @@ -1634,7 +1638,7 @@ addRangeTableEntryForSubquery(ParseState *pstate, ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg("table \"%s\" has %d columns available but %d columns specified", - refname, varattno, numaliases))); + eref->aliasname, varattno, numaliases))); rte->eref = eref; @@ -1665,8 +1669,15 @@ addRangeTableEntryForSubquery(ParseState *pstate, * Build a ParseNamespaceItem, but don't add it to the pstate's namespace * list --- caller must do that if appropriate. */ - return buildNSItemFromLists(rte, list_length(pstate->p_rtable), - coltypes, coltypmods, colcollations); + nsitem = buildNSItemFromLists(rte, list_length(pstate->p_rtable), + coltypes, coltypmods, colcollations); + + /* + * Mark it visible as a relation name only if it had a user-written alias. + */ + nsitem->p_rel_visible = (alias != NULL); + + return nsitem; } /* @@ -2520,6 +2531,10 @@ addRangeTableEntryForENR(ParseState *pstate, * This is used when we have not yet done transformLockingClause, but need * to know the correct lock to take during initial opening of relations. * + * Note that refname may be NULL (for a subquery without an alias), in which + * case the relation can't be locked by name, but it might still be locked if + * a locking clause requests that all tables be locked. + * * Note: we pay no attention to whether it's FOR UPDATE vs FOR SHARE, * since the table-level lock is the same either way. */ @@ -2544,7 +2559,7 @@ isLockedRefname(ParseState *pstate, const char *refname) /* all tables used in query */ return true; } - else + else if (refname != NULL) { /* just the named tables */ ListCell *l2; |