From: | "Billow Gao" <billowgy(at)gmail(dot)com> |
---|---|
To: | pgsql-hackers(at)postgresql(dot)org |
Subject: | Why my C function is called twice? |
Date: | 2007-12-11 16:59:18 |
Message-ID: | 677a32120712110859u39e6c490gf90e93bedaab4331@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
A very simple C function which I copied from the manual.
And I found that it's called twice.
Even in the function:
if (SRF_IS_FIRSTCALL()) {
ereport(INFO, (errcode(ERRCODE_IO_ERROR), errmsg("1")));
}
An example output. You will find two INFO: 1 there......
Why a function is called twice and how to prevent this problem?
Thanks
Billow
test=# select * from retcomposite(1,48);
INFO: 1
INFO: 2
INFO: 3
INFO: 1
INFO: 4
INFO: 2
INFO: 2
INFO: 5
INFO: 3
INFO: 4
INFO: 2
INFO: 5
f1 | f2 | f3
----+----+-----
48 | 96 | 144
(1 row)
===============================================================
Code......
===============================================================
/*
CREATE OR REPLACE FUNCTION retcomposite(integer, integer)
RETURNS SETOF __retcomposite
AS 'test.so', 'retcomposite'
LANGUAGE C IMMUTABLE STRICT;
*/
// PostgreSQL includes
#include "postgres.h"
#include "fmgr.h"
// Tuple building functions and macros
#include "access/heapam.h"
#include "funcapi.h"
#include "utils/builtins.h"
#include <sys/socket.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/select.h>
#define _textout(str) DatumGetPointer(DirectFunctionCall1(textout,
PointerGetDatum(str)))
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(retcomposite);
Datum
retcomposite(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
int call_cntr;
int max_calls;
TupleDesc tupdesc;
AttInMetadata *attinmeta;
/* stuff done only on the first call of the function */
if (SRF_IS_FIRSTCALL()) {
MemoryContext oldcontext;
ereport(INFO, (errcode(ERRCODE_IO_ERROR), errmsg("1")));
/* create a function context for cross-call persistence
*/
funcctx = SRF_FIRSTCALL_INIT();
/* switch to memory context appropriate for multiple
function calls */
oldcontext =
MemoryContextSwitchTo(funcctx->
multi_call_memory_ctx);
/* total number of tuples to be returned */
funcctx->max_calls = PG_GETARG_UINT32(0);
/* Build a tuple descriptor for our result type */
if (get_call_result_type(fcinfo, NULL, &tupdesc) !=
TYPEFUNC_COMPOSITE)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg
("function returning record called in context "
"that cannot accept type record")));
/* generate attribute metadata needed later to produce
tuples from raw C strings */
attinmeta = TupleDescGetAttInMetadata(tupdesc);
funcctx->attinmeta = attinmeta;
MemoryContextSwitchTo(oldcontext);
}
ereport(INFO, (errcode(ERRCODE_IO_ERROR), errmsg("2")));
/* stuff done on every call of the function */
funcctx = SRF_PERCALL_SETUP();
call_cntr = funcctx->call_cntr;
max_calls = funcctx->max_calls;
attinmeta = funcctx->attinmeta;
if (call_cntr < max_calls) { /* do when there is more
left to send */
char **values;
HeapTuple tuple;
Datum result;
ereport(INFO, (errcode(ERRCODE_IO_ERROR), errmsg("3")));
/* Prepare a values array for building the returned
tuple. This should be an array of C strings which
will be processed later by the type input functions. */
values = (char **) palloc(3 * sizeof(char *));
values[0] = (char *) palloc(16 * sizeof(char));
values[1] = (char *) palloc(16 * sizeof(char));
values[2] = (char *) palloc(16 * sizeof(char));
snprintf(values[0], 16, "%d", 1 * PG_GETARG_INT32(1));
snprintf(values[1], 16, "%d", 2 * PG_GETARG_INT32(1));
snprintf(values[2], 16, "%d", 3 * PG_GETARG_INT32(1));
/* build a tuple */
tuple = BuildTupleFromCStrings(attinmeta, values);
/* make the tuple into a datum */
result = HeapTupleGetDatum(tuple);
/* clean up (this is not really necessary) */
pfree(values[0]);
pfree(values[1]);
pfree(values[2]);
pfree(values);
ereport(INFO, (errcode(ERRCODE_IO_ERROR), errmsg("4")));
SRF_RETURN_NEXT(funcctx, result);
} else { /* do when there is no more left */
ereport(INFO, (errcode(ERRCODE_IO_ERROR), errmsg("5")));
SRF_RETURN_DONE(funcctx);
}
}
From | Date | Subject | |
---|---|---|---|
Next Message | Simon Riggs | 2007-12-11 17:16:00 | Re: archive_command failures report confusing exit status |
Previous Message | Tom Lane | 2007-12-11 16:54:14 | Re: PGparam proposal |