Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

This code compiles without error but it does not return anything. Any ideas on what's missing?

    #include <postgres.h>
    #include <fmgr.h>
    #include <utils/array.h>

    #ifdef PG_MODULE_MAGIC
    PG_MODULE_MAGIC;
    #endif

    Datum my_c_function(PG_FUNCTION_ARGS);

    PG_FUNCTION_INFO_V1(my_c_function);

    Datum
    my_c_function(PG_FUNCTION_ARGS)
    {
            float4          var1, var2, var3, var4;
            Datum*          vals;
            var1 = PG_GETARG_FLOAT8(0);
            var2 = PG_GETARG_FLOAT8(1);
            var3 = PG_GETARG_FLOAT8(2);
            var4 = PG_GETARG_FLOAT8(3);

            vals = palloc(sizeof(Datum)*4);

            if (var1 < var4) {
                    vals[0]  = (int)1;
                    vals[1]  = (int)(0.5+(100*((var2-var4)/(var2-var3))));
                    vals[2]  = (int)(0.5+(100*((var4-var1)/(var2-var3))));
                    vals[3]  = (int)(0.5+(100*((var1-var3)/(var2-var3))));
            } else if (var1 > var4) {
                    vals[0]  = (int)-1;
                    vals[1]  = (int)(0.5+(100*((var2-var1)/(var2-var3))));
                    vals[2]  = (int)(0.5+(100*((var1-var4)/(var2-var3))));
                    vals[3]  = (int)(0.5+(100*((var4-var3)/(var2-var3))));
            } else if (var2 == var3) {
                    PG_RETURN_NULL();
            } else {
                    vals[0]  = (int)0;
                    vals[1]  = (int)(0.5+(100*((var2-var4)/(var2-var3))));
                    vals[2]  = (int)0;
                    vals[3]  = (int)(0.5+(100*((var4-var3)/(var2-var3))));
            }

            PG_RETURN_ARRAYTYPE_P(vals);

    }

Corrected version:

    #include <postgres.h>
    #include <fmgr.h>
    #include <utils/array.h>
    #include <catalog/pg_type.h>

    #ifdef PG_MODULE_MAGIC
    PG_MODULE_MAGIC;
    #endif

    Datum cget_bar_structure2(PG_FUNCTION_ARGS);

    PG_FUNCTION_INFO_V1(cget_bar_structure2);

    Datum
    cget_bar_structure2(PG_FUNCTION_ARGS)
    {
            float4          var1, var2, var3, var4;
            Datum           *vals = (Datum *) palloc(sizeof(Datum) * 4);
            ArrayType       *result;

            var1 = PG_GETARG_FLOAT8(0);
            var2 = PG_GETARG_FLOAT8(1);
            var3 = PG_GETARG_FLOAT8(2);
            var4 = PG_GETARG_FLOAT8(3);

            if (var1 < var4) {
                    vals[0]  = Int32GetDatum(1);
                    vals[1]  = Int32GetDatum((0.5+(100*((var2-var4)/(var2-var3)))));
                    vals[2]  = Int32GetDatum((0.5+(100*((var4-var1)/(var2-var3)))));
                    vals[3]  = Int32GetDatum((0.5+(100*((var1-var3)/(var2-var3)))));
            } else if (var1 > var4) {
                    vals[0]  = Int32GetDatum(-1);
                    vals[1]  = Int32GetDatum((0.5+(100*((var2-var1)/(var2-var3)))));
                    vals[2]  = Int32GetDatum((0.5+(100*((var1-var4)/(var2-var3)))));
                    vals[3]  = Int32GetDatum((0.5+(100*((var4-var3)/(var2-var3)))));
            } else if (var2 == var3) {
                    PG_RETURN_NULL();
            } else {
                    vals[0]  = Int32GetDatum(0);
                    vals[1]  = Int32GetDatum((0.5+(100*((var2-var4)/(var2-var3)))));
                    vals[2]  = Int32GetDatum(0);
                    vals[3]  = Int32GetDatum((0.5+(100*((var4-var3)/(var2-var3)))));
            }

            result = construct_array(vals, 4, INT4OID, sizeof(int4), true, 'i');

            PG_RETURN_ARRAYTYPE_P(result);

    }
share|improve this question
    
"Does not return anything". Huh? Can you show the commands you used to CREATE FUNCTION and what happens when you invoke it? If you SELECT pg_backend_pid(), attach gdb to the backend, break my_c_function then c and run the SQL, does gdb actually stop execution at the start of your function? –  Craig Ringer May 9 at 6:34

1 Answer 1

up vote 1 down vote accepted

The fundamental problem is in fact, so PostgreSQL arrays are not compatible with C arrays.

Good google keyword is a "construct_md_array" or "construct_array"

I found one fragment that should to help

const int *data = array.data(); // C array
Datum *d = (Datum *) palloc(sizeof(Datum) * size);
ArrayType *a;

for (int i = 0; i < size; i++)
     d[i] = Int32GetDatum(data[i]);

a = construct_array(d, size, INT4OID, sizeof(int4), true, 'i');

PG_RETURN_ARRAYTYPE_P(a)
share|improve this answer
    
error: ‘INT4OID’ undeclared (first use in this function) –  Nick Boutelier May 9 at 15:50
    
I added <catalog/pg_type.h> which removed the undeclared error. Works now. Thanks! –  Nick Boutelier May 9 at 17:51

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.