@@ -1596,19 +1596,16 @@ plpgsql_parse_tripword(char *word1, char *word2, char *word3,
1596
1596
1597
1597
1598
1598
/* ----------
1599
- * plpgsql_parse_wordtype The scanner found word%TYPE. word can be
1600
- * a variable name or a basetype .
1599
+ * plpgsql_parse_wordtype The scanner found word%TYPE. word should be
1600
+ * a pre-existing variable name.
1601
1601
*
1602
1602
* Returns datatype struct, or NULL if no match found for word.
1603
1603
* ----------
1604
1604
*/
1605
1605
PLpgSQL_type *
1606
1606
plpgsql_parse_wordtype (char * ident )
1607
1607
{
1608
- PLpgSQL_type * dtype ;
1609
1608
PLpgSQL_nsitem * nse ;
1610
- TypeName * typeName ;
1611
- HeapTuple typeTup ;
1612
1609
1613
1610
/*
1614
1611
* Do a lookup in the current namespace stack
@@ -1623,39 +1620,13 @@ plpgsql_parse_wordtype(char *ident)
1623
1620
{
1624
1621
case PLPGSQL_NSTYPE_VAR :
1625
1622
return ((PLpgSQL_var * ) (plpgsql_Datums [nse -> itemno ]))-> datatype ;
1626
-
1627
- /* XXX perhaps allow REC/ROW here? */
1628
-
1623
+ case PLPGSQL_NSTYPE_REC :
1624
+ return ((PLpgSQL_rec * ) (plpgsql_Datums [nse -> itemno ]))-> datatype ;
1629
1625
default :
1630
1626
return NULL ;
1631
1627
}
1632
1628
}
1633
1629
1634
- /*
1635
- * Word wasn't found in the namespace stack. Try to find a data type with
1636
- * that name, but ignore shell types and complex types.
1637
- */
1638
- typeName = makeTypeName (ident );
1639
- typeTup = LookupTypeName (NULL , typeName , NULL , false);
1640
- if (typeTup )
1641
- {
1642
- Form_pg_type typeStruct = (Form_pg_type ) GETSTRUCT (typeTup );
1643
-
1644
- if (!typeStruct -> typisdefined ||
1645
- typeStruct -> typrelid != InvalidOid )
1646
- {
1647
- ReleaseSysCache (typeTup );
1648
- return NULL ;
1649
- }
1650
-
1651
- dtype = build_datatype (typeTup , -1 ,
1652
- plpgsql_curr_compile -> fn_input_collation ,
1653
- typeName );
1654
-
1655
- ReleaseSysCache (typeTup );
1656
- return dtype ;
1657
- }
1658
-
1659
1630
/*
1660
1631
* Nothing found - up to now it's a word without any special meaning for
1661
1632
* us.
@@ -1666,13 +1637,17 @@ plpgsql_parse_wordtype(char *ident)
1666
1637
1667
1638
/* ----------
1668
1639
* plpgsql_parse_cwordtype Same lookup for compositeword%TYPE
1640
+ *
1641
+ * Here, we allow either a block-qualified variable name, or a reference
1642
+ * to a column of some table.
1669
1643
* ----------
1670
1644
*/
1671
1645
PLpgSQL_type *
1672
1646
plpgsql_parse_cwordtype (List * idents )
1673
1647
{
1674
1648
PLpgSQL_type * dtype = NULL ;
1675
1649
PLpgSQL_nsitem * nse ;
1650
+ int nnames ;
1676
1651
const char * fldname ;
1677
1652
Oid classOid ;
1678
1653
HeapTuple classtup = NULL ;
@@ -1688,21 +1663,27 @@ plpgsql_parse_cwordtype(List *idents)
1688
1663
if (list_length (idents ) == 2 )
1689
1664
{
1690
1665
/*
1691
- * Do a lookup in the current namespace stack. We don't need to check
1692
- * number of names matched, because we will only consider scalar
1693
- * variables.
1666
+ * Do a lookup in the current namespace stack
1694
1667
*/
1695
1668
nse = plpgsql_ns_lookup (plpgsql_ns_top (), false,
1696
1669
strVal (linitial (idents )),
1697
1670
strVal (lsecond (idents )),
1698
1671
NULL ,
1699
- NULL );
1672
+ & nnames );
1700
1673
1701
1674
if (nse != NULL && nse -> itemtype == PLPGSQL_NSTYPE_VAR )
1702
1675
{
1676
+ /* Block-qualified reference to scalar variable. */
1703
1677
dtype = ((PLpgSQL_var * ) (plpgsql_Datums [nse -> itemno ]))-> datatype ;
1704
1678
goto done ;
1705
1679
}
1680
+ else if (nse != NULL && nse -> itemtype == PLPGSQL_NSTYPE_REC &&
1681
+ nnames == 2 )
1682
+ {
1683
+ /* Block-qualified reference to record variable. */
1684
+ dtype = ((PLpgSQL_rec * ) (plpgsql_Datums [nse -> itemno ]))-> datatype ;
1685
+ goto done ;
1686
+ }
1706
1687
1707
1688
/*
1708
1689
* First word could also be a table name
@@ -1716,6 +1697,12 @@ plpgsql_parse_cwordtype(List *idents)
1716
1697
{
1717
1698
RangeVar * relvar ;
1718
1699
1700
+ /*
1701
+ * We could check for a block-qualified reference to a field of a
1702
+ * record variable, but %TYPE is documented as applying to variables,
1703
+ * not fields of variables. Things would get rather ambiguous if we
1704
+ * allowed either interpretation.
1705
+ */
1719
1706
relvar = makeRangeVar (strVal (linitial (idents )),
1720
1707
strVal (lsecond (idents )),
1721
1708
-1 );
0 commit comments