src/pl/tcl/pltcl.c
static int
pltcl_returnnext(ClientData cdata, Tcl_Interp *interp,
				 int objc, Tcl_Obj *const objv[])
{
	pltcl_call_state *call_state = pltcl_current_call_state;
	FunctionCallInfo fcinfo = call_state->fcinfo;
	pltcl_proc_desc *prodesc = call_state->prodesc;
	MemoryContext oldcontext = CurrentMemoryContext;
	ResourceOwner oldowner = CurrentResourceOwner;
	volatile int result = TCL_OK;

	/*
	 * Check that we're called as a set-returning function
	 */
	if (fcinfo == NULL)
	{
		Tcl_SetObjResult(interp,
						 Tcl_NewStringObj("return_next cannot be used in triggers", -1));
		return TCL_ERROR;
	}

	if (!prodesc->fn_retisset)
	{
		Tcl_SetObjResult(interp,
						 Tcl_NewStringObj("return_next cannot be used in non-set-returning functions", -1));
		return TCL_ERROR;
	}

	/*
	 * Check call syntax
	 */
	if (objc != 2)
	{
		Tcl_WrongNumArgs(interp, 1, objv, "result");
		return TCL_ERROR;
	}

	/*
	 * The rest might throw elog(ERROR), so must run in a subtransaction.
	 *
	 * A small advantage of using a subtransaction is that it provides a
	 * short-lived memory context for free, so we needn't worry about leaking
	 * memory here.  To use that context, call BeginInternalSubTransaction
	 * directly instead of going through pltcl_subtrans_begin.
	 */
	BeginInternalSubTransaction(NULL);
	PG_TRY();
	{
		/* Set up tuple store if first output row */
		if (call_state->tuple_store == NULL)
			pltcl_init_tuple_store(call_state);

		if (prodesc->fn_retistuple)
		{
			Tcl_Obj   **rowObjv;
			int			rowObjc;

			/* result should be a list, so break it down */
			if (Tcl_ListObjGetElements(interp, objv[1], &rowObjc, &rowObjv) == TCL_ERROR)
				result = TCL_ERROR;
			else
			{
				HeapTuple	tuple;

				tuple = pltcl_build_tuple_result(interp, rowObjv, rowObjc,
												 call_state);
				tuplestore_puttuple(call_state->tuple_store, tuple);
			}
		}
		else
		{
			Datum		retval;
			bool		isNull = false;

			/* for paranoia's sake, check that tupdesc has exactly one column */
			if (call_state->ret_tupdesc->natts != 1)
				elog(ERROR, "wrong result type supplied in return_next");

			retval = InputFunctionCall(&prodesc->result_in_func,
									   utf_u2e((char *) Tcl_GetString(objv[1])),
									   prodesc->result_typioparam,
									   -1);
			tuplestore_putvalues(call_state->tuple_store, call_state->ret_tupdesc,
								 &retval, &isNull);
		}

		pltcl_subtrans_commit(oldcontext, oldowner);
	}
	PG_CATCH();
	{
		pltcl_subtrans_abort(interp, oldcontext, oldowner);
		return TCL_ERROR;
	}
	PG_END_TRY();

	return result;
}
/**********************************************************************
 * pltcl_returnnext()	- Add a row to the result tuplestore in a SRF.
 **********************************************************************/
pltcl_returnnext()   - Add a row to the result tuplestore in a SRF.
pltcl_returnnext () - Add a row to the result tuplestore in a SRF .
static int
pltcl_returnnext(ClientData cdata, Tcl_Interp *interp,
				 int objc, Tcl_Obj *const objv[])
{
	pltcl_call_state *call_state = pltcl_current_call_state;
	FunctionCallInfo fcinfo = call_state->fcinfo;
	pltcl_proc_desc *prodesc = call_state->prodesc;
	MemoryContext oldcontext = CurrentMemoryContext;
	ResourceOwner oldowner = CurrentResourceOwner;
	volatile int result = TCL_OK;
	if (fcinfo == NULL)
	{
		Tcl_SetObjResult(interp,
						 Tcl_NewStringObj("return_next cannot be used in triggers", -1));
		return TCL_ERROR;
	}
	if (!prodesc->fn_retisset)
	{
		Tcl_SetObjResult(interp,
						 Tcl_NewStringObj("return_next cannot be used in non-set-returning functions", -1));
		return TCL_ERROR;
	}
	if (objc != 2)
	{
		Tcl_WrongNumArgs(interp, 1, objv, "result");
		return TCL_ERROR;
	}
	BeginInternalSubTransaction(NULL);
	PG_TRY();
	{
		if (call_state->tuple_store == NULL)
			pltcl_init_tuple_store(call_state);
		if (prodesc->fn_retistuple)
		{
			Tcl_Obj   **rowObjv;
			int			rowObjc;
			if (Tcl_ListObjGetElements(interp, objv[1], &rowObjc, &rowObjv) == TCL_ERROR)
				result = TCL_ERROR;
			else
			{
				HeapTuple	tuple;
				tuple = pltcl_build_tuple_result(interp, rowObjv, rowObjc,
												 call_state);
				tuplestore_puttuple(call_state->tuple_store, tuple);
			}
		}
		else
		{
			Datum		retval;
			bool		isNull = false;
			if (call_state->ret_tupdesc->natts != 1)
				elog(ERROR, "wrong result type supplied in return_next");
			retval = InputFunctionCall(&prodesc->result_in_func,
									   utf_u2e((char *) Tcl_GetString(objv[1])),
									   prodesc->result_typioparam,
									   -1);
			tuplestore_putvalues(call_state->tuple_store, call_state->ret_tupdesc,
								 &retval, &isNull);
		}
		pltcl_subtrans_commit(oldcontext, oldowner);
	}
	PG_CATCH();
	{
		pltcl_subtrans_abort(interp, oldcontext, oldowner);
		return TCL_ERROR;
	}
	PG_END_TRY();
	return result;
}
static int pltcl_returnnext ( ClientData cdata , Tcl_Interp * interp , int objc , Tcl_Obj * const objv [ ] ) { pltcl_call_state * call_state = pltcl_current_call_state ; FunctionCallInfo fcinfo = call_state -> fcinfo ; pltcl_proc_desc * prodesc = call_state -> prodesc ; MemoryContext oldcontext = CurrentMemoryContext ; ResourceOwner oldowner = CurrentResourceOwner ; volatile int result = TCL_OK ; if ( fcinfo == NULL ) { Tcl_SetObjResult ( interp , Tcl_NewStringObj ( " " , -1 ) ) ; return TCL_ERROR ; } if ( ! prodesc -> fn_retisset ) { Tcl_SetObjResult ( interp , Tcl_NewStringObj ( " " , -1 ) ) ; return TCL_ERROR ; } if ( objc != 2 ) { Tcl_WrongNumArgs ( interp , 1 , objv , " " ) ; return TCL_ERROR ; } BeginInternalSubTransaction ( NULL ) ; PG_TRY ( ) ; { if ( call_state -> tuple_store == NULL ) pltcl_init_tuple_store ( call_state ) ; if ( prodesc -> fn_retistuple ) { Tcl_Obj * * rowObjv ; int rowObjc ; if ( Tcl_ListObjGetElements ( interp , objv [ 1 ] , & rowObjc , & rowObjv ) == TCL_ERROR ) result = TCL_ERROR ; else { HeapTuple tuple ; tuple = pltcl_build_tuple_result ( interp , rowObjv , rowObjc , call_state ) ; tuplestore_puttuple ( call_state -> tuple_store , tuple ) ; } } else { Datum retval ; bool isNull = false ; if ( call_state -> ret_tupdesc -> natts != 1 ) elog ( ERROR , " " ) ; retval = InputFunctionCall ( & prodesc -> result_in_func , utf_u2e ( ( char * ) Tcl_GetString ( objv [ 1 ] ) ) , prodesc -> result_typioparam , -1 ) ; tuplestore_putvalues ( call_state -> tuple_store , call_state -> ret_tupdesc , & retval , & isNull ) ; } pltcl_subtrans_commit ( oldcontext , oldowner ) ; } PG_CATCH ( ) ; { pltcl_subtrans_abort ( interp , oldcontext , oldowner ) ; return TCL_ERROR ; } PG_END_TRY ( ) ; return result ; }
pltcl_returnnext()   - Add a row to the result tuplestore in a SRF.
pltcl_returnnext () - Add a row to the result tuplestore in a SRF .
/*
	 * Check that we're called as a set-returning function
	 */ /*
	 * Check call syntax
	 */ /*
	 * The rest might throw elog(ERROR), so must run in a subtransaction.
	 *
	 * A small advantage of using a subtransaction is that it provides a
	 * short-lived memory context for free, so we needn't worry about leaking
	 * memory here.  To use that context, call BeginInternalSubTransaction
	 * directly instead of going through pltcl_subtrans_begin.
	 */ /* Set up tuple store if first output row */ /* result should be a list, so break it down */ /* for paranoia's sake, check that tupdesc has exactly one column */