Thread: C function returns null values

C function returns null values

From
Gregor Trefs
Date:

Hello all,

 

I developed a C function which returns a record. The record contains 3 scalar values and 2 arrays. Randomly some record elements are null and I wonder why. I could trace down the problem to the point where the return record is created. Until this point everything is computed correctly. Below you see an excerpt of the relevant code. I use PostGres 8.4 on Ubuntu 10.10 (x64).

 

typedef struct {

    // Size of the array

    int size;

    // Values of the array

    double *values;

} array_d;

 

// Integer

 

typedef struct {

    // Size of the array

    int size;

    // Values of the array

    int *values;

} array_i;

 

typedef struct {

    interval_orders o;

    array_d *interval_weights;

    array_d *interval_borders;

    array_i *add_weights;

    double b;

} c_param_type;

 

void create_dati_from_result(Datum *values, c_param_type *param) {

    // Array creation

    ArrayType *weights, *borders;

    Datum *weights_elem;

    Datum *borders_elem;

    int16 typlen;

    bool typbyval;

    char typalign;

 

    int i;

 

    // Set values

    values[0] = Float8GetDatum(param->o.interval_weight);

    values[1] = Float8GetDatum(param->o.quantitiy);

    values[2] = Float8GetDatum(param->o.long_sql);

    // Create datum arrays

    weights_elem = palloc(param->interval_weights->size * sizeof (Datum));

    borders_elem = palloc(param->interval_borders->size * sizeof (Datum));

    for (i = 0; i < param->interval_weights->size; i++) {

        weights_elem[i] = Float8GetDatum((float8) param->interval_weights->values[i]);

    }

    for (i = 0; i < param->interval_borders->size; i++) {

        borders_elem[i] = Float8GetDatum((float8) param->interval_borders->values[i]);

    }

    // Create array type

    get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);

    weights = construct_array(weights_elem, param->interval_weights->size, FLOAT8OID, typlen, typbyval, typalign);

    borders = construct_array(borders_elem, param->interval_borders->size, FLOAT8OID, typlen, typbyval, typalign);

    values[3] = PointerGetDatum(borders);

    values[4] = PointerGetDatum(weights); 

}

 

PG_FUNCTION_INFO_V1(insert_order);

 

Datum insert_order(PG_FUNCTION_ARGS) {

    // Variable declarations go here

    // …

    // vars for result

    TupleDesc tupdesc;

    Datum *values;

    bool *nulls;

    int tuplen,i;

    HeapTuple res_tuple;

    // Look whether everything has been provided

    if (PG_ARGISNULL(0)) {

        ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("First argument is NULL")));

        PG_RETURN_NULL();

    }

    // Allocate memory

    param = palloc(sizeof (c_param_type));

    // Get the HeapTupleHeader

    header = PG_GETARG_HEAPTUPLEHEADER_COPY(0);

    // Extract information from parameter

    if (!extract_information(param, header)) {

        PG_RETURN_NULL();

    }

    // Some more code goes here

    // …

 

    // Set values

    param->o.long_sql = total_cost;

    param->o.quantitiy = weight;

    param->o.interval_weight = weight;

  

    // Create result tuple

    values = palloc(sizeof(Datum)*5);

    if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)

        ereport(ERROR, (errcode(ERRCODE_SUCCESSFUL_COMPLETION), errmsg("function returning record called in context that cannot accept type record")));

    // Get Dati

    create_dati_from_result(values, param);

    // Init Tuple Desc

    tupdesc = BlessTupleDesc(tupdesc);

    // Size

    tuplen = tupdesc->natts;

    // Allocate enough memory for nulls

    nulls = palloc(tuplen * sizeof (bool));

    // Create tuple

    res_tuple = heap_form_tuple(tupdesc, values, nulls);

    // Free allocated memory

    pfree(nulls);

    // Return result

    PG_RETURN_DATUM(HeapTupleGetDatum(res_tuple));

}

 

I hope you can help me.

 

Regards,

Gregor

 

Re: C function returns null values

From
Tom Lane
Date:
Gregor Trefs <gregor.trefs@delphit.com> writes:
> I developed a C function which returns a record. The record contains 3 scalar values and 2 arrays. Randomly some
recordelements are null and I wonder why. I could trace down the problem to the point where the return record is
created.Until this point everything is computed correctly. Below you see an excerpt of the relevant code. I use
PostGres8.4 on Ubuntu 10.10 (x64). 

You're not bothering to fill in the nulls[] array:

>     // Allocate enough memory for nulls
>     nulls = palloc(tuplen * sizeof (bool));
>     // Create tuple
>     res_tuple = heap_form_tuple(tupdesc, values, nulls);

palloc0 would work better here.

BTW, it's a good idea to develop/test C code in a backend built with
--enable-debug --enable-cassert.  Had you been doing so, palloc would
have given you back intentionally-garbage-filled memory, and you'd have
noticed the mistake immediately.

            regards, tom lane

Re: C function returns null values

From
Gregor Trefs
Date:
Thanks for your answer. I edited my code, but still get these random null values. What else can I do ?

Regards

-----Ursprüngliche Nachricht-----
Von: Tom Lane [mailto:tgl@sss.pgh.pa.us]
Gesendet: Freitag, 15. Juli 2011 16:24
An: Gregor Trefs
Cc: pgsql-general@postgresql.org
Betreff: Re: [GENERAL] C function returns null values

Gregor Trefs <gregor.trefs@delphit.com> writes:
> I developed a C function which returns a record. The record contains 3 scalar values and 2 arrays. Randomly some
recordelements are null and I wonder why. I could trace down the problem to the point where the return record is
created.Until this point everything is computed correctly. Below you see an excerpt of the relevant code. I use
PostGres8.4 on Ubuntu 10.10 (x64). 

You're not bothering to fill in the nulls[] array:

>     // Allocate enough memory for nulls
>     nulls = palloc(tuplen * sizeof (bool));
>     // Create tuple
>     res_tuple = heap_form_tuple(tupdesc, values, nulls);

palloc0 would work better here.

BTW, it's a good idea to develop/test C code in a backend built with --enable-debug --enable-cassert.  Had you been
doingso, palloc would have given you back intentionally-garbage-filled memory, and you'd have noticed the mistake
immediately.

            regards, tom lane

Re: C function returns null values

From
Tom Lane
Date:
Gregor Trefs <gregor.trefs@delphit.com> writes:
> Thanks for your answer. I edited my code, but still get these random null values. What else can I do ?

Mph ... you're aware that you have to start a fresh session to load a
new version of a .so into the backend?

            regards, tom lane

Re: C function returns null values

From
Gregor Trefs
Date:
Well, yes. I wrote a little make file which takes care of this part (except restarting the session):

INCLUDEDIRS += -I$(shell pg_config --includedir-server)
LIBDIR = -L$(shell pg_config --libdir)
LIBINSTALL = $(shell pg_config --pkglibdir)

integrated_c.so: integrated_c.c Makefile
            gcc -fpic -o integrated_c.o -c integrated_c.c $(INCLUDEDIRS)
            gcc -shared -o integrated_c.so integrated_c.o $(LIBDIR) -lmpfr -lgmp
            cp integrated_c.so $(LIBINSTALL)

-----Ursprüngliche Nachricht-----
Von: Tom Lane [mailto:tgl@sss.pgh.pa.us]
Gesendet: Montag, 18. Juli 2011 16:33
An: Gregor Trefs
Cc: pgsql-general@postgresql.org
Betreff: Re: [GENERAL] C function returns null values

Gregor Trefs <gregor.trefs@delphit.com> writes:
> Thanks for your answer. I edited my code, but still get these random null values. What else can I do ?

Mph ... you're aware that you have to start a fresh session to load a new version of a .so into the backend?

            regards, tom lane

Re: C function returns null values

From
Gregor Trefs
Date:
Finally I got it working. You were right Tom Lane. I actually did not copy the corrected source file onto the server
andthus still had this "mysterious" failure. So, palloc0 is the solution. Thanks again. 

Regards,
Gregor Trefs

-----Ursprüngliche Nachricht-----
Von: pgsql-general-owner@postgresql.org [mailto:pgsql-general-owner@postgresql.org] Im Auftrag von Gregor Trefs
Gesendet: Montag, 18. Juli 2011 17:20
Cc: pgsql-general@postgresql.org
Betreff: Re: [GENERAL] C function returns null values

Well, yes. I wrote a little make file which takes care of this part (except restarting the session):

INCLUDEDIRS += -I$(shell pg_config --includedir-server) LIBDIR = -L$(shell pg_config --libdir) LIBINSTALL = $(shell
pg_config--pkglibdir) 

integrated_c.so: integrated_c.c Makefile
            gcc -fpic -o integrated_c.o -c integrated_c.c $(INCLUDEDIRS)
            gcc -shared -o integrated_c.so integrated_c.o $(LIBDIR) -lmpfr -lgmp
            cp integrated_c.so $(LIBINSTALL)

-----Ursprüngliche Nachricht-----
Von: Tom Lane [mailto:tgl@sss.pgh.pa.us]
Gesendet: Montag, 18. Juli 2011 16:33
An: Gregor Trefs
Cc: pgsql-general@postgresql.org
Betreff: Re: [GENERAL] C function returns null values

Gregor Trefs <gregor.trefs@delphit.com> writes:
> Thanks for your answer. I edited my code, but still get these random null values. What else can I do ?

Mph ... you're aware that you have to start a fresh session to load a new version of a .so into the backend?

            regards, tom lane

--
Sent via pgsql-general mailing list (pgsql-general@postgresql.org) To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general