3131 * ENHANCEMENTS, OR MODIFICATIONS.
3232 *
3333 * IDENTIFICATION
34- * $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.31 2000/12/08 00:09:07 tgl Exp $
34+ * $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.32 2001/02/16 03:26:40 tgl Exp $
3535 *
3636 **********************************************************************/
3737
@@ -103,7 +103,7 @@ static Tcl_Interp *pltcl_safe_interp = NULL;
103103static Tcl_HashTable * pltcl_proc_hash = NULL ;
104104static Tcl_HashTable * pltcl_norm_query_hash = NULL ;
105105static Tcl_HashTable * pltcl_safe_query_hash = NULL ;
106- static FunctionCallInfo pltcl_actual_fcinfo = NULL ;
106+ static FunctionCallInfo pltcl_current_fcinfo = NULL ;
107107
108108/**********************************************************************
109109 * Forward declarations
@@ -354,18 +354,18 @@ pltcl_call_handler(PG_FUNCTION_ARGS)
354354 * Determine if called as function or trigger and
355355 * call appropriate subhandler
356356 ************************************************************/
357- save_fcinfo = pltcl_actual_fcinfo ;
357+ save_fcinfo = pltcl_current_fcinfo ;
358358
359359if (CALLED_AS_TRIGGER (fcinfo ))
360360{
361- pltcl_actual_fcinfo = NULL ;
361+ pltcl_current_fcinfo = NULL ;
362362retval = PointerGetDatum (pltcl_trigger_handler (fcinfo ));
363363}else {
364- pltcl_actual_fcinfo = fcinfo ;
364+ pltcl_current_fcinfo = fcinfo ;
365365retval = pltcl_func_handler (fcinfo );
366366}
367367
368- pltcl_actual_fcinfo = save_fcinfo ;
368+ pltcl_current_fcinfo = save_fcinfo ;
369369
370370pltcl_call_level -- ;
371371
@@ -743,17 +743,27 @@ pltcl_func_handler(PG_FUNCTION_ARGS)
743743 * Disconnect from SPI manager and then create the return
744744 * values datum (if the input function does a palloc for it
745745 * this must not be allocated in the SPI memory context
746- * because SPI_finish would free it).
746+ * because SPI_finish would free it). But don't try to call
747+ * the result_in_func if we've been told to return a NULL;
748+ * the contents of interp->result may not be a valid value of
749+ * the result type in that case.
747750 ************************************************************/
748751if (SPI_finish ()!= SPI_OK_FINISH )
749752elog (ERROR ,"pltcl: SPI_finish() failed" );
750753
751- retval = FunctionCall3 (& prodesc -> result_in_func ,
752- PointerGetDatum (interp -> result ),
753- ObjectIdGetDatum (prodesc -> result_in_elem ),
754- Int32GetDatum (-1 ));
754+ if (fcinfo -> isnull )
755+ retval = (Datum )0 ;
756+ else
757+ retval = FunctionCall3 (& prodesc -> result_in_func ,
758+ PointerGetDatum (interp -> result ),
759+ ObjectIdGetDatum (prodesc -> result_in_elem ),
760+ Int32GetDatum (-1 ));
755761
762+ /************************************************************
763+ * Finally we may restore normal error handling.
764+ ************************************************************/
756765memcpy (& Warn_restart ,& save_restart ,sizeof (Warn_restart ));
766+
757767return retval ;
758768}
759769
@@ -1345,7 +1355,7 @@ pltcl_argisnull(ClientData cdata, Tcl_Interp *interp,
13451355int argc ,char * argv [])
13461356{
13471357int argno ;
1348- FunctionCallInfo fcinfo = pltcl_actual_fcinfo ;
1358+ FunctionCallInfo fcinfo = pltcl_current_fcinfo ;
13491359
13501360/************************************************************
13511361 * Check call syntax
@@ -1356,22 +1366,22 @@ pltcl_argisnull(ClientData cdata, Tcl_Interp *interp,
13561366return TCL_ERROR ;
13571367}
13581368
1359- /************************************************************
1360- * Get the argument number
1361- ************************************************************/
1362- if (Tcl_GetInt (interp ,argv [1 ],& argno )!= TCL_OK )
1363- return TCL_ERROR ;
1364-
13651369/************************************************************
13661370 * Check that we're called as a normal function
13671371 ************************************************************/
13681372if (fcinfo == NULL )
13691373{
13701374Tcl_SetResult (interp ,"argisnull cannot be used in triggers" ,
1371- TCL_VOLATILE );
1375+ TCL_VOLATILE );
13721376return TCL_ERROR ;
13731377}
13741378
1379+ /************************************************************
1380+ * Get the argument number
1381+ ************************************************************/
1382+ if (Tcl_GetInt (interp ,argv [1 ],& argno )!= TCL_OK )
1383+ return TCL_ERROR ;
1384+
13751385/************************************************************
13761386 * Check that the argno is valid
13771387 ************************************************************/
@@ -1402,7 +1412,7 @@ pltcl_returnnull(ClientData cdata, Tcl_Interp *interp,
14021412int argc ,char * argv [])
14031413{
14041414int argno ;
1405- FunctionCallInfo fcinfo = pltcl_actual_fcinfo ;
1415+ FunctionCallInfo fcinfo = pltcl_current_fcinfo ;
14061416
14071417/************************************************************
14081418 * Check call syntax
@@ -1413,11 +1423,22 @@ pltcl_returnnull(ClientData cdata, Tcl_Interp *interp,
14131423return TCL_ERROR ;
14141424}
14151425
1426+ /************************************************************
1427+ * Check that we're called as a normal function
1428+ ************************************************************/
1429+ if (fcinfo == NULL )
1430+ {
1431+ Tcl_SetResult (interp ,"return_null cannot be used in triggers" ,
1432+ TCL_VOLATILE );
1433+ return TCL_ERROR ;
1434+ }
1435+
14161436/************************************************************
14171437 * Set the NULL return flag and cause Tcl to return from the
14181438 * procedure.
14191439 ************************************************************/
14201440fcinfo -> isnull = true;
1441+
14211442return TCL_RETURN ;
14221443}
14231444