@@ -143,10 +143,13 @@ typedef struct pltcl_proc_desc
143143 bool fn_readonly ; /* is function readonly? */
144144 bool lanpltrusted ; /* is it pltcl (vs. pltclu)? */
145145 pltcl_interp_desc * interp_desc ; /* interpreter to use */
146+ Oid result_typid ; /* OID of fn's result type */
146147 FmgrInfo result_in_func ; /* input function for fn's result type */
147148 Oid result_typioparam ; /* param to pass to same */
148149 bool fn_retisset ; /* true if function returns a set */
149150 bool fn_retistuple ; /* true if function returns composite */
151+ bool fn_retisdomain ; /* true if function returns domain */
152+ void * domain_info ; /* opaque cache for domain checks */
150153 int nargs ; /* number of arguments */
151154 /* these arrays have nargs entries: */
152155 FmgrInfo * arg_out_func ; /* output fns for arg types */
@@ -988,11 +991,26 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
988991 * result type is a named composite type, so it's not exactly trivial.
989992 * Maybe worth improving someday.
990993 */
991- if (get_call_result_type (fcinfo , NULL , & td ) != TYPEFUNC_COMPOSITE )
992- ereport (ERROR ,
993- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
994- errmsg ("function returning record called in context "
995- "that cannot accept type record" )));
994+ switch (get_call_result_type (fcinfo , NULL , & td ))
995+ {
996+ case TYPEFUNC_COMPOSITE :
997+ /* success */
998+ break ;
999+ case TYPEFUNC_COMPOSITE_DOMAIN :
1000+ Assert (prodesc -> fn_retisdomain );
1001+ break ;
1002+ case TYPEFUNC_RECORD :
1003+ /* failed to determine actual type of RECORD */
1004+ ereport (ERROR ,
1005+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1006+ errmsg ("function returning record called in context "
1007+ "that cannot accept type record" )));
1008+ break ;
1009+ default :
1010+ /* result type isn't composite? */
1011+ elog (ERROR , "return type must be a row type" );
1012+ break ;
1013+ }
9961014
9971015 Assert (!call_state -> ret_tupdesc );
9981016 Assert (!call_state -> attinmeta );
@@ -1490,40 +1508,41 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid,
14901508 ************************************************************/
14911509 if (!is_trigger && !is_event_trigger )
14921510 {
1493- typeTup =
1494- SearchSysCache1 ( TYPEOID ,
1495- ObjectIdGetDatum (procStruct -> prorettype ));
1511+ Oid rettype = procStruct -> prorettype ;
1512+
1513+ typeTup = SearchSysCache1 ( TYPEOID , ObjectIdGetDatum (rettype ));
14961514 if (!HeapTupleIsValid (typeTup ))
1497- elog (ERROR , "cache lookup failed for type %u" ,
1498- procStruct -> prorettype );
1515+ elog (ERROR , "cache lookup failed for type %u" , rettype );
14991516 typeStruct = (Form_pg_type ) GETSTRUCT (typeTup );
15001517
15011518 /* Disallow pseudotype result, except VOID and RECORD */
15021519 if (typeStruct -> typtype == TYPTYPE_PSEUDO )
15031520 {
1504- if (procStruct -> prorettype == VOIDOID ||
1505- procStruct -> prorettype == RECORDOID )
1521+ if (rettype == VOIDOID ||
1522+ rettype == RECORDOID )
15061523 /* okay */ ;
1507- else if (procStruct -> prorettype == TRIGGEROID ||
1508- procStruct -> prorettype == EVTTRIGGEROID )
1524+ else if (rettype == TRIGGEROID ||
1525+ rettype == EVTTRIGGEROID )
15091526 ereport (ERROR ,
15101527 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
15111528 errmsg ("trigger functions can only be called as triggers" )));
15121529 else
15131530 ereport (ERROR ,
15141531 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
15151532 errmsg ("PL/Tcl functions cannot return type %s" ,
1516- format_type_be (procStruct -> prorettype ))));
1533+ format_type_be (rettype ))));
15171534 }
15181535
1536+ prodesc -> result_typid = rettype ;
15191537 fmgr_info_cxt (typeStruct -> typinput ,
15201538 & (prodesc -> result_in_func ),
15211539 proc_cxt );
15221540 prodesc -> result_typioparam = getTypeIOParam (typeTup );
15231541
15241542 prodesc -> fn_retisset = procStruct -> proretset ;
1525- prodesc -> fn_retistuple = (procStruct -> prorettype == RECORDOID ||
1526- typeStruct -> typtype == TYPTYPE_COMPOSITE );
1543+ prodesc -> fn_retistuple = type_is_rowtype (rettype );
1544+ prodesc -> fn_retisdomain = (typeStruct -> typtype == TYPTYPE_DOMAIN );
1545+ prodesc -> domain_info = NULL ;
15271546
15281547 ReleaseSysCache (typeTup );
15291548 }
@@ -1537,21 +1556,22 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid,
15371556 proc_internal_args [0 ] = '\0' ;
15381557 for (i = 0 ; i < prodesc -> nargs ; i ++ )
15391558 {
1540- typeTup = SearchSysCache1 (TYPEOID ,
1541- ObjectIdGetDatum (procStruct -> proargtypes .values [i ]));
1559+ Oid argtype = procStruct -> proargtypes .values [i ];
1560+
1561+ typeTup = SearchSysCache1 (TYPEOID , ObjectIdGetDatum (argtype ));
15421562 if (!HeapTupleIsValid (typeTup ))
1543- elog (ERROR , "cache lookup failed for type %u" ,
1544- procStruct -> proargtypes .values [i ]);
1563+ elog (ERROR , "cache lookup failed for type %u" , argtype );
15451564 typeStruct = (Form_pg_type ) GETSTRUCT (typeTup );
15461565
1547- /* Disallow pseudotype argument */
1548- if (typeStruct -> typtype == TYPTYPE_PSEUDO )
1566+ /* Disallow pseudotype argument, except RECORD */
1567+ if (typeStruct -> typtype == TYPTYPE_PSEUDO &&
1568+ argtype != RECORDOID )
15491569 ereport (ERROR ,
15501570 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
15511571 errmsg ("PL/Tcl functions cannot accept type %s" ,
1552- format_type_be (procStruct -> proargtypes . values [ i ] ))));
1572+ format_type_be (argtype ))));
15531573
1554- if (typeStruct -> typtype == TYPTYPE_COMPOSITE )
1574+ if (type_is_rowtype ( argtype ) )
15551575 {
15561576 prodesc -> arg_is_rowtype [i ] = true;
15571577 snprintf (buf , sizeof (buf ), "__PLTcl_Tup_%d" , i + 1 );
@@ -3075,6 +3095,7 @@ static HeapTuple
30753095pltcl_build_tuple_result (Tcl_Interp * interp , Tcl_Obj * * kvObjv , int kvObjc ,
30763096 pltcl_call_state * call_state )
30773097{
3098+ HeapTuple tuple ;
30783099 TupleDesc tupdesc ;
30793100 AttInMetadata * attinmeta ;
30803101 char * * values ;
@@ -3133,7 +3154,16 @@ pltcl_build_tuple_result(Tcl_Interp *interp, Tcl_Obj **kvObjv, int kvObjc,
31333154 values [attn - 1 ] = utf_u2e (Tcl_GetString (kvObjv [i + 1 ]));
31343155 }
31353156
3136- return BuildTupleFromCStrings (attinmeta , values );
3157+ tuple = BuildTupleFromCStrings (attinmeta , values );
3158+
3159+ /* if result type is domain-over-composite, check domain constraints */
3160+ if (call_state -> prodesc -> fn_retisdomain )
3161+ domain_check (HeapTupleGetDatum (tuple ), false,
3162+ call_state -> prodesc -> result_typid ,
3163+ & call_state -> prodesc -> domain_info ,
3164+ call_state -> prodesc -> fn_cxt );
3165+
3166+ return tuple ;
31373167}
31383168
31393169/**********************************************************************
0 commit comments