3333 * ENHANCEMENTS, OR MODIFICATIONS.
3434 *
3535 * IDENTIFICATION
36- * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.46 2004/07/12 14:31:04 momjian Exp $
36+ * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.47 2004/07/21 20:45:54 momjian Exp $
3737 *
3838 **********************************************************************/
3939
@@ -889,7 +889,8 @@ plperl_func_handler(PG_FUNCTION_ARGS)
889889
890890if (prodesc -> fn_retisset && SRF_IS_FIRSTCALL ())
891891 {
892- if (prodesc -> fn_retistuple )g_column_keys = newAV ();
892+ if (prodesc -> fn_retistuple )
893+ g_column_keys = newAV ();
893894if (SvTYPE (perlret )!= SVt_RV )
894895elog (ERROR ,"plperl: set-returning function must return reference" );
895896}
@@ -910,7 +911,13 @@ plperl_func_handler(PG_FUNCTION_ARGS)
910911fcinfo -> isnull = true;
911912}
912913
913- if (prodesc -> fn_retistuple )
914+ if (prodesc -> fn_retisset && !(perlret && SvTYPE (SvRV (perlret ))== SVt_PVAV ))
915+ elog (ERROR ,"plperl: set-returning function must return reference to array" );
916+
917+ if (prodesc -> fn_retistuple && perlret && SvTYPE (perlret )!= SVt_RV )
918+ elog (ERROR ,"plperl: composite-returning function must return a reference" );
919+
920+ if (prodesc -> fn_retistuple && fcinfo -> resultinfo )/* set of tuples */
914921{
915922/* SRF support */
916923HV * ret_hv ;
@@ -932,9 +939,6 @@ plperl_func_handler(PG_FUNCTION_ARGS)
932939errmsg ("returning a composite type is not allowed in this context" ),
933940errhint ("This function is intended for use in the FROM clause." )));
934941
935- if (SvTYPE (perlret )!= SVt_RV )
936- elog (ERROR ,"plperl: composite-returning function must return a reference" );
937-
938942
939943isset = plperl_is_set (perlret );
940944
@@ -1042,7 +1046,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
10421046SRF_RETURN_DONE (funcctx );
10431047}
10441048}
1045- else if (prodesc -> fn_retisset )
1049+ else if (prodesc -> fn_retisset )/* set of non-tuples */
10461050{
10471051FuncCallContext * funcctx ;
10481052
@@ -1054,8 +1058,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
10541058funcctx = SRF_FIRSTCALL_INIT ();
10551059oldcontext = MemoryContextSwitchTo (funcctx -> multi_call_memory_ctx );
10561060
1057- if (SvTYPE (SvRV (perlret ))!= SVt_PVAV )elog (ERROR ,"plperl: set-returning function must return reference to array" );
1058- else funcctx -> max_calls = av_len ((AV * )SvRV (perlret ))+ 1 ;
1061+ funcctx -> max_calls = av_len ((AV * )SvRV (perlret ))+ 1 ;
10591062}
10601063
10611064funcctx = SRF_PERCALL_SETUP ();
@@ -1085,16 +1088,53 @@ plperl_func_handler(PG_FUNCTION_ARGS)
10851088}
10861089else
10871090{
1088- if (perlret )SvREFCNT_dec (perlret );
1091+ if (perlret )
1092+ SvREFCNT_dec (perlret );
10891093SRF_RETURN_DONE (funcctx );
10901094}
10911095 }
1092- else if (!fcinfo -> isnull )
1096+ else if (!fcinfo -> isnull )/* non-null singleton */
10931097{
1098+
1099+
1100+ if (prodesc -> fn_retistuple )/* singleton perl hash to Datum */
1101+ {
1102+ TupleDesc td = lookup_rowtype_tupdesc (prodesc -> ret_oid ,(int32 )- 1 );
1103+ HV * perlhash = (HV * )SvRV (perlret );
1104+ int i ;
1105+ char * * values ;
1106+ char * key ,* val ;
1107+ AttInMetadata * attinmeta ;
1108+ HeapTuple tup ;
1109+
1110+ if (!td )
1111+ ereport (ERROR ,
1112+ (errcode (ERRCODE_SYNTAX_ERROR ),
1113+ errmsg ("no TupleDesc info available" )));
1114+
1115+ values = (char * * )palloc (td -> natts * sizeof (char * ));
1116+ for (i = 0 ;i < td -> natts ;i ++ )
1117+ {
1118+
1119+ key = SPI_fname (td ,i + 1 );
1120+ val = plperl_get_elem (perlhash ,key );
1121+ if (val )
1122+ values [i ]= val ;
1123+ else
1124+ values [i ]= NULL ;
1125+ }
1126+ attinmeta = TupleDescGetAttInMetadata (td );
1127+ tup = BuildTupleFromCStrings (attinmeta ,values );
1128+ retval = HeapTupleGetDatum (tup );
1129+
1130+ }
1131+ else /* perl string to Datum */
1132+
10941133retval = FunctionCall3 (& prodesc -> result_in_func ,
10951134PointerGetDatum (SvPV (perlret ,PL_na )),
10961135ObjectIdGetDatum (prodesc -> result_typioparam ),
10971136Int32GetDatum (-1 ));
1137+
10981138}
10991139
11001140SvREFCNT_dec (perlret );
@@ -1341,12 +1381,16 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
13411381}
13421382}
13431383
1344- prodesc -> fn_retisset = procStruct -> proretset ;/*true, if function returns set*/
1384+ prodesc -> fn_retisset = procStruct -> proretset ;/* true, if function
1385+ * returns set */
13451386
13461387if (typeStruct -> typtype == 'c' || procStruct -> prorettype == RECORDOID )
13471388{
13481389prodesc -> fn_retistuple = true;
1349- prodesc -> ret_oid = typeStruct -> typrelid ;
1390+ prodesc -> ret_oid =
1391+ procStruct -> prorettype == RECORDOID ?
1392+ typeStruct -> typrelid :
1393+ procStruct -> prorettype ;
13501394}
13511395
13521396perm_fmgr_info (typeStruct -> typinput ,& (prodesc -> result_in_func ));