@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* 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 */
/* Do case conversion and word separation */
plpgsql_convert_ident ( word , cp , 1 ) ;
plpgsql_convert_ident ( word , cp , 1 ) ;
/*
/* No lookup if disabled */
* Do a lookup in the current namespace stack
if ( plpgsql_LookupIdentifiers )
*/
nse = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
cp [ 0 ] , NULL , NULL ,
NULL ) ;
pfree ( cp [ 0 ] ) ;
if ( nse ! = NULL )
{
{
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 :
switch ( nse - > itemtype )
case PLPGSQL_NSTYPE_ROW :
{
case PLPGSQL_NSTYPE_REC :
case PLPGSQL_NSTYPE_VAR :
plpgsql_yylval . datum = plpgsql_Datums [ nse - > itemno ] ;
case PLPGSQL_NSTYPE_ROW :
return T_DATUM ;
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 :
default :
elog ( ERROR , " unrecognized plpgsql itemtype: %d " , nse - > itemtype ) ;
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
* Nothing found - up to now it ' s a word without any special meaning for
* us .
* us .
*/
*/
plpgsql_yylval . word . ident = cp [ 0 ] ;
plpgsql_yylval . word . quoted = ( word [ 0 ] = = ' " ' ) ;
return T_WORD ;
return T_WORD ;
}
}
@ -1291,107 +1300,111 @@ plpgsql_parse_dblword(const char *word)
{
{
PLpgSQL_nsitem * ns ;
PLpgSQL_nsitem * ns ;
char * cp [ 2 ] ;
char * cp [ 2 ] ;
List * idents ;
int nnames ;
int nnames ;
/* Do case conversion and word separation */
/* Do case conversion and word separation */
plpgsql_convert_ident ( word , cp , 2 ) ;
plpgsql_convert_ident ( word , cp , 2 ) ;
/*
idents = list_make2 ( makeString ( cp [ 0 ] ) ,
* Do a lookup in the current namespace stack
makeString ( cp [ 1 ] ) ) ;
*/
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 ;
}
switch ( ns - > itemtype )
/* No lookup if disabled */
if ( plpgsql_LookupIdentifiers )
{
{
case PLPGSQL_NSTYPE_VAR :
/*
/* Block-qualified reference to scalar variable. */
* Do a lookup in the current namespace stack
plpgsql_yylval . datum = plpgsql_Datums [ ns - > itemno ] ;
*/
pfree ( cp [ 0 ] ) ;
ns = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
pfree ( cp [ 1 ] ) ;
cp [ 0 ] , cp [ 1 ] , NULL ,
return T_DATUM ;
& nnames ) ;
if ( ns ! = NULL )
case PLPGSQL_NSTYPE_REC :
{
if ( nnames = = 1 )
switch ( ns - > itemtype )
{
{
/*
case PLPGSQL_NSTYPE_VAR :
* First word is a record name , so second word must be a field
/* Block-qualified reference to scalar variable. */
* in this record .
plpgsql_yylval . wdatum . datum = plpgsql_Datums [ ns - > itemno ] ;
*/
plpgsql_yylval . wdatum . ident = NULL ;
PLpgSQL_recfield * new ;
plpgsql_yylval . wdatum . quoted = false ; /* not used */
plpgsql_yylval . wdatum . idents = idents ;
new = palloc ( sizeof ( PLpgSQL_recfield ) ) ;
return T_DATUM ;
new - > dtype = PLPGSQL_DTYPE_RECFIELD ;
new - > fieldname = pstrdup ( cp [ 1 ] ) ;
case PLPGSQL_NSTYPE_REC :
new - > recparentno = ns - > itemno ;
if ( nnames = = 1 )
{
plpgsql_adddatum ( ( PLpgSQL_datum * ) new ) ;
/*
* 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 ] ) ;
plpgsql_adddatum ( ( PLpgSQL_datum * ) new ) ;
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 ;
}
case PLPGSQL_NSTYPE_ROW :
plpgsql_yylval . wdatum . datum = ( PLpgSQL_datum * ) new ;
if ( nnames = = 1 )
}
{
else
/*
{
* First word is a row name , so second word must be a field in
/* Block-qualified reference to record variable. */
* this row .
plpgsql_yylval . wdatum . datum = plpgsql_Datums [ ns - > itemno ] ;
*/
}
PLpgSQL_row * row ;
plpgsql_yylval . wdatum . ident = NULL ;
int i ;
plpgsql_yylval . wdatum . quoted = false ; /* not used */
plpgsql_yylval . wdatum . idents = idents ;
return T_DATUM ;
row = ( PLpgSQL_row * ) ( plpgsql_Datums [ ns - > itemno ] ) ;
case PLPGSQL_NSTYPE_ROW :
for ( i = 0 ; i < row - > nfields ; i + + )
if ( nnames = = 1 )
{
{
if ( row - > fieldnames [ i ] & &
/*
strcmp ( row - > fieldnames [ i ] , cp [ 1 ] ) = = 0 )
* 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 ] ] ;
/* Block-qualified reference to row variable. */
pfree ( cp [ 0 ] ) ;
plpgsql_yylval . wdatum . datum = plpgsql_Datums [ ns - > itemno ] ;
pfree ( cp [ 1 ] ) ;
plpgsql_yylval . wdatum . ident = NULL ;
plpgsql_yylval . wdatum . quoted = false ; /* not used */
plpgsql_yylval . wdatum . idents = idents ;
return T_DATUM ;
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 :
default :
break ;
break ;
}
}
}
}
pfree ( cp [ 0 ] ) ;
/* Nothing found */
pfree ( cp [ 1 ] ) ;
plpgsql_yylval . cword . idents = idents ;
return T_DBL WORD ;
return T_CWORD ;
}
}
@ -1405,90 +1418,89 @@ plpgsql_parse_tripword(const char *word)
{
{
PLpgSQL_nsitem * ns ;
PLpgSQL_nsitem * ns ;
char * cp [ 3 ] ;
char * cp [ 3 ] ;
List * idents ;
int nnames ;
int nnames ;
/* Do case conversion and word separation */
/* Do case conversion and word separation */
plpgsql_convert_ident ( word , cp , 3 ) ;
plpgsql_convert_ident ( word , cp , 3 ) ;
/*
idents = list_make3 ( makeString ( cp [ 0 ] ) ,
* Do a lookup in the current namespace stack . Must find a qualified
makeString ( cp [ 1 ] ) ,
* reference .
makeString ( cp [ 2 ] ) ) ;
*/
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 ;
}
switch ( ns - > itemtype )
/* No lookup if disabled */
if ( plpgsql_LookupIdentifiers )
{
{
case PLPGSQL_NSTYPE_REC :
/*
{
* Do a lookup in the current namespace stack . Must find a qualified
/*
* reference , else ignore .
* words 1 / 2 are a record name , so third word must be a field
*/
* in this record .
ns = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
*/
cp [ 0 ] , cp [ 1 ] , cp [ 2 ] ,
PLpgSQL_recfield * new ;
& nnames ) ;
if ( ns ! = NULL & & nnames = = 2 )
new = palloc ( sizeof ( PLpgSQL_recfield ) ) ;
{
new - > dtype = PLPGSQL_DTYPE_RECFIELD ;
switch ( ns - > itemtype )
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 :
{
{
/*
case PLPGSQL_NSTYPE_REC :
* words 1 / 2 are a row name , so third word must be a field in
{
* this row .
/*
*/
* words 1 / 2 are a record name , so third word must be a
PLpgSQL_row * row ;
* field in this record .
int i ;
*/
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 ] ) ;
case PLPGSQL_NSTYPE_ROW :
for ( i = 0 ; i < row - > nfields ; i + + )
{
{
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 ] ] ;
if ( row - > fieldnames [ i ] & &
strcmp ( row - > fieldnames [ i ] , cp [ 2 ] ) = = 0 )
pfree ( cp [ 0 ] ) ;
{
pfree ( cp [ 1 ] ) ;
plpgsql_yylval . wdatum . datum = plpgsql_Datums [ row - > varnos [ i ] ] ;
pfree ( cp [ 2 ] ) ;
plpgsql_yylval . wdatum . ident = NULL ;
plpgsql_yylval . wdatum . quoted = false ; /* not used */
return T_DATUM ;
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 :
default :
break ;
break ;
}
}
}
}
pfree ( cp [ 0 ] ) ;
/* Nothing found */
pfree ( cp [ 1 ] ) ;
plpgsql_yylval . cword . idents = idents ;
pfree ( cp [ 2 ] ) ;
return T_CWORD ;
return T_TRIPWORD ;
}
}
@ -1500,26 +1512,21 @@ plpgsql_parse_tripword(const char *word)
* - - - - - - - - - -
* - - - - - - - - - -
*/
*/
PLpgSQL_type *
PLpgSQL_type *
plpgsql_parse_wordtype ( const char * word )
plpgsql_parse_wordtype ( char * ident )
{
{
PLpgSQL_type * dtype ;
PLpgSQL_type * dtype ;
PLpgSQL_nsitem * nse ;
PLpgSQL_nsitem * nse ;
HeapTuple typeTup ;
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
* Do a lookup in the current namespace stack
*/
*/
nse = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
nse = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
cp [ 0 ] , NULL , NULL ,
ident , NULL , NULL ,
NULL ) ;
NULL ) ;
if ( nse ! = NULL )
if ( nse ! = NULL )
{
{
pfree ( cp [ 0 ] ) ;
switch ( nse - > itemtype )
switch ( nse - > itemtype )
{
{
case PLPGSQL_NSTYPE_VAR :
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
* Word wasn ' t found in the namespace stack . Try to find a data type
* with that name , but ignore shell types and complex types .
* 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 )
if ( typeTup )
{
{
Form_pg_type typeStruct = ( Form_pg_type ) GETSTRUCT ( typeTup ) ;
Form_pg_type typeStruct = ( Form_pg_type ) GETSTRUCT ( typeTup ) ;
@ -1545,14 +1552,12 @@ plpgsql_parse_wordtype(const char *word)
typeStruct - > typrelid ! = InvalidOid )
typeStruct - > typrelid ! = InvalidOid )
{
{
ReleaseSysCache ( typeTup ) ;
ReleaseSysCache ( typeTup ) ;
pfree ( cp [ 0 ] ) ;
return NULL ;
return NULL ;
}
}
dtype = build_datatype ( typeTup , - 1 ) ;
dtype = build_datatype ( typeTup , - 1 ) ;
ReleaseSysCache ( typeTup ) ;
ReleaseSysCache ( typeTup ) ;
pfree ( cp [ 0 ] ) ;
return dtype ;
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
* Nothing found - up to now it ' s a word without any special meaning for
* us .
* us .
*/
*/
pfree ( cp [ 0 ] ) ;
return NULL ;
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_type *
plpgsql_parse_dblwordtype ( const char * word )
plpgsql_parse_cwordtype ( List * idents )
{
{
PLpgSQL_type * dtype = NULL ;
PLpgSQL_type * dtype = NULL ;
PLpgSQL_nsitem * nse ;
PLpgSQL_nsitem * nse ;
const char * fldname ;
Oid classOid ;
Oid classOid ;
HeapTuple classtup = NULL ;
HeapTuple classtup = NULL ;
HeapTuple attrtup = NULL ;
HeapTuple attrtup = NULL ;
HeapTuple typetup = NULL ;
HeapTuple typetup = NULL ;
Form_pg_class classStruct ;
Form_pg_class classStruct ;
Form_pg_attribute attrStruct ;
Form_pg_attribute attrStruct ;
char * cp [ 2 ] ;
MemoryContext oldCxt ;
MemoryContext oldCxt ;
/* Avoid memory leaks in the long-term function context */
/* Avoid memory leaks in the long-term function context */
oldCxt = MemoryContextSwitchTo ( compile_tmp_cxt ) ;
oldCxt = MemoryContextSwitchTo ( compile_tmp_cxt ) ;
/* Do case conversion and word separation */
if ( list_length ( idents ) = = 2 )
plpgsql_convert_ident ( word , cp , 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 ) ;
/*
if ( nse ! = NULL & & nse - > itemtype = = PLPGSQL_NSTYPE_VAR )
* Do a lookup in the current namespace stack .
{
* We don ' t need to check number of names matched , because we will only
dtype = ( ( PLpgSQL_var * ) ( plpgsql_Datums [ nse - > itemno ] ) ) - > datatype ;
* consider scalar variables .
goto done ;
*/
}
nse = plpgsql_ns_lookup ( plpgsql_ns_top ( ) , false ,
cp [ 0 ] , cp [ 1 ] , NULL ,
NULL ) ;
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 ;
RangeVar * relvar ;
goto done ;
relvar = makeRangeVar ( strVal ( linitial ( idents ) ) ,
strVal ( lsecond ( idents ) ) ,
- 1 ) ;
classOid = RangeVarGetRelid ( relvar , true ) ;
if ( ! OidIsValid ( classOid ) )
goto done ;
fldname = strVal ( lthird ( idents ) ) ;
}
}
else
/*
* 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 ) )
goto done ;
goto done ;
classtup = SearchSysCache ( RELOID ,
classtup = SearchSysCache ( RELOID ,
@ -1709,7 +1651,7 @@ plpgsql_parse_tripwordtype(const char *word)
/*
/*
* Fetch the named table field and its type
* Fetch the named table field and its type
*/
*/
attrtup = SearchSysCacheAttName ( classOid , cp [ 2 ] ) ;
attrtup = SearchSysCacheAttName ( classOid , fldname ) ;
if ( ! HeapTupleIsValid ( attrtup ) )
if ( ! HeapTupleIsValid ( attrtup ) )
goto done ;
goto done ;
attrStruct = ( Form_pg_attribute ) GETSTRUCT ( attrtup ) ;
attrStruct = ( Form_pg_attribute ) GETSTRUCT ( attrtup ) ;
@ -1746,64 +1688,54 @@ done:
* - - - - - - - - - -
* - - - - - - - - - -
*/
*/
PLpgSQL_type *
PLpgSQL_type *
plpgsql_parse_wordrowtype ( const char * word )
plpgsql_parse_wordrowtype ( char * ident )
{
{
PLpgSQL_type * dtype ;
Oid classOid ;
Oid classOid ;
char * cp [ 1 ] ;
/* Do case conversion and word separation */
plpgsql_convert_ident ( word , cp , 1 ) ;
/* Lookup the relation */
/* Lookup the relation */
classOid = RelnameGetRelid ( cp [ 0 ] ) ;
classOid = RelnameGetRelid ( ident ) ;
if ( ! OidIsValid ( classOid ) )
if ( ! OidIsValid ( classOid ) )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_TABLE ) ,
( 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 */
/* Build and return the row type struct */
dtype = plpgsql_build_datatype ( get_rel_type_id ( classOid ) , - 1 ) ;
return plpgsql_build_datatype ( get_rel_type_id ( classOid ) , - 1 ) ;
pfree ( cp [ 0 ] ) ;
return dtype ;
}
}
/* ----------
/* ----------
* plpgsql_parse_dblwordrowtype Scanner found word . word % ROWTYPE .
* plpgsql_parse_cwordrowtype Scanner found compositeword % ROWTYPE .
* So word must be a namespace qualified table name .
* So word must be a namespace qualified table name .
* - - - - - - - - - -
* - - - - - - - - - -
*/
*/
PLpgSQL_type *
PLpgSQL_type *
plpgsql_parse_dblwordrowtype ( const char * word )
plpgsql_parse_cwordrowtype ( List * idents )
{
{
PLpgSQL_type * dtype ;
Oid classOid ;
Oid classOid ;
char * cp [ 2 ] ;
RangeVar * relvar ;
RangeVar * relvar ;
MemoryContext oldCxt ;
MemoryContext oldCxt ;
if ( list_length ( idents ) ! = 2 )
return NULL ;
/* Avoid memory leaks in long-term function context */
/* Avoid memory leaks in long-term function context */
oldCxt = MemoryContextSwitchTo ( compile_tmp_cxt ) ;
oldCxt = MemoryContextSwitchTo ( compile_tmp_cxt ) ;
/* Do case conversion and word separation */
plpgsql_convert_ident ( word , cp , 2 ) ;
/* Lookup the relation */
/* Lookup the relation */
relvar = makeRangeVar ( cp [ 0 ] , cp [ 1 ] , - 1 ) ;
relvar = makeRangeVar ( strVal ( linitial ( idents ) ) ,
strVal ( lsecond ( idents ) ) ,
- 1 ) ;
classOid = RangeVarGetRelid ( relvar , true ) ;
classOid = RangeVarGetRelid ( relvar , true ) ;
if ( ! OidIsValid ( classOid ) )
if ( ! OidIsValid ( classOid ) )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_TABLE ) ,
( 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 ) ;
MemoryContextSwitchTo ( oldCxt ) ;
/* Build and return the row type struct */
/* Build and return the row type struct */
dtype = plpgsql_build_datatype ( get_rel_type_id ( classOid ) , - 1 ) ;
return plpgsql_build_datatype ( get_rel_type_id ( classOid ) , - 1 ) ;
return dtype ;
}
}
/*
/*