33 * procedural language
44 *
55 * IDENTIFICATION
6- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.44 2002/08/08 01:36:04 tgl Exp $
6+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.45 2002/08/12 14:25:07 tgl Exp $
77 *
88 * This software is copyrighted by Jan Wieck - Hamburg.
99 *
@@ -85,6 +85,9 @@ intplpgsql_DumpExecTree = 0;
8585PLpgSQL_function * plpgsql_curr_compile ;
8686
8787
88+ static PLpgSQL_row * build_rowtype (Oid classOid );
89+
90+
8891/*
8992 * This routine is a crock, and so is everyplace that calls it. The problem
9093 * is that the compiled form of a plpgsql function is allocated permanently
@@ -234,7 +237,9 @@ plpgsql_compile(Oid fn_oid, int functype)
234237 */
235238for (i = 0 ;i < procStruct -> pronargs ;i ++ )
236239{
237- char buf [256 ];
240+ char buf [32 ];
241+
242+ sprintf (buf ,"$%d" ,i + 1 );/* name for variable */
238243
239244/*
240245 * Get the parameters type
@@ -258,13 +263,7 @@ plpgsql_compile(Oid fn_oid, int functype)
258263 * For tuple type parameters, we set up a record of
259264 * that type
260265 */
261- sprintf (buf ,"%s%%rowtype" ,NameStr (typeStruct -> typname ));
262- if (plpgsql_parse_wordrowtype (buf )!= T_ROW )
263- elog (ERROR ,"cannot get tuple struct of argument %d" ,
264- i + 1 );
265-
266- row = plpgsql_yylval .row ;
267- sprintf (buf ,"$%d" ,i + 1 );
266+ row = build_rowtype (typeStruct -> typrelid );
268267
269268row -> refname = strdup (buf );
270269
@@ -284,7 +283,6 @@ plpgsql_compile(Oid fn_oid, int functype)
284283var -> datatype = malloc (sizeof (PLpgSQL_type ));
285284memset (var -> datatype ,0 ,sizeof (PLpgSQL_type ));
286285
287- sprintf (buf ,"$%d" ,i + 1 );
288286var -> dtype = PLPGSQL_DTYPE_VAR ;
289287var -> refname = strdup (buf );
290288var -> lineno = 0 ;
@@ -1097,15 +1095,6 @@ int
10971095plpgsql_parse_wordrowtype (char * word )
10981096{
10991097Oid classOid ;
1100- HeapTuple classtup ;
1101- Form_pg_class classStruct ;
1102- HeapTuple typetup ;
1103- Form_pg_type typeStruct ;
1104- HeapTuple attrtup ;
1105- Form_pg_attribute attrStruct ;
1106- PLpgSQL_row * row ;
1107- PLpgSQL_var * var ;
1108- char * attname ;
11091098char * cp [2 ];
11101099int i ;
11111100
@@ -1116,25 +1105,51 @@ plpgsql_parse_wordrowtype(char *word)
11161105word [i ]= '.' ;
11171106plpgsql_convert_ident (word ,cp ,2 );
11181107word [i ]= '%' ;
1108+
1109+ /* Lookup the relation */
1110+ classOid = RelnameGetRelid (cp [0 ]);
1111+ if (!OidIsValid (classOid ))
1112+ elog (ERROR ,"%s: no such class" ,cp [0 ]);
1113+
1114+ /*
1115+ * Build and return the complete row definition
1116+ */
1117+ plpgsql_yylval .row = build_rowtype (classOid );
1118+
1119+ pfree (cp [0 ]);
11191120pfree (cp [1 ]);
11201121
1122+ return T_ROW ;
1123+ }
1124+
1125+ /*
1126+ * Build a rowtype data structure given the pg_class OID.
1127+ */
1128+ static PLpgSQL_row *
1129+ build_rowtype (Oid classOid )
1130+ {
1131+ PLpgSQL_row * row ;
1132+ HeapTuple classtup ;
1133+ Form_pg_class classStruct ;
1134+ const char * relname ;
1135+ int i ;
1136+
11211137/*
11221138 * Fetch the pg_class tuple.
11231139 */
1124- classOid = RelnameGetRelid (cp [0 ]);
1125- if (!OidIsValid (classOid ))
1126- elog (ERROR ,"%s: no such class" ,cp [0 ]);
11271140classtup = SearchSysCache (RELOID ,
11281141ObjectIdGetDatum (classOid ),
112911420 ,0 ,0 );
11301143if (!HeapTupleIsValid (classtup ))
1131- elog (ERROR ,"%s: no such class " ,cp [ 0 ] );
1144+ elog (ERROR ,"cache lookup failed for relation %u " ,classOid );
11321145classStruct = (Form_pg_class )GETSTRUCT (classtup );
1146+ relname = NameStr (classStruct -> relname );
1147+
11331148/* accept relation, sequence, or view pg_class entries */
11341149if (classStruct -> relkind != RELKIND_RELATION &&
11351150classStruct -> relkind != RELKIND_SEQUENCE &&
11361151classStruct -> relkind != RELKIND_VIEW )
1137- elog (ERROR ,"%s isn't a table" ,cp [ 0 ] );
1152+ elog (ERROR ,"%s isn't a table" ,relname );
11381153
11391154/*
11401155 * Create a row datum entry and all the required variables that it
@@ -1151,6 +1166,13 @@ plpgsql_parse_wordrowtype(char *word)
11511166
11521167for (i = 0 ;i < row -> nfields ;i ++ )
11531168{
1169+ HeapTuple attrtup ;
1170+ Form_pg_attribute attrStruct ;
1171+ HeapTuple typetup ;
1172+ Form_pg_type typeStruct ;
1173+ const char * attname ;
1174+ PLpgSQL_var * var ;
1175+
11541176/*
11551177 * Get the attribute and it's type
11561178 */
@@ -1160,17 +1182,17 @@ plpgsql_parse_wordrowtype(char *word)
116011820 ,0 );
11611183if (!HeapTupleIsValid (attrtup ))
11621184elog (ERROR ,"cache lookup for attribute %d of class %s failed" ,
1163- i + 1 ,cp [ 0 ] );
1185+ i + 1 ,relname );
11641186attrStruct = (Form_pg_attribute )GETSTRUCT (attrtup );
11651187
1166- attname = pstrdup ( NameStr (attrStruct -> attname ) );
1188+ attname = NameStr (attrStruct -> attname );
11671189
11681190typetup = SearchSysCache (TYPEOID ,
11691191ObjectIdGetDatum (attrStruct -> atttypid ),
117011920 ,0 ,0 );
11711193if (!HeapTupleIsValid (typetup ))
11721194elog (ERROR ,"cache lookup for type %u of %s.%s failed" ,
1173- attrStruct -> atttypid ,cp [ 0 ] ,attname );
1195+ attrStruct -> atttypid ,relname ,attname );
11741196typeStruct = (Form_pg_type )GETSTRUCT (typetup );
11751197
11761198/*
@@ -1186,8 +1208,8 @@ plpgsql_parse_wordrowtype(char *word)
11861208var = malloc (sizeof (PLpgSQL_var ));
11871209memset (var ,0 ,sizeof (PLpgSQL_var ));
11881210var -> dtype = PLPGSQL_DTYPE_VAR ;
1189- var -> refname = malloc (strlen (cp [ 0 ] )+ strlen (attname )+ 2 );
1190- strcpy (var -> refname ,cp [ 0 ] );
1211+ var -> refname = malloc (strlen (relname )+ strlen (attname )+ 2 );
1212+ strcpy (var -> refname ,relname );
11911213strcat (var -> refname ,"." );
11921214strcat (var -> refname ,attname );
11931215var -> datatype = malloc (sizeof (PLpgSQL_type ));
@@ -1205,26 +1227,21 @@ plpgsql_parse_wordrowtype(char *word)
12051227var -> isnull = true;
12061228var -> freeval = false;
12071229
1208- ReleaseSysCache (typetup );
1209- ReleaseSysCache (attrtup );
1210-
12111230plpgsql_adddatum ((PLpgSQL_datum * )var );
12121231
12131232/*
12141233 * Add the variable to the row.
12151234 */
12161235row -> fieldnames [i ]= strdup (attname );
12171236row -> varnos [i ]= var -> varno ;
1237+
1238+ ReleaseSysCache (typetup );
1239+ ReleaseSysCache (attrtup );
12181240}
12191241
12201242ReleaseSysCache (classtup );
12211243
1222- /*
1223- * Return the complete row definition
1224- */
1225- plpgsql_yylval .row = row ;
1226-
1227- return T_ROW ;
1244+ return row ;
12281245}
12291246
12301247