Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

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.

share|improve this question
up vote 4 down vote accepted

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.

share|improve this answer
    
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. – Tomas Greif Dec 5 '13 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. – Craig Ringer Dec 5 '13 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. – Tomas Greif Dec 5 '13 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. – Craig Ringer Dec 5 '13 at 12:07

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.