@@ -179,8 +179,11 @@ typedef struct plperl_call_data
179
179
{
180
180
plperl_proc_desc * prodesc ;
181
181
FunctionCallInfo fcinfo ;
182
+ /* remaining fields are used only in a function returning set: */
182
183
Tuplestorestate * tuple_store ;
183
184
TupleDesc ret_tdesc ;
185
+ Oid cdomain_oid ; /* 0 unless returning domain-over-composite */
186
+ void * cdomain_info ;
184
187
MemoryContext tmp_cxt ;
185
188
} plperl_call_data ;
186
189
@@ -1356,27 +1359,44 @@ plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod,
1356
1359
/* handle a hashref */
1357
1360
Datum ret ;
1358
1361
TupleDesc td ;
1362
+ bool isdomain ;
1359
1363
1360
1364
if (!type_is_rowtype (typid ))
1361
1365
ereport (ERROR ,
1362
1366
(errcode (ERRCODE_DATATYPE_MISMATCH ),
1363
1367
errmsg ("cannot convert Perl hash to non-composite type %s" ,
1364
1368
format_type_be (typid ))));
1365
1369
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 )
1368
1372
{
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 )
1372
1387
ereport (ERROR ,
1373
1388
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1374
1389
errmsg ("function returning record called in context "
1375
1390
"that cannot accept type record" )));
1391
+ Assert (td );
1392
+ isdomain = (funcclass == TYPEFUNC_COMPOSITE_DOMAIN );
1376
1393
}
1377
1394
1378
1395
ret = plperl_hash_to_datum (sv , td );
1379
1396
1397
+ if (isdomain )
1398
+ domain_check (ret , false, typid , NULL , NULL );
1399
+
1380
1400
/* Release on the result of get_call_result_type is harmless */
1381
1401
ReleaseTupleDesc (td );
1382
1402
@@ -2401,8 +2421,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
2401
2421
{
2402
2422
/* Check context before allowing the call to go through */
2403
2423
if (!rsi || !IsA (rsi , ReturnSetInfo ) ||
2404
- (rsi -> allowedModes & SFRM_Materialize ) == 0 ||
2405
- rsi -> expectedDesc == NULL )
2424
+ (rsi -> allowedModes & SFRM_Materialize ) == 0 )
2406
2425
ereport (ERROR ,
2407
2426
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
2408
2427
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)
2809
2828
************************************************************/
2810
2829
if (!is_trigger && !is_event_trigger )
2811
2830
{
2812
- typeTup =
2813
- SearchSysCache1 ( TYPEOID ,
2814
- ObjectIdGetDatum (procStruct -> prorettype ));
2831
+ Oid rettype = procStruct -> prorettype ;
2832
+
2833
+ typeTup = SearchSysCache1 ( TYPEOID , ObjectIdGetDatum (rettype ));
2815
2834
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 );
2818
2836
typeStruct = (Form_pg_type ) GETSTRUCT (typeTup );
2819
2837
2820
2838
/* Disallow pseudotype result, except VOID or RECORD */
2821
2839
if (typeStruct -> typtype == TYPTYPE_PSEUDO )
2822
2840
{
2823
- if (procStruct -> prorettype == VOIDOID ||
2824
- procStruct -> prorettype == RECORDOID )
2841
+ if (rettype == VOIDOID ||
2842
+ rettype == RECORDOID )
2825
2843
/* okay */ ;
2826
- else if (procStruct -> prorettype == TRIGGEROID ||
2827
- procStruct -> prorettype == EVTTRIGGEROID )
2844
+ else if (rettype == TRIGGEROID ||
2845
+ rettype == EVTTRIGGEROID )
2828
2846
ereport (ERROR ,
2829
2847
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
2830
2848
errmsg ("trigger functions can only be called "
@@ -2833,13 +2851,12 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
2833
2851
ereport (ERROR ,
2834
2852
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
2835
2853
errmsg ("PL/Perl functions cannot return type %s" ,
2836
- format_type_be (procStruct -> prorettype ))));
2854
+ format_type_be (rettype ))));
2837
2855
}
2838
2856
2839
- prodesc -> result_oid = procStruct -> prorettype ;
2857
+ prodesc -> result_oid = rettype ;
2840
2858
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 );
2843
2860
2844
2861
prodesc -> fn_retisarray =
2845
2862
(typeStruct -> typlen == -1 && typeStruct -> typelem );
@@ -2862,23 +2879,22 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
2862
2879
2863
2880
for (i = 0 ; i < prodesc -> nargs ; i ++ )
2864
2881
{
2865
- typeTup = SearchSysCache1 (TYPEOID ,
2866
- ObjectIdGetDatum (procStruct -> proargtypes .values [i ]));
2882
+ Oid argtype = procStruct -> proargtypes .values [i ];
2883
+
2884
+ typeTup = SearchSysCache1 (TYPEOID , ObjectIdGetDatum (argtype ));
2867
2885
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 );
2870
2887
typeStruct = (Form_pg_type ) GETSTRUCT (typeTup );
2871
2888
2872
- /* Disallow pseudotype argument */
2889
+ /* Disallow pseudotype argument, except RECORD */
2873
2890
if (typeStruct -> typtype == TYPTYPE_PSEUDO &&
2874
- procStruct -> proargtypes . values [ i ] != RECORDOID )
2891
+ argtype != RECORDOID )
2875
2892
ereport (ERROR ,
2876
2893
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
2877
2894
errmsg ("PL/Perl functions cannot accept type %s" ,
2878
- format_type_be (procStruct -> proargtypes . values [ i ] ))));
2895
+ format_type_be (argtype ))));
2879
2896
2880
- if (typeStruct -> typtype == TYPTYPE_COMPOSITE ||
2881
- procStruct -> proargtypes .values [i ] == RECORDOID )
2897
+ if (type_is_rowtype (argtype ))
2882
2898
prodesc -> arg_is_rowtype [i ] = true;
2883
2899
else
2884
2900
{
@@ -2888,9 +2904,9 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
2888
2904
proc_cxt );
2889
2905
}
2890
2906
2891
- /* Identify array attributes */
2907
+ /* Identify array-type arguments */
2892
2908
if (typeStruct -> typelem != 0 && typeStruct -> typlen == -1 )
2893
- prodesc -> arg_arraytype [i ] = procStruct -> proargtypes . values [ i ] ;
2909
+ prodesc -> arg_arraytype [i ] = argtype ;
2894
2910
else
2895
2911
prodesc -> arg_arraytype [i ] = InvalidOid ;
2896
2912
@@ -3249,11 +3265,25 @@ plperl_return_next_internal(SV *sv)
3249
3265
3250
3266
/*
3251
3267
* 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
3253
3269
* tuplestore to hold the result rows.
3254
3270
*/
3255
3271
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
+ }
3257
3287
else
3258
3288
{
3259
3289
tupdesc = rsi -> expectedDesc ;
@@ -3304,6 +3334,13 @@ plperl_return_next_internal(SV *sv)
3304
3334
3305
3335
tuple = plperl_build_tuple_result ((HV * ) SvRV (sv ),
3306
3336
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
+
3307
3344
tuplestore_puttuple (current_call_data -> tuple_store , tuple );
3308
3345
}
3309
3346
else
0 commit comments