@@ -143,10 +143,13 @@ typedef struct pltcl_proc_desc
143
143
bool fn_readonly ; /* is function readonly? */
144
144
bool lanpltrusted ; /* is it pltcl (vs. pltclu)? */
145
145
pltcl_interp_desc * interp_desc ; /* interpreter to use */
146
+ Oid result_typid ; /* OID of fn's result type */
146
147
FmgrInfo result_in_func ; /* input function for fn's result type */
147
148
Oid result_typioparam ; /* param to pass to same */
148
149
bool fn_retisset ; /* true if function returns a set */
149
150
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 */
150
153
int nargs ; /* number of arguments */
151
154
/* these arrays have nargs entries: */
152
155
FmgrInfo * arg_out_func ; /* output fns for arg types */
@@ -988,11 +991,26 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
988
991
* result type is a named composite type, so it's not exactly trivial.
989
992
* Maybe worth improving someday.
990
993
*/
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
+ }
996
1014
997
1015
Assert (!call_state -> ret_tupdesc );
998
1016
Assert (!call_state -> attinmeta );
@@ -1490,40 +1508,41 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid,
1490
1508
************************************************************/
1491
1509
if (!is_trigger && !is_event_trigger )
1492
1510
{
1493
- typeTup =
1494
- SearchSysCache1 ( TYPEOID ,
1495
- ObjectIdGetDatum (procStruct -> prorettype ));
1511
+ Oid rettype = procStruct -> prorettype ;
1512
+
1513
+ typeTup = SearchSysCache1 ( TYPEOID , ObjectIdGetDatum (rettype ));
1496
1514
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 );
1499
1516
typeStruct = (Form_pg_type ) GETSTRUCT (typeTup );
1500
1517
1501
1518
/* Disallow pseudotype result, except VOID and RECORD */
1502
1519
if (typeStruct -> typtype == TYPTYPE_PSEUDO )
1503
1520
{
1504
- if (procStruct -> prorettype == VOIDOID ||
1505
- procStruct -> prorettype == RECORDOID )
1521
+ if (rettype == VOIDOID ||
1522
+ rettype == RECORDOID )
1506
1523
/* okay */ ;
1507
- else if (procStruct -> prorettype == TRIGGEROID ||
1508
- procStruct -> prorettype == EVTTRIGGEROID )
1524
+ else if (rettype == TRIGGEROID ||
1525
+ rettype == EVTTRIGGEROID )
1509
1526
ereport (ERROR ,
1510
1527
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1511
1528
errmsg ("trigger functions can only be called as triggers" )));
1512
1529
else
1513
1530
ereport (ERROR ,
1514
1531
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1515
1532
errmsg ("PL/Tcl functions cannot return type %s" ,
1516
- format_type_be (procStruct -> prorettype ))));
1533
+ format_type_be (rettype ))));
1517
1534
}
1518
1535
1536
+ prodesc -> result_typid = rettype ;
1519
1537
fmgr_info_cxt (typeStruct -> typinput ,
1520
1538
& (prodesc -> result_in_func ),
1521
1539
proc_cxt );
1522
1540
prodesc -> result_typioparam = getTypeIOParam (typeTup );
1523
1541
1524
1542
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 ;
1527
1546
1528
1547
ReleaseSysCache (typeTup );
1529
1548
}
@@ -1537,21 +1556,22 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid,
1537
1556
proc_internal_args [0 ] = '\0' ;
1538
1557
for (i = 0 ; i < prodesc -> nargs ; i ++ )
1539
1558
{
1540
- typeTup = SearchSysCache1 (TYPEOID ,
1541
- ObjectIdGetDatum (procStruct -> proargtypes .values [i ]));
1559
+ Oid argtype = procStruct -> proargtypes .values [i ];
1560
+
1561
+ typeTup = SearchSysCache1 (TYPEOID , ObjectIdGetDatum (argtype ));
1542
1562
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 );
1545
1564
typeStruct = (Form_pg_type ) GETSTRUCT (typeTup );
1546
1565
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 )
1549
1569
ereport (ERROR ,
1550
1570
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1551
1571
errmsg ("PL/Tcl functions cannot accept type %s" ,
1552
- format_type_be (procStruct -> proargtypes . values [ i ] ))));
1572
+ format_type_be (argtype ))));
1553
1573
1554
- if (typeStruct -> typtype == TYPTYPE_COMPOSITE )
1574
+ if (type_is_rowtype ( argtype ) )
1555
1575
{
1556
1576
prodesc -> arg_is_rowtype [i ] = true;
1557
1577
snprintf (buf , sizeof (buf ), "__PLTcl_Tup_%d" , i + 1 );
@@ -3075,6 +3095,7 @@ static HeapTuple
3075
3095
pltcl_build_tuple_result (Tcl_Interp * interp , Tcl_Obj * * kvObjv , int kvObjc ,
3076
3096
pltcl_call_state * call_state )
3077
3097
{
3098
+ HeapTuple tuple ;
3078
3099
TupleDesc tupdesc ;
3079
3100
AttInMetadata * attinmeta ;
3080
3101
char * * values ;
@@ -3133,7 +3154,16 @@ pltcl_build_tuple_result(Tcl_Interp *interp, Tcl_Obj **kvObjv, int kvObjc,
3133
3154
values [attn - 1 ] = utf_u2e (Tcl_GetString (kvObjv [i + 1 ]));
3134
3155
}
3135
3156
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 ;
3137
3167
}
3138
3168
3139
3169
/**********************************************************************
0 commit comments