@@ -1599,7 +1599,7 @@ plpgsql_parse_tripword(char *word1, char *word2, char *word3,
15991599 * plpgsql_parse_wordtype The scanner found word%TYPE. word should be
16001600 * a pre-existing variable name.
16011601 *
1602- * Returns datatype struct, or NULL if no match found for word.
1602+ * Returns datatype struct. Throws error if no match found for word.
16031603 * ----------
16041604 */
16051605PLpgSQL_type *
@@ -1623,23 +1623,24 @@ plpgsql_parse_wordtype(char *ident)
16231623 case PLPGSQL_NSTYPE_REC :
16241624 return ((PLpgSQL_rec * ) (plpgsql_Datums [nse -> itemno ]))-> datatype ;
16251625 default :
1626- return NULL ;
1626+ break ;
16271627 }
16281628 }
16291629
1630- /*
1631- * Nothing found - up to now it's a word without any special meaning for
1632- * us.
1633- */
1634- return NULL ;
1630+ /* No match, complain */
1631+ ereport ( ERROR ,
1632+ ( errcode ( ERRCODE_UNDEFINED_OBJECT ),
1633+ errmsg ( "variable \"%s\" does not exist" , ident )));
1634+ return NULL ; /* keep compiler quiet */
16351635}
16361636
16371637
16381638/* ----------
16391639 * plpgsql_parse_cwordtype Same lookup for compositeword%TYPE
16401640 *
16411641 * Here, we allow either a block-qualified variable name, or a reference
1642- * to a column of some table.
1642+ * to a column of some table. (If we must throw error, we assume that the
1643+ * latter case was intended.)
16431644 * ----------
16441645 */
16451646PLpgSQL_type *
@@ -1648,12 +1649,11 @@ plpgsql_parse_cwordtype(List *idents)
16481649 PLpgSQL_type * dtype = NULL ;
16491650 PLpgSQL_nsitem * nse ;
16501651 int nnames ;
1651- const char * fldname ;
1652+ RangeVar * relvar = NULL ;
1653+ const char * fldname = NULL ;
16521654 Oid classOid ;
1653- HeapTuple classtup = NULL ;
16541655 HeapTuple attrtup = NULL ;
16551656 HeapTuple typetup = NULL ;
1656- Form_pg_class classStruct ;
16571657 Form_pg_attribute attrStruct ;
16581658 MemoryContext oldCxt ;
16591659
@@ -1688,57 +1688,39 @@ plpgsql_parse_cwordtype(List *idents)
16881688 /*
16891689 * First word could also be a table name
16901690 */
1691- classOid = RelnameGetRelid ( strVal ( linitial ( idents )));
1692- if (! OidIsValid ( classOid ))
1693- goto done ;
1691+ relvar = makeRangeVar ( NULL ,
1692+ strVal ( linitial ( idents )),
1693+ -1 ) ;
16941694 fldname = strVal (lsecond (idents ));
16951695 }
1696- else if ( list_length ( idents ) == 3 )
1696+ else
16971697 {
1698- RangeVar * relvar ;
1699-
17001698 /*
17011699 * We could check for a block-qualified reference to a field of a
17021700 * record variable, but %TYPE is documented as applying to variables,
17031701 * not fields of variables. Things would get rather ambiguous if we
17041702 * allowed either interpretation.
17051703 */
1706- relvar = makeRangeVar (strVal (linitial (idents )),
1707- strVal (lsecond (idents )),
1708- -1 );
1709- /* Can't lock relation - we might not have privileges. */
1710- classOid = RangeVarGetRelid (relvar , NoLock , true);
1711- if (!OidIsValid (classOid ))
1712- goto done ;
1713- fldname = strVal (lthird (idents ));
1714- }
1715- else
1716- goto done ;
1704+ List * rvnames ;
17171705
1718- classtup = SearchSysCache1 (RELOID , ObjectIdGetDatum (classOid ));
1719- if (!HeapTupleIsValid (classtup ))
1720- goto done ;
1721- classStruct = (Form_pg_class ) GETSTRUCT (classtup );
1706+ Assert (list_length (idents ) > 2 );
1707+ rvnames = list_delete_last (list_copy (idents ));
1708+ relvar = makeRangeVarFromNameList (rvnames );
1709+ fldname = strVal (llast (idents ));
1710+ }
17221711
1723- /*
1724- * It must be a relation, sequence, view, materialized view, composite
1725- * type, or foreign table
1726- */
1727- if (classStruct -> relkind != RELKIND_RELATION &&
1728- classStruct -> relkind != RELKIND_SEQUENCE &&
1729- classStruct -> relkind != RELKIND_VIEW &&
1730- classStruct -> relkind != RELKIND_MATVIEW &&
1731- classStruct -> relkind != RELKIND_COMPOSITE_TYPE &&
1732- classStruct -> relkind != RELKIND_FOREIGN_TABLE &&
1733- classStruct -> relkind != RELKIND_PARTITIONED_TABLE )
1734- goto done ;
1712+ /* Look up relation name. Can't lock it - we might not have privileges. */
1713+ classOid = RangeVarGetRelid (relvar , NoLock , false);
17351714
17361715 /*
17371716 * Fetch the named table field and its type
17381717 */
17391718 attrtup = SearchSysCacheAttName (classOid , fldname );
17401719 if (!HeapTupleIsValid (attrtup ))
1741- goto done ;
1720+ ereport (ERROR ,
1721+ (errcode (ERRCODE_UNDEFINED_COLUMN ),
1722+ errmsg ("column \"%s\" of relation \"%s\" does not exist" ,
1723+ fldname , relvar -> relname )));
17421724 attrStruct = (Form_pg_attribute ) GETSTRUCT (attrtup );
17431725
17441726 typetup = SearchSysCache1 (TYPEOID ,
@@ -1759,8 +1741,6 @@ plpgsql_parse_cwordtype(List *idents)
17591741 MemoryContextSwitchTo (plpgsql_compile_tmp_cxt );
17601742
17611743done :
1762- if (HeapTupleIsValid (classtup ))
1763- ReleaseSysCache (classtup );
17641744 if (HeapTupleIsValid (attrtup ))
17651745 ReleaseSysCache (attrtup );
17661746 if (HeapTupleIsValid (typetup ))
@@ -1824,16 +1804,12 @@ plpgsql_parse_cwordrowtype(List *idents)
18241804 * As above, this is a relation lookup but could be a type lookup if we
18251805 * weren't being backwards-compatible about error wording.
18261806 */
1827- if (list_length (idents ) != 2 )
1828- return NULL ;
18291807
18301808 /* Avoid memory leaks in long-term function context */
18311809 oldCxt = MemoryContextSwitchTo (plpgsql_compile_tmp_cxt );
18321810
18331811 /* Look up relation name. Can't lock it - we might not have privileges. */
1834- relvar = makeRangeVar (strVal (linitial (idents )),
1835- strVal (lsecond (idents )),
1836- -1 );
1812+ relvar = makeRangeVarFromNameList (idents );
18371813 classOid = RangeVarGetRelid (relvar , NoLock , false);
18381814
18391815 /* Some relkinds lack type OIDs */
@@ -1842,7 +1818,7 @@ plpgsql_parse_cwordrowtype(List *idents)
18421818 ereport (ERROR ,
18431819 (errcode (ERRCODE_WRONG_OBJECT_TYPE ),
18441820 errmsg ("relation \"%s\" does not have a composite type" ,
1845- strVal ( lsecond ( idents )) )));
1821+ relvar -> relname )));
18461822
18471823 MemoryContextSwitchTo (oldCxt );
18481824
0 commit comments