@@ -179,8 +179,11 @@ typedef struct plperl_call_data
179179{
180180 plperl_proc_desc * prodesc ;
181181 FunctionCallInfo fcinfo ;
182+ /* remaining fields are used only in a function returning set: */
182183 Tuplestorestate * tuple_store ;
183184 TupleDesc ret_tdesc ;
185+ Oid cdomain_oid ; /* 0 unless returning domain-over-composite */
186+ void * cdomain_info ;
184187 MemoryContext tmp_cxt ;
185188} plperl_call_data ;
186189
@@ -1356,27 +1359,44 @@ plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod,
13561359 /* handle a hashref */
13571360 Datum ret ;
13581361 TupleDesc td ;
1362+ bool isdomain ;
13591363
13601364 if (!type_is_rowtype (typid ))
13611365 ereport (ERROR ,
13621366 (errcode (ERRCODE_DATATYPE_MISMATCH ),
13631367 errmsg ("cannot convert Perl hash to non-composite type %s" ,
13641368 format_type_be (typid ))));
13651369
1366- td = lookup_rowtype_tupdesc_noerror (typid , typmod , true);
1367- if (td = = NULL )
1370+ td = lookup_rowtype_tupdesc_domain (typid , typmod , true);
1371+ if (td ! = NULL )
13681372 {
1369- /* Try to look it up based on our result type */
1370- if (fcinfo == NULL ||
1371- get_call_result_type (fcinfo , NULL , & td ) != TYPEFUNC_COMPOSITE )
1373+ /* Did we look through a domain? */
1374+ isdomain = (typid != td -> tdtypeid );
1375+ }
1376+ else
1377+ {
1378+ /* Must be RECORD, try to resolve based on call info */
1379+ TypeFuncClass funcclass ;
1380+
1381+ if (fcinfo )
1382+ funcclass = get_call_result_type (fcinfo , & typid , & td );
1383+ else
1384+ funcclass = TYPEFUNC_OTHER ;
1385+ if (funcclass != TYPEFUNC_COMPOSITE &&
1386+ funcclass != TYPEFUNC_COMPOSITE_DOMAIN )
13721387 ereport (ERROR ,
13731388 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
13741389 errmsg ("function returning record called in context "
13751390 "that cannot accept type record" )));
1391+ Assert (td );
1392+ isdomain = (funcclass == TYPEFUNC_COMPOSITE_DOMAIN );
13761393 }
13771394
13781395 ret = plperl_hash_to_datum (sv , td );
13791396
1397+ if (isdomain )
1398+ domain_check (ret , false, typid , NULL , NULL );
1399+
13801400 /* Release on the result of get_call_result_type is harmless */
13811401 ReleaseTupleDesc (td );
13821402
@@ -2401,8 +2421,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
24012421 {
24022422 /* Check context before allowing the call to go through */
24032423 if (!rsi || !IsA (rsi , ReturnSetInfo ) ||
2404- (rsi -> allowedModes & SFRM_Materialize ) == 0 ||
2405- rsi -> expectedDesc == NULL )
2424+ (rsi -> allowedModes & SFRM_Materialize ) == 0 )
24062425 ereport (ERROR ,
24072426 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
24082427 errmsg ("set-valued function called in context that "
@@ -2809,22 +2828,21 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
28092828 ************************************************************/
28102829 if (!is_trigger && !is_event_trigger )
28112830 {
2812- typeTup =
2813- SearchSysCache1 ( TYPEOID ,
2814- ObjectIdGetDatum (procStruct -> prorettype ));
2831+ Oid rettype = procStruct -> prorettype ;
2832+
2833+ typeTup = SearchSysCache1 ( TYPEOID , ObjectIdGetDatum (rettype ));
28152834 if (!HeapTupleIsValid (typeTup ))
2816- elog (ERROR , "cache lookup failed for type %u" ,
2817- procStruct -> prorettype );
2835+ elog (ERROR , "cache lookup failed for type %u" , rettype );
28182836 typeStruct = (Form_pg_type ) GETSTRUCT (typeTup );
28192837
28202838 /* Disallow pseudotype result, except VOID or RECORD */
28212839 if (typeStruct -> typtype == TYPTYPE_PSEUDO )
28222840 {
2823- if (procStruct -> prorettype == VOIDOID ||
2824- procStruct -> prorettype == RECORDOID )
2841+ if (rettype == VOIDOID ||
2842+ rettype == RECORDOID )
28252843 /* okay */ ;
2826- else if (procStruct -> prorettype == TRIGGEROID ||
2827- procStruct -> prorettype == EVTTRIGGEROID )
2844+ else if (rettype == TRIGGEROID ||
2845+ rettype == EVTTRIGGEROID )
28282846 ereport (ERROR ,
28292847 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
28302848 errmsg ("trigger functions can only be called "
@@ -2833,13 +2851,12 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
28332851 ereport (ERROR ,
28342852 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
28352853 errmsg ("PL/Perl functions cannot return type %s" ,
2836- format_type_be (procStruct -> prorettype ))));
2854+ format_type_be (rettype ))));
28372855 }
28382856
2839- prodesc -> result_oid = procStruct -> prorettype ;
2857+ prodesc -> result_oid = rettype ;
28402858 prodesc -> fn_retisset = procStruct -> proretset ;
2841- prodesc -> fn_retistuple = (procStruct -> prorettype == RECORDOID ||
2842- typeStruct -> typtype == TYPTYPE_COMPOSITE );
2859+ prodesc -> fn_retistuple = type_is_rowtype (rettype );
28432860
28442861 prodesc -> fn_retisarray =
28452862 (typeStruct -> typlen == -1 && typeStruct -> typelem );
@@ -2862,23 +2879,22 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
28622879
28632880 for (i = 0 ; i < prodesc -> nargs ; i ++ )
28642881 {
2865- typeTup = SearchSysCache1 (TYPEOID ,
2866- ObjectIdGetDatum (procStruct -> proargtypes .values [i ]));
2882+ Oid argtype = procStruct -> proargtypes .values [i ];
2883+
2884+ typeTup = SearchSysCache1 (TYPEOID , ObjectIdGetDatum (argtype ));
28672885 if (!HeapTupleIsValid (typeTup ))
2868- elog (ERROR , "cache lookup failed for type %u" ,
2869- procStruct -> proargtypes .values [i ]);
2886+ elog (ERROR , "cache lookup failed for type %u" , argtype );
28702887 typeStruct = (Form_pg_type ) GETSTRUCT (typeTup );
28712888
2872- /* Disallow pseudotype argument */
2889+ /* Disallow pseudotype argument, except RECORD */
28732890 if (typeStruct -> typtype == TYPTYPE_PSEUDO &&
2874- procStruct -> proargtypes . values [ i ] != RECORDOID )
2891+ argtype != RECORDOID )
28752892 ereport (ERROR ,
28762893 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
28772894 errmsg ("PL/Perl functions cannot accept type %s" ,
2878- format_type_be (procStruct -> proargtypes . values [ i ] ))));
2895+ format_type_be (argtype ))));
28792896
2880- if (typeStruct -> typtype == TYPTYPE_COMPOSITE ||
2881- procStruct -> proargtypes .values [i ] == RECORDOID )
2897+ if (type_is_rowtype (argtype ))
28822898 prodesc -> arg_is_rowtype [i ] = true;
28832899 else
28842900 {
@@ -2888,9 +2904,9 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
28882904 proc_cxt );
28892905 }
28902906
2891- /* Identify array attributes */
2907+ /* Identify array-type arguments */
28922908 if (typeStruct -> typelem != 0 && typeStruct -> typlen == -1 )
2893- prodesc -> arg_arraytype [i ] = procStruct -> proargtypes . values [ i ] ;
2909+ prodesc -> arg_arraytype [i ] = argtype ;
28942910 else
28952911 prodesc -> arg_arraytype [i ] = InvalidOid ;
28962912
@@ -3249,11 +3265,25 @@ plperl_return_next_internal(SV *sv)
32493265
32503266 /*
32513267 * This is the first call to return_next in the current PL/Perl
3252- * function call, so identify the output tuple descriptor and create a
3268+ * function call, so identify the output tuple type and create a
32533269 * tuplestore to hold the result rows.
32543270 */
32553271 if (prodesc -> fn_retistuple )
3256- (void ) get_call_result_type (fcinfo , NULL , & tupdesc );
3272+ {
3273+ TypeFuncClass funcclass ;
3274+ Oid typid ;
3275+
3276+ funcclass = get_call_result_type (fcinfo , & typid , & tupdesc );
3277+ if (funcclass != TYPEFUNC_COMPOSITE &&
3278+ funcclass != TYPEFUNC_COMPOSITE_DOMAIN )
3279+ ereport (ERROR ,
3280+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
3281+ errmsg ("function returning record called in context "
3282+ "that cannot accept type record" )));
3283+ /* if domain-over-composite, remember the domain's type OID */
3284+ if (funcclass == TYPEFUNC_COMPOSITE_DOMAIN )
3285+ current_call_data -> cdomain_oid = typid ;
3286+ }
32573287 else
32583288 {
32593289 tupdesc = rsi -> expectedDesc ;
@@ -3304,6 +3334,13 @@ plperl_return_next_internal(SV *sv)
33043334
33053335 tuple = plperl_build_tuple_result ((HV * ) SvRV (sv ),
33063336 current_call_data -> ret_tdesc );
3337+
3338+ if (OidIsValid (current_call_data -> cdomain_oid ))
3339+ domain_check (HeapTupleGetDatum (tuple ), false,
3340+ current_call_data -> cdomain_oid ,
3341+ & current_call_data -> cdomain_info ,
3342+ rsi -> econtext -> ecxt_per_query_memory );
3343+
33073344 tuplestore_puttuple (current_call_data -> tuple_store , tuple );
33083345 }
33093346 else
0 commit comments