Re: Srf function : missing library on PostgreSQL 8.3.6 on Windows?

From: Ben Ali Rachid <souliman239(at)yahoo(dot)fr>
To: tgl(at)sss(dot)pgh(dot)pa(dot)us
Cc: craig(at)postnewspapers(dot)com(dot)au, pgsql-general(at)postgresql(dot)org
Subject: Re: Srf function : missing library on PostgreSQL 8.3.6 on Windows?
Date: 2009-03-22 17:52:25
Message-ID: 659064.79401.qm@web28514.mail.ukl.yahoo.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general


Tom Lane wrote :
> PG_FUNCTION_INFO_V1() generates a function that has to have "C" linkage.
> So does PG_MODULE_MAGIC.  I'm actually not sure how you got the module
> to load at all with the latter point ...

Sorry, I forgot this in my previous post :

#ifdef __cplusplus
extern "C" {
#endif

--

#ifdef __cplusplus
}
#endif

I also forgot the definition of the function 'get_normal_pair'. So my (correct) cpp file is like below :

#include "dll.h"

#ifdef __cplusplus
extern "C" {
#endif

PG_MODULE_MAGIC;

void get_normal_pair(float8 *x1, float8 *x2);
void get_normal_pair(float8 *x1, float8 *x2)
{
    float8     u1,
                u2,
                v1,
                v2,
                s;
    do
    {
        u1 = (float8) rand() / (float8) MAX_RANDOM_VALUE;
        u2 = (float8) rand() / (float8) MAX_RANDOM_VALUE;
        v1 = (2.0 * u1) - 1.0;
        v2 = (2.0 * u2) - 1.0;
        s = v1 * v1 + v2 * v2;
    }
    while (s >= 1.0);

    if (s == 0)
    {
        *x1 = 0;
        *x2 = 0;
    }
    else
    {
        s = sqrt((-2.0 * log(s)) / s);
        *x1 = v1 * s;
        *x2 = v2 * s;
    }
}

typedef struct
{
    float8        mean;             /* mean of the distribution */
    float8        stddev;            /* stddev of the distribution */
    float8        carry_val;        /* hold second generated value */
    bool         use_carry;        /* use second generated value */
} normal_rand_fctx;

PG_FUNCTION_INFO_V1(normal_rand);
Datum normal_rand(PG_FUNCTION_ARGS)
{
    FuncCallContext *funcctx;
    int            call_cntr;
    int            max_calls;
    normal_rand_fctx *fctx;
    float8        mean;
    float8        stddev;
    float8        carry_val;
    bool        use_carry;
    MemoryContext oldcontext;

    /* stuff done only on the first call of the function */
    if (SRF_IS_FIRSTCALL())
    {
        /* 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);

        /* allocate memory for user context */
        fctx = (normal_rand_fctx *) palloc(sizeof(normal_rand_fctx));

        /*
         * Use fctx to keep track of upper and lower bounds from call to call.
         * It will also be used to carry over the spare value we get from the
         * Box-Muller algorithm so that we only actually calculate a new value
         * every other call.
         */
        fctx->mean = PG_GETARG_FLOAT8(1);
        fctx->stddev = PG_GETARG_FLOAT8(2);
        fctx->carry_val = 0;
        fctx->use_carry = false;

        funcctx->user_fctx = fctx;
        MemoryContextSwitchTo(oldcontext);
    }

    /* stuff done on every call of the function */
    funcctx = SRF_PERCALL_SETUP();

    call_cntr = funcctx->call_cntr;
    max_calls = funcctx->max_calls;
    fctx = (normal_rand_fctx*) funcctx->user_fctx;
    mean = fctx->mean;
    stddev = fctx->stddev;
    carry_val = fctx->carry_val;
    use_carry = fctx->use_carry;

    if (call_cntr < max_calls)    /* do when there is more left to send */
    {
        float8        result;
        if (use_carry)
        {
            /* reset use_carry and use second value obtained on last pass */
            fctx->use_carry = false;
            result = carry_val;
        }
        else
        {
            float8        normval_1;
            float8        normval_2;

            /* Get the next two normal values */
            get_normal_pair(&normval_1, &normval_2);

            /* use the first */
            result = mean + (stddev * normval_1);

            /* and save the second */
            fctx->carry_val = mean + (stddev * normval_2);
            fctx->use_carry = true;
        }

        /* send the result */
        SRF_RETURN_NEXT(funcctx, Float8GetDatum(result));
    }
    else
        /* do when there is no more left */
        SRF_RETURN_DONE(funcctx);
}

#ifdef __cplusplus
}
#endif

I have no problem when I load the DLL (no 'missing magic block' error). The server crashes when I try : SELECT normal_rand(5, 10.0, 20.0) or SELECT * FROM normal_rand(5, 10.0, 20.0).

--
Ben Ali Rachid

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Oliver Weichhold 2009-03-22 19:05:19 Understanding Execution Plans
Previous Message RebeccaJ 2009-03-22 17:36:37 Re: text column constraint, newbie question