@ -1596,8 +1596,8 @@ plpgsql_parse_tripword(char *word1, char *word2, char *word3,
/* ----------
/* ----------
* plpgsql_parse_wordtype The scanner found word % TYPE . word can be
* plpgsql_parse_wordtype The scanner found word % TYPE . word should be
* a variable name or a basetyp e.
* a pre - existing variable nam e.
*
*
* Returns datatype struct , or NULL if no match found for word .
* Returns datatype struct , or NULL if no match found for word .
* - - - - - - - - - -
* - - - - - - - - - -
@ -1605,10 +1605,7 @@ plpgsql_parse_tripword(char *word1, char *word2, char *word3,
PLpgSQL_type *
PLpgSQL_type *
plpgsql_parse_wordtype ( char * ident )
plpgsql_parse_wordtype ( char * ident )
{
{
PLpgSQL_type * dtype ;
PLpgSQL_nsitem * nse ;
PLpgSQL_nsitem * nse ;
TypeName * typeName ;
HeapTuple typeTup ;
/*
/*
* Do a lookup in the current namespace stack
* Do a lookup in the current namespace stack
@ -1623,39 +1620,13 @@ plpgsql_parse_wordtype(char *ident)
{
{
case PLPGSQL_NSTYPE_VAR :
case PLPGSQL_NSTYPE_VAR :
return ( ( PLpgSQL_var * ) ( plpgsql_Datums [ nse - > itemno ] ) ) - > datatype ;
return ( ( PLpgSQL_var * ) ( plpgsql_Datums [ nse - > itemno ] ) ) - > datatype ;
case PLPGSQL_NSTYPE_REC :
/* XXX perhaps allow REC/ROW here? */
return ( ( PLpgSQL_rec * ) ( plpgsql_Datums [ nse - > itemno ] ) ) - > datatype ;
default :
default :
return NULL ;
return NULL ;
}
}
}
}
/*
* Word wasn ' t found in the namespace stack . Try to find a data type with
* that name , but ignore shell types and complex types .
*/
typeName = makeTypeName ( ident ) ;
typeTup = LookupTypeName ( NULL , typeName , NULL , false ) ;
if ( typeTup )
{
Form_pg_type typeStruct = ( Form_pg_type ) GETSTRUCT ( typeTup ) ;
if ( ! typeStruct - > typisdefined | |
typeStruct - > typrelid ! = InvalidOid )
{
ReleaseSysCache ( typeTup ) ;
return NULL ;
}
dtype = build_datatype ( typeTup , - 1 ,
plpgsql_curr_compile - > fn_input_collation ,
typeName ) ;
ReleaseSysCache ( typeTup ) ;
return dtype ;
}
/*
/*
* Nothing found - up to now it ' s a word without any special meaning for
* Nothing found - up to now it ' s a word without any special meaning for
* us .
* us .
@ -1666,6 +1637,9 @@ plpgsql_parse_wordtype(char *ident)
/* ----------
/* ----------
* plpgsql_parse_cwordtype Same lookup for compositeword % TYPE
* plpgsql_parse_cwordtype Same lookup for compositeword % TYPE
*
* Here , we allow either a block - qualified variable name , or a reference
* to a column of some table .
* - - - - - - - - - -
* - - - - - - - - - -
*/
*/
PLpgSQL_type *
PLpgSQL_type *
@ -1673,6 +1647,7 @@ plpgsql_parse_cwordtype(List *idents)
{
{
PLpgSQL_type * dtype = NULL ;
PLpgSQL_type * dtype = NULL ;
PLpgSQL_nsitem * nse ;
PLpgSQL_nsitem * nse ;
int nnames ;
const char * fldname ;
const char * fldname ;
Oid classOid ;
Oid classOid ;
HeapTuple classtup = NULL ;
HeapTuple classtup = NULL ;
@ -1688,21 +1663,27 @@ plpgsql_parse_cwordtype(List *idents)
if ( list_length ( idents ) = = 2 )
if ( list_length ( idents ) = = 2 )
{
{
/*
/*
* Do a lookup in the current namespace stack . We don ' t need to check
* Do a lookup in the current namespace stack
* number of names matched , because we will only consider scalar
* variables .
*/
*/
nse = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
nse = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
strVal ( linitial ( idents ) ) ,
strVal ( linitial ( idents ) ) ,
strVal ( lsecond ( idents ) ) ,
strVal ( lsecond ( idents ) ) ,
NULL ,
NULL ,
NULL ) ;
& nnames ) ;
if ( nse ! = NULL & & nse - > itemtype = = PLPGSQL_NSTYPE_VAR )
if ( nse ! = NULL & & nse - > itemtype = = PLPGSQL_NSTYPE_VAR )
{
{
/* Block-qualified reference to scalar variable. */
dtype = ( ( PLpgSQL_var * ) ( plpgsql_Datums [ nse - > itemno ] ) ) - > datatype ;
dtype = ( ( PLpgSQL_var * ) ( plpgsql_Datums [ nse - > itemno ] ) ) - > datatype ;
goto done ;
goto done ;
}
}
else if ( nse ! = NULL & & nse - > itemtype = = PLPGSQL_NSTYPE_REC & &
nnames = = 2 )
{
/* Block-qualified reference to record variable. */
dtype = ( ( PLpgSQL_rec * ) ( plpgsql_Datums [ nse - > itemno ] ) ) - > datatype ;
goto done ;
}
/*
/*
* First word could also be a table name
* First word could also be a table name
@ -1716,6 +1697,12 @@ plpgsql_parse_cwordtype(List *idents)
{
{
RangeVar * relvar ;
RangeVar * relvar ;
/*
* We could check for a block - qualified reference to a field of a
* record variable , but % TYPE is documented as applying to variables ,
* not fields of variables . Things would get rather ambiguous if we
* allowed either interpretation .
*/
relvar = makeRangeVar ( strVal ( linitial ( idents ) ) ,
relvar = makeRangeVar ( strVal ( linitial ( idents ) ) ,
strVal ( lsecond ( idents ) ) ,
strVal ( lsecond ( idents ) ) ,
- 1 ) ;
- 1 ) ;