@@ -1577,7 +1577,11 @@ addRangeTableEntryForRelation(ParseState *pstate,
1577
1577
* Then, construct and return a ParseNamespaceItem for the new RTE.
1578
1578
*
1579
1579
* This is much like addRangeTableEntry() except that it makes a subquery RTE.
1580
- * Note that an alias clause *must* be supplied.
1580
+ *
1581
+ * If the subquery does not have an alias, the auto-generated relation name in
1582
+ * the returned ParseNamespaceItem will be marked as not visible, and so only
1583
+ * unqualified references to the subquery columns will be allowed, and the
1584
+ * relation name will not conflict with others in the pstate's namespace list.
1581
1585
*/
1582
1586
ParseNamespaceItem *
1583
1587
addRangeTableEntryForSubquery (ParseState * pstate ,
@@ -1587,22 +1591,22 @@ addRangeTableEntryForSubquery(ParseState *pstate,
1587
1591
bool inFromCl )
1588
1592
{
1589
1593
RangeTblEntry * rte = makeNode (RangeTblEntry );
1590
- char * refname = alias -> aliasname ;
1591
1594
Alias * eref ;
1592
1595
int numaliases ;
1593
1596
List * coltypes ,
1594
1597
* coltypmods ,
1595
1598
* colcollations ;
1596
1599
int varattno ;
1597
1600
ListCell * tlistitem ;
1601
+ ParseNamespaceItem * nsitem ;
1598
1602
1599
1603
Assert (pstate != NULL );
1600
1604
1601
1605
rte -> rtekind = RTE_SUBQUERY ;
1602
1606
rte -> subquery = subquery ;
1603
1607
rte -> alias = alias ;
1604
1608
1605
- eref = copyObject (alias );
1609
+ eref = alias ? copyObject (alias ) : makeAlias ( "unnamed_subquery" , NIL );
1606
1610
numaliases = list_length (eref -> colnames );
1607
1611
1608
1612
/* fill in any unspecified alias columns, and extract column type info */
@@ -1634,7 +1638,7 @@ addRangeTableEntryForSubquery(ParseState *pstate,
1634
1638
ereport (ERROR ,
1635
1639
(errcode (ERRCODE_INVALID_COLUMN_REFERENCE ),
1636
1640
errmsg ("table \"%s\" has %d columns available but %d columns specified" ,
1637
- refname , varattno , numaliases )));
1641
+ eref -> aliasname , varattno , numaliases )));
1638
1642
1639
1643
rte -> eref = eref ;
1640
1644
@@ -1665,8 +1669,15 @@ addRangeTableEntryForSubquery(ParseState *pstate,
1665
1669
* Build a ParseNamespaceItem, but don't add it to the pstate's namespace
1666
1670
* list --- caller must do that if appropriate.
1667
1671
*/
1668
- return buildNSItemFromLists (rte , list_length (pstate -> p_rtable ),
1669
- coltypes , coltypmods , colcollations );
1672
+ nsitem = buildNSItemFromLists (rte , list_length (pstate -> p_rtable ),
1673
+ coltypes , coltypmods , colcollations );
1674
+
1675
+ /*
1676
+ * Mark it visible as a relation name only if it had a user-written alias.
1677
+ */
1678
+ nsitem -> p_rel_visible = (alias != NULL );
1679
+
1680
+ return nsitem ;
1670
1681
}
1671
1682
1672
1683
/*
@@ -2520,6 +2531,10 @@ addRangeTableEntryForENR(ParseState *pstate,
2520
2531
* This is used when we have not yet done transformLockingClause, but need
2521
2532
* to know the correct lock to take during initial opening of relations.
2522
2533
*
2534
+ * Note that refname may be NULL (for a subquery without an alias), in which
2535
+ * case the relation can't be locked by name, but it might still be locked if
2536
+ * a locking clause requests that all tables be locked.
2537
+ *
2523
2538
* Note: we pay no attention to whether it's FOR UPDATE vs FOR SHARE,
2524
2539
* since the table-level lock is the same either way.
2525
2540
*/
@@ -2544,7 +2559,7 @@ isLockedRefname(ParseState *pstate, const char *refname)
2544
2559
/* all tables used in query */
2545
2560
return true;
2546
2561
}
2547
- else
2562
+ else if ( refname != NULL )
2548
2563
{
2549
2564
/* just the named tables */
2550
2565
ListCell * l2 ;
0 commit comments