@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $ PostgreSQL : pgsql / src / pl / plpgsql / src / pl_comp . c , v 1.143 2009 / 11 / 09 00 : 26 : 55 tgl Exp $
* $ PostgreSQL : pgsql / src / pl / plpgsql / src / pl_comp . c , v 1.144 2009 / 11 / 10 02 : 13 : 13 tgl Exp $
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
@ -1250,26 +1250,33 @@ plpgsql_parse_word(const char *word)
/* Do case conversion and word separation */
plpgsql_convert_ident ( word , cp , 1 ) ;
/*
* Do a lookup in the current namespace stack
*/
nse = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
cp [ 0 ] , NULL , NULL ,
NULL ) ;
pfree ( cp [ 0 ] ) ;
if ( nse ! = NULL )
/* No lookup if disabled */
if ( plpgsql_LookupIdentifiers )
{
switch ( nse - > itemtype )
/*
* Do a lookup in the current namespace stack
*/
nse = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
cp [ 0 ] , NULL , NULL ,
NULL ) ;
if ( nse ! = NULL )
{
case PLPGSQL_NSTYPE_VAR :
case PLPGSQL_NSTYPE_ROW :
case PLPGSQL_NSTYPE_REC :
plpgsql_yylval . datum = plpgsql_Datums [ nse - > itemno ] ;
return T_DATUM ;
switch ( nse - > itemtype )
{
case PLPGSQL_NSTYPE_VAR :
case PLPGSQL_NSTYPE_ROW :
case PLPGSQL_NSTYPE_REC :
plpgsql_yylval . wdatum . datum = plpgsql_Datums [ nse - > itemno ] ;
plpgsql_yylval . wdatum . ident = cp [ 0 ] ;
plpgsql_yylval . wdatum . quoted = ( word [ 0 ] = = ' " ' ) ;
plpgsql_yylval . wdatum . idents = NIL ;
return T_DATUM ;
default :
elog ( ERROR , " unrecognized plpgsql itemtype: %d " , nse - > itemtype ) ;
default :
elog ( ERROR , " unrecognized plpgsql itemtype: %d " ,
nse - > itemtype ) ;
}
}
}
@ -1277,6 +1284,8 @@ plpgsql_parse_word(const char *word)
* Nothing found - up to now it ' s a word without any special meaning for
* us .
*/
plpgsql_yylval . word . ident = cp [ 0 ] ;
plpgsql_yylval . word . quoted = ( word [ 0 ] = = ' " ' ) ;
return T_WORD ;
}
@ -1291,107 +1300,111 @@ plpgsql_parse_dblword(const char *word)
{
PLpgSQL_nsitem * ns ;
char * cp [ 2 ] ;
List * idents ;
int nnames ;
/* Do case conversion and word separation */
plpgsql_convert_ident ( word , cp , 2 ) ;
/*
* Do a lookup in the current namespace stack
*/
ns = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
cp [ 0 ] , cp [ 1 ] , NULL ,
& nnames ) ;
if ( ns = = NULL )
{
pfree ( cp [ 0 ] ) ;
pfree ( cp [ 1 ] ) ;
return T_DBLWORD ;
}
idents = list_make2 ( makeString ( cp [ 0 ] ) ,
makeString ( cp [ 1 ] ) ) ;
switch ( ns - > itemtype )
/* No lookup if disabled */
if ( plpgsql_LookupIdentifiers )
{
case PLPGSQL_NSTYPE_VAR :
/* Block-qualified reference to scalar variable. */
plpgsql_yylval . datum = plpgsql_Datums [ ns - > itemno ] ;
pfree ( cp [ 0 ] ) ;
pfree ( cp [ 1 ] ) ;
return T_DATUM ;
case PLPGSQL_NSTYPE_REC :
if ( nnames = = 1 )
/*
* Do a lookup in the current namespace stack
*/
ns = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
cp [ 0 ] , cp [ 1 ] , NULL ,
& nnames ) ;
if ( ns ! = NULL )
{
switch ( ns - > itemtype )
{
/*
* First word is a record name , so second word must be a field
* in this record .
*/
PLpgSQL_recfield * new ;
new = palloc ( sizeof ( PLpgSQL_recfield ) ) ;
new - > dtype = PLPGSQL_DTYPE_RECFIELD ;
new - > fieldname = pstrdup ( cp [ 1 ] ) ;
new - > recparentno = ns - > itemno ;
plpgsql_adddatum ( ( PLpgSQL_datum * ) new ) ;
case PLPGSQL_NSTYPE_VAR :
/* Block-qualified reference to scalar variable. */
plpgsql_yylval . wdatum . datum = plpgsql_Datums [ ns - > itemno ] ;
plpgsql_yylval . wdatum . ident = NULL ;
plpgsql_yylval . wdatum . quoted = false ; /* not used */
plpgsql_yylval . wdatum . idents = idents ;
return T_DATUM ;
case PLPGSQL_NSTYPE_REC :
if ( nnames = = 1 )
{
/*
* First word is a record name , so second word must be
* a field in this record .
*/
PLpgSQL_recfield * new ;
plpgsql_yylval . datum = ( PLpgSQL_datum * ) new ;
new = palloc ( sizeof ( PLpgSQL_recfield ) ) ;
new - > dtype = PLPGSQL_DTYPE_RECFIELD ;
new - > fieldname = pstrdup ( cp [ 1 ] ) ;
new - > recparentno = ns - > itemno ;
pfree ( cp [ 0 ] ) ;
pfree ( cp [ 1 ] ) ;
return T_DATUM ;
}
else
{
/* Block-qualified reference to record variable. */
plpgsql_yylval . datum = plpgsql_Datums [ ns - > itemno ] ;
pfree ( cp [ 0 ] ) ;
pfree ( cp [ 1 ] ) ;
return T_DATUM ;
}
plpgsql_adddatum ( ( PLpgSQL_datum * ) new ) ;
case PLPGSQL_NSTYPE_ROW :
if ( nnames = = 1 )
{
/*
* First word is a row name , so second word must be a field in
* this row .
*/
PLpgSQL_row * row ;
int i ;
plpgsql_yylval . wdatum . datum = ( PLpgSQL_datum * ) new ;
}
else
{
/* Block-qualified reference to record variable. */
plpgsql_yylval . wdatum . datum = plpgsql_Datums [ ns - > itemno ] ;
}
plpgsql_yylval . wdatum . ident = NULL ;
plpgsql_yylval . wdatum . quoted = false ; /* not used */
plpgsql_yylval . wdatum . idents = idents ;
return T_DATUM ;
row = ( PLpgSQL_row * ) ( plpgsql_Datums [ ns - > itemno ] ) ;
for ( i = 0 ; i < row - > nfields ; i + + )
{
if ( row - > fieldnames [ i ] & &
strcmp ( row - > fieldnames [ i ] , cp [ 1 ] ) = = 0 )
case PLPGSQL_NSTYPE_ROW :
if ( nnames = = 1 )
{
/*
* First word is a row name , so second word must be a
* field in this row .
*/
PLpgSQL_row * row ;
int i ;
row = ( PLpgSQL_row * ) ( plpgsql_Datums [ ns - > itemno ] ) ;
for ( i = 0 ; i < row - > nfields ; i + + )
{
if ( row - > fieldnames [ i ] & &
strcmp ( row - > fieldnames [ i ] , cp [ 1 ] ) = = 0 )
{
plpgsql_yylval . wdatum . datum = plpgsql_Datums [ row - > varnos [ i ] ] ;
plpgsql_yylval . wdatum . ident = NULL ;
plpgsql_yylval . wdatum . quoted = false ; /* not used */
plpgsql_yylval . wdatum . idents = idents ;
return T_DATUM ;
}
}
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_COLUMN ) ,
errmsg ( " row \" %s \" has no field \" %s \" " ,
cp [ 0 ] , cp [ 1 ] ) ) ) ;
}
else
{
plpgsql_yylval . datum = plpgsql_Datums [ row - > varnos [ i ] ] ;
pfree ( cp [ 0 ] ) ;
pfree ( cp [ 1 ] ) ;
/* Block-qualified reference to row variable. */
plpgsql_yylval . wdatum . datum = plpgsql_Datums [ ns - > itemno ] ;
plpgsql_yylval . wdatum . ident = NULL ;
plpgsql_yylval . wdatum . quoted = false ; /* not used */
plpgsql_yylval . wdatum . idents = idents ;
return T_DATUM ;
}
}
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_COLUMN ) ,
errmsg ( " row \" %s \" has no field \" %s \" " ,
cp [ 0 ] , cp [ 1 ] ) ) ) ;
}
else
{
/* Block-qualified reference to row variable. */
plpgsql_yylval . datum = plpgsql_Datums [ ns - > itemno ] ;
pfree ( cp [ 0 ] ) ;
pfree ( cp [ 1 ] ) ;
return T_DATUM ;
}
default :
break ;
default :
break ;
}
}
}
pfree ( cp [ 0 ] ) ;
pfree ( cp [ 1 ] ) ;
return T_DBL WORD ;
/* Nothing found */
plpgsql_yylval . cword . idents = idents ;
return T_CWORD ;
}
@ -1405,90 +1418,89 @@ plpgsql_parse_tripword(const char *word)
{
PLpgSQL_nsitem * ns ;
char * cp [ 3 ] ;
List * idents ;
int nnames ;
/* Do case conversion and word separation */
plpgsql_convert_ident ( word , cp , 3 ) ;
/*
* Do a lookup in the current namespace stack . Must find a qualified
* reference .
*/
ns = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
cp [ 0 ] , cp [ 1 ] , cp [ 2 ] ,
& nnames ) ;
if ( ns = = NULL | | nnames ! = 2 )
{
pfree ( cp [ 0 ] ) ;
pfree ( cp [ 1 ] ) ;
pfree ( cp [ 2 ] ) ;
return T_TRIPWORD ;
}
idents = list_make3 ( makeString ( cp [ 0 ] ) ,
makeString ( cp [ 1 ] ) ,
makeString ( cp [ 2 ] ) ) ;
switch ( ns - > itemtype )
/* No lookup if disabled */
if ( plpgsql_LookupIdentifiers )
{
case PLPGSQL_NSTYPE_REC :
{
/*
* words 1 / 2 are a record name , so third word must be a field
* in this record .
*/
PLpgSQL_recfield * new ;
new = palloc ( sizeof ( PLpgSQL_recfield ) ) ;
new - > dtype = PLPGSQL_DTYPE_RECFIELD ;
new - > fieldname = pstrdup ( cp [ 2 ] ) ;
new - > recparentno = ns - > itemno ;
plpgsql_adddatum ( ( PLpgSQL_datum * ) new ) ;
plpgsql_yylval . datum = ( PLpgSQL_datum * ) new ;
pfree ( cp [ 0 ] ) ;
pfree ( cp [ 1 ] ) ;
pfree ( cp [ 2 ] ) ;
return T_DATUM ;
}
case PLPGSQL_NSTYPE_ROW :
/*
* Do a lookup in the current namespace stack . Must find a qualified
* reference , else ignore .
*/
ns = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
cp [ 0 ] , cp [ 1 ] , cp [ 2 ] ,
& nnames ) ;
if ( ns ! = NULL & & nnames = = 2 )
{
switch ( ns - > itemtype )
{
/*
* words 1 / 2 are a row name , so third word must be a field in
* this row .
*/
PLpgSQL_row * row ;
int i ;
case PLPGSQL_NSTYPE_REC :
{
/*
* words 1 / 2 are a record name , so third word must be a
* field in this record .
*/
PLpgSQL_recfield * new ;
new = palloc ( sizeof ( PLpgSQL_recfield ) ) ;
new - > dtype = PLPGSQL_DTYPE_RECFIELD ;
new - > fieldname = pstrdup ( cp [ 2 ] ) ;
new - > recparentno = ns - > itemno ;
plpgsql_adddatum ( ( PLpgSQL_datum * ) new ) ;
plpgsql_yylval . wdatum . datum = ( PLpgSQL_datum * ) new ;
plpgsql_yylval . wdatum . ident = NULL ;
plpgsql_yylval . wdatum . quoted = false ; /* not used */
plpgsql_yylval . wdatum . idents = idents ;
return T_DATUM ;
}
row = ( PLpgSQL_row * ) ( plpgsql_Datums [ ns - > itemno ] ) ;
for ( i = 0 ; i < row - > nfields ; i + + )
case PLPGSQL_NSTYPE_ROW :
{
if ( row - > fieldnames [ i ] & &
strcmp ( row - > fieldnames [ i ] , cp [ 2 ] ) = = 0 )
/*
* words 1 / 2 are a row name , so third word must be a field
* in this row .
*/
PLpgSQL_row * row ;
int i ;
row = ( PLpgSQL_row * ) ( plpgsql_Datums [ ns - > itemno ] ) ;
for ( i = 0 ; i < row - > nfields ; i + + )
{
plpgsql_yylval . datum = plpgsql_Datums [ row - > varnos [ i ] ] ;
pfree ( cp [ 0 ] ) ;
pfree ( cp [ 1 ] ) ;
pfree ( cp [ 2 ] ) ;
return T_DATUM ;
if ( row - > fieldnames [ i ] & &
strcmp ( row - > fieldnames [ i ] , cp [ 2 ] ) = = 0 )
{
plpgsql_yylval . wdatum . datum = plpgsql_Datums [ row - > varnos [ i ] ] ;
plpgsql_yylval . wdatum . ident = NULL ;
plpgsql_yylval . wdatum . quoted = false ; /* not used */
plpgsql_yylval . wdatum . idents = idents ;
return T_DATUM ;
}
}
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_COLUMN ) ,
errmsg ( " row \" %s.%s \" has no field \" %s \" " ,
cp [ 0 ] , cp [ 1 ] , cp [ 2 ] ) ) ) ;
}
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_COLUMN ) ,
errmsg ( " row \" %s.%s \" has no field \" %s \" " ,
cp [ 0 ] , cp [ 1 ] , cp [ 2 ] ) ) ) ;
}
default :
break ;
default :
break ;
}
}
}
pfree ( cp [ 0 ] ) ;
pfree ( cp [ 1 ] ) ;
pfree ( cp [ 2 ] ) ;
return T_TRIPWORD ;
/* Nothing found */
plpgsql_yylval . cword . idents = idents ;
return T_CWORD ;
}
@ -1500,26 +1512,21 @@ plpgsql_parse_tripword(const char *word)
* - - - - - - - - - -
*/
PLpgSQL_type *
plpgsql_parse_wordtype ( const char * word )
plpgsql_parse_wordtype ( char * ident )
{
PLpgSQL_type * dtype ;
PLpgSQL_nsitem * nse ;
HeapTuple typeTup ;
char * cp [ 1 ] ;
/* Do case conversion and word separation */
plpgsql_convert_ident ( word , cp , 1 ) ;
/*
* Do a lookup in the current namespace stack
*/
nse = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
cp [ 0 ] , NULL , NULL ,
ident , NULL , NULL ,
NULL ) ;
if ( nse ! = NULL )
{
pfree ( cp [ 0 ] ) ;
switch ( nse - > itemtype )
{
case PLPGSQL_NSTYPE_VAR :
@ -1536,7 +1543,7 @@ plpgsql_parse_wordtype(const char *word)
* Word wasn ' t found in the namespace stack . Try to find a data type
* with that name , but ignore shell types and complex types .
*/
typeTup = LookupTypeName ( NULL , makeTypeName ( cp [ 0 ] ) , NULL ) ;
typeTup = LookupTypeName ( NULL , makeTypeName ( ident ) , NULL ) ;
if ( typeTup )
{
Form_pg_type typeStruct = ( Form_pg_type ) GETSTRUCT ( typeTup ) ;
@ -1545,14 +1552,12 @@ plpgsql_parse_wordtype(const char *word)
typeStruct - > typrelid ! = InvalidOid )
{
ReleaseSysCache ( typeTup ) ;
pfree ( cp [ 0 ] ) ;
return NULL ;
}
dtype = build_datatype ( typeTup , - 1 ) ;
ReleaseSysCache ( typeTup ) ;
pfree ( cp [ 0 ] ) ;
return dtype ;
}
@ -1560,134 +1565,71 @@ plpgsql_parse_wordtype(const char *word)
* Nothing found - up to now it ' s a word without any special meaning for
* us .
*/
pfree ( cp [ 0 ] ) ;
return NULL ;
}
/* ----------
* plpgsql_parse_dbl wordtype Same lookup for word . word % TYPE
* plpgsql_parse_c wordtype Same lookup for composite word% TYPE
* - - - - - - - - - -
*/
PLpgSQL_type *
plpgsql_parse_dblwordtype ( const char * word )
plpgsql_parse_cwordtype ( List * idents )
{
PLpgSQL_type * dtype = NULL ;
PLpgSQL_nsitem * nse ;
const char * fldname ;
Oid classOid ;
HeapTuple classtup = NULL ;
HeapTuple attrtup = NULL ;
HeapTuple typetup = NULL ;
Form_pg_class classStruct ;
Form_pg_attribute attrStruct ;
char * cp [ 2 ] ;
MemoryContext oldCxt ;
/* Avoid memory leaks in the long-term function context */
oldCxt = MemoryContextSwitchTo ( compile_tmp_cxt ) ;
/* Do case conversion and word separation */
plpgsql_convert_ident ( word , cp , 2 ) ;
if ( list_length ( idents ) = = 2 )
{
/*
* Do a lookup in the current namespace stack .
* We don ' t need to check number of names matched , because we will
* only consider scalar variables .
*/
nse = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
strVal ( linitial ( idents ) ) ,
strVal ( lsecond ( idents ) ) ,
NULL ,
NULL ) ;
/*
* Do a lookup in the current namespace stack .
* We don ' t need to check number of names matched , because we will only
* consider scalar variables .
*/
nse = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
cp [ 0 ] , cp [ 1 ] , NULL ,
NULL ) ;
if ( nse ! = NULL & & nse - > itemtype = = PLPGSQL_NSTYPE_VAR )
{
dtype = ( ( PLpgSQL_var * ) ( plpgsql_Datums [ nse - > itemno ] ) ) - > datatype ;
goto done ;
}
if ( nse ! = NULL & & nse - > itemtype = = PLPGSQL_NSTYPE_VAR )
/*
* First word could also be a table name
*/
classOid = RelnameGetRelid ( strVal ( linitial ( idents ) ) ) ;
if ( ! OidIsValid ( classOid ) )
goto done ;
fldname = strVal ( lsecond ( idents ) ) ;
}
else if ( list_length ( idents ) = = 3 )
{
dtype = ( ( PLpgSQL_var * ) ( plpgsql_Datums [ nse - > itemno ] ) ) - > datatype ;
goto done ;
RangeVar * relvar ;
relvar = makeRangeVar ( strVal ( linitial ( idents ) ) ,
strVal ( lsecond ( idents ) ) ,
- 1 ) ;
classOid = RangeVarGetRelid ( relvar , true ) ;
if ( ! OidIsValid ( classOid ) )
goto done ;
fldname = strVal ( lthird ( idents ) ) ;
}
/*
* First word could also be a table name
*/
classOid = RelnameGetRelid ( cp [ 0 ] ) ;
if ( ! OidIsValid ( classOid ) )
goto done ;
classtup = SearchSysCache ( RELOID ,
ObjectIdGetDatum ( classOid ) ,
0 , 0 , 0 ) ;
if ( ! HeapTupleIsValid ( classtup ) )
goto done ;
classStruct = ( Form_pg_class ) GETSTRUCT ( classtup ) ;
/*
* It must be a relation , sequence , view , or type
*/
if ( classStruct - > relkind ! = RELKIND_RELATION & &
classStruct - > relkind ! = RELKIND_SEQUENCE & &
classStruct - > relkind ! = RELKIND_VIEW & &
classStruct - > relkind ! = RELKIND_COMPOSITE_TYPE )
goto done ;
/*
* Fetch the named table field and its type
*/
attrtup = SearchSysCacheAttName ( classOid , cp [ 1 ] ) ;
if ( ! HeapTupleIsValid ( attrtup ) )
goto done ;
attrStruct = ( Form_pg_attribute ) GETSTRUCT ( attrtup ) ;
typetup = SearchSysCache ( TYPEOID ,
ObjectIdGetDatum ( attrStruct - > atttypid ) ,
0 , 0 , 0 ) ;
if ( ! HeapTupleIsValid ( typetup ) )
elog ( ERROR , " cache lookup failed for type %u " , attrStruct - > atttypid ) ;
/*
* Found that - build a compiler type struct in the caller ' s cxt and
* return it
*/
MemoryContextSwitchTo ( oldCxt ) ;
dtype = build_datatype ( typetup , attrStruct - > atttypmod ) ;
MemoryContextSwitchTo ( compile_tmp_cxt ) ;
done :
if ( HeapTupleIsValid ( classtup ) )
ReleaseSysCache ( classtup ) ;
if ( HeapTupleIsValid ( attrtup ) )
ReleaseSysCache ( attrtup ) ;
if ( HeapTupleIsValid ( typetup ) )
ReleaseSysCache ( typetup ) ;
MemoryContextSwitchTo ( oldCxt ) ;
return dtype ;
}
/* ----------
* plpgsql_parse_tripwordtype Same lookup for word . word . word % TYPE
* - - - - - - - - - -
*/
PLpgSQL_type *
plpgsql_parse_tripwordtype ( const char * word )
{
PLpgSQL_type * dtype = NULL ;
Oid classOid ;
HeapTuple classtup = NULL ;
HeapTuple attrtup = NULL ;
HeapTuple typetup = NULL ;
Form_pg_class classStruct ;
Form_pg_attribute attrStruct ;
char * cp [ 3 ] ;
RangeVar * relvar ;
MemoryContext oldCxt ;
/* Avoid memory leaks in the long-term function context */
oldCxt = MemoryContextSwitchTo ( compile_tmp_cxt ) ;
/* Do case conversion and word separation */
plpgsql_convert_ident ( word , cp , 3 ) ;
relvar = makeRangeVar ( cp [ 0 ] , cp [ 1 ] , - 1 ) ;
classOid = RangeVarGetRelid ( relvar , true ) ;
if ( ! OidIsValid ( classOid ) )
else
goto done ;
classtup = SearchSysCache ( RELOID ,
@ -1709,7 +1651,7 @@ plpgsql_parse_tripwordtype(const char *word)
/*
* Fetch the named table field and its type
*/
attrtup = SearchSysCacheAttName ( classOid , cp [ 2 ] ) ;
attrtup = SearchSysCacheAttName ( classOid , fldname ) ;
if ( ! HeapTupleIsValid ( attrtup ) )
goto done ;
attrStruct = ( Form_pg_attribute ) GETSTRUCT ( attrtup ) ;
@ -1746,64 +1688,54 @@ done:
* - - - - - - - - - -
*/
PLpgSQL_type *
plpgsql_parse_wordrowtype ( const char * word )
plpgsql_parse_wordrowtype ( char * ident )
{
PLpgSQL_type * dtype ;
Oid classOid ;
char * cp [ 1 ] ;
/* Do case conversion and word separation */
plpgsql_convert_ident ( word , cp , 1 ) ;
/* Lookup the relation */
classOid = RelnameGetRelid ( cp [ 0 ] ) ;
classOid = RelnameGetRelid ( ident ) ;
if ( ! OidIsValid ( classOid ) )
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_TABLE ) ,
errmsg ( " relation \" %s \" does not exist " , cp [ 0 ] ) ) ) ;
errmsg ( " relation \" %s \" does not exist " , ident ) ) ) ;
/* Build and return the row type struct */
dtype = plpgsql_build_datatype ( get_rel_type_id ( classOid ) , - 1 ) ;
pfree ( cp [ 0 ] ) ;
return dtype ;
return plpgsql_build_datatype ( get_rel_type_id ( classOid ) , - 1 ) ;
}
/* ----------
* plpgsql_parse_dblwordrowtype Scanner found word . word % ROWTYPE .
* plpgsql_parse_cwordrowtype Scanner found compositeword % ROWTYPE .
* So word must be a namespace qualified table name .
* - - - - - - - - - -
*/
PLpgSQL_type *
plpgsql_parse_dblwordrowtype ( const char * word )
plpgsql_parse_cwordrowtype ( List * idents )
{
PLpgSQL_type * dtype ;
Oid classOid ;
char * cp [ 2 ] ;
RangeVar * relvar ;
MemoryContext oldCxt ;
if ( list_length ( idents ) ! = 2 )
return NULL ;
/* Avoid memory leaks in long-term function context */
oldCxt = MemoryContextSwitchTo ( compile_tmp_cxt ) ;
/* Do case conversion and word separation */
plpgsql_convert_ident ( word , cp , 2 ) ;
/* Lookup the relation */
relvar = makeRangeVar ( cp [ 0 ] , cp [ 1 ] , - 1 ) ;
relvar = makeRangeVar ( strVal ( linitial ( idents ) ) ,
strVal ( lsecond ( idents ) ) ,
- 1 ) ;
classOid = RangeVarGetRelid ( relvar , true ) ;
if ( ! OidIsValid ( classOid ) )
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_TABLE ) ,
errmsg ( " relation \" %s.%s \" does not exist " , cp [ 0 ] , cp [ 1 ] ) ) ) ;
errmsg ( " relation \" %s.%s \" does not exist " ,
strVal ( linitial ( idents ) ) , strVal ( lsecond ( idents ) ) ) ) ) ;
MemoryContextSwitchTo ( oldCxt ) ;
/* Build and return the row type struct */
dtype = plpgsql_build_datatype ( get_rel_type_id ( classOid ) , - 1 ) ;
return dtype ;
return plpgsql_build_datatype ( get_rel_type_id ( classOid ) , - 1 ) ;
}
/*