1

Can anyone share an example how I can create C function for PostgreSQL which takes array of two integers as input and returns array as output?

For simple integer I have:

#include "postgres.h"
#include <fmgr.h>

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

int
add_one(int arg) {
    arg++;
    return arg;
}

And after compilation in PostgreSQL:

load '/usr/lib/postgresql/9.1/lib/add_one';

    create or replace function add_one(integer)
      returns integer as
    '/usr/lib/postgresql/9.1/lib/add_one', 'add_one'
      language c;

    select add_one(1);

I need something like:

#include "postgres.h"
#include <fmgr.h>

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

int
add_one(int[] arg) {
    arg[1]++;
    arg[2] = arg[2] + 2
    return arg[];
}

And in PostgreSQL:

load '/usr/lib/postgresql/9.1/lib/add_one';

create or replace function add_one(integer[])
     returns integer[] as
    '/usr/lib/postgresql/9.1/lib/add_one', 'add_one'
      language c;

    select add_one(ARRAY[1::int,1::int]);

I have tried to modify some function from numeric.c, but without any success so far.

1 Answer 1

7

Your code won't even remotely begin to work as written. PostgreSQL doesn't pass Pg-level arrays as int[], it passes them via the function context in PG_FUNCTION_ARGS (fcinfo) and they're accessed via PG_GETARG_ARRAYTYPE_P macros.

For basic extension function guidance see the docs on C language functions.

Take a look at the definition of array_cat in src/backend/utils/adt/array_userfuncs.c, or array_remove in src/backend/utils/adt/arrayfuncs.c. Or numerous other options.

Your skeleton will look something like:

PG_FUNCTION_INFO_V1(add_arrays);

Datum
add_arrays(PG_FUNCTION_ARGS)
{
    ArrayType  *array1, *array2, *resultarray;

    array1 = PG_GETARG_ARRAYTYPE_P(0);
    array2 = PG_GETARG_ARRAYTYPE_P(1);

    /* Loop over the array bodies and do your mapping to generate resultarray here */

    PG_RETURN_ARRAYTYPE_P(resultarray);
}

The PostgreSQL C array API is awful so I won't have time to fill out the function body. The point is that your function signature is dead wrong - you've totally misunderstood how it works, and what you wrote can't possibly even get executed.

It'd then be declared as:

create or replace function add_arrays(integer[], integer[])
returns integer[] as
'add_arrays', 'add_arrays'
language c immutable strict;

The strict is important; the function skeleton I provided doesn't check for null inputs, so you need to tell the executor not to invoke it with them.

It'd be nice if array_map from src/backend/utils/adt/arrayfuncs.c had a map2 or zip variant that did lockstep iteration of two arrays. Unfortunately it doesn't, so you'll need to iterate over them yourself.

After re-reading your question I'm now wondering if you mean a single array of int[] with two elements and you want the integer result that is the sum of the array. If so, take a look at how the intarray module works; it has simplified functions for handling simple integer arrays.

4
  • Thank you, your answer is really helpful. I would like to pass one array with 2 elements (two integers) to C function and get back also one array with 2 integers. Commented Dec 5, 2013 at 11:47
  • @TomasGreif ... and what happens to the integers? What does it do with the integers? Do you want to add a constant to them? In that case, you can use the array_map function to produce your result. Commented Dec 5, 2013 at 11:53
  • Adds 1 to 1st element and 2 to the 2nd element and returns elements in the same order. For [1,2] I expect [2,4] as result. Commented Dec 5, 2013 at 11:55
  • 1
    @TomasGreif OK, so you'll need to loop over the input array elements and assign values into the result array after constructing the result array. Browse the built-in array functions and those in intarray and you'll see a few useful examples. Commented Dec 5, 2013 at 12:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.