2012-01-05 18 views
7

我正在爲PostgreSQL寫一個C擴展(v 8.4)。我目前堅持如何將PostgreSQL的柱狀數據傳遞給我的C函數。我也有一個內存所有權的問題,因爲PostgreSQL似乎做了很多內存管理。爲PostgreSQL實現C擴展函數 - 我該如何做? (在C/PostgreSQL之間傳遞數據)

如果有人能幫助我「加入點」,我將不勝感激,以獲得一個基本的骨架代碼庫,我可以從中建立庫。

這是我到目前爲止有:

/*******************************************************/ 
/*     C header file      */ 
/*******************************************************/ 
typedef struct _myarray 
{ 
    double *data; 
    size_t len; 
} MyArray; 


MyArray * NEW_MyArray(const size_t len); 
void Destroy_MyArray(MyArray * arr); 
size_t NumElements_MyArray(MyArray * arr);  /* trivial function returns number of elements */ 
MyArray * NotTrivial_MyArray(MyArray * arr); /* non trivial function returns MyArray (a float8[] in PG) */ 
double HeapFunc_MyArray(MyArray * arr);   /* allocs from heap */ 


/*******************************************************/ 
/*     C Source file      */ 
/*******************************************************/ 

/* utility conversion funcs */ 
/* How do I convert from the structure returned by array_agg to float8[] (or int4[] ?) */ 


MyArray * NEW_MyArray(const size_t len){ 
    /* Do I use palloc0() or calloc() here ? */ 
} 

void Destroy_MyArray(MyArray * arr){ 
    /* Do I use pfree() or free() here ? */ 
} 

size_t NumElements_MyArray(MyArray * arr){ 
    assert(arr != 0); 
    return arr->len; 
} 

MyArray * NotTrivial_MyArray(MyArray * arr){ 
    assert(arr != 0); 
    MyArray * ptr = NEW_MyArray(arr->len); 
    return ptr; 
} 

double HeapFunc_MyArray(MyArray * arr){ 
    /* Create temporary variables on heap (use palloc0() or calloc()?) */ 
    /* Cleanup temp variables (use pfree() or free() ? */ 
    return 42/1.0; 
} 



/*******************************************************/ 
/* PostgreSQL wrapper funcs implementation source file */ 
/*******************************************************/ 

/* Prototypes */ 
PG_FUNCTION_INFO_V1(test_num_elements); 
PG_FUNCTION_INFO_V1(test_not_trivial); 
PG_FUNCTION_INFO_V1(test_heapfunc); 

Datum test_num_elements(PG_FUNCTION_ARGS); 
Datum test_not_trivial(PG_FUNCTION_ARGS); 
Datum test_heapfunc(PG_FUNCTION_ARGS); 


Datum 
test_num_elements(PG_FUNCTION_ARGS) 
{ 
    /* Convert data returned by array_agg() into MyArray * (how?) */ 
    /* invoke NumElements_MyArray() */ 
    /* Do I free temporary MyArray * ptr or will PG clean up 
     - if I have to clean up (like I suspect), do I use pfree() or free() ?*/ 
    PG_RETURN_INT32(result); 
} 

Datum 
test_not_trivial(PG_FUNCTION_ARGS) 
{ 
    /* Ditto, as above */ 
    PG_RETURN_POINTER(/* utility function to convert MyArray* to float8[] equiv for PG (how) */); 
} 

Datum 
test_heapfunc(PG_FUNCTION_ARGS) 
{ 
    /* Ditto, as above */ 
    PG_RETURN_FLOAT8(result); 
} 


-- SQL FUNCTIONS 

CREATE OR REPLACE FUNCTION test_num_elements(float8[]) RETURNS int4 
AS '$libdir/pg_testlib.so' LANGUAGE 'c'; 

CREATE OR REPLACE FUNCTION test_not_trivial(float8[]) RETURNS float8[] 
AS '$libdir/pg_testlib.so' LANGUAGE 'c'; 

CREATE OR REPLACE FUNCTION test_heapfunc(float8[]) RETURNS float8 
AS '$libdir/pg_testlib.so' LANGUAGE 'c'; 


-- SQL TEST 
SELECT test_num_elements(array_agg(salary)) FROM employees; 
SELECT test_not_trivial(array_agg(salary)) FROM employees; 
SELECT test_heapfunc(array_agg(salary)) FROM employees; 

總之,我的問題是:

  1. 如何轉換的列數據從ARRAY_AGG()到雙打的C數組(或ints)
  2. 如何將C數組中的整數(或雙精度)轉換回int4 []或float8 []以便在PostgreSQL中使用?
  3. 內存分配原則 - 我使用PostgreSQL內存管理函數palloc()/ pfree()還是可以使用calloc/free ?.另外,當使用PG mem funcs時,我是否負責釋放分配的內存?

回答

1

首先,您應該始終使用palloc/pfree來管理內存。 PostgreSQL不會爲你管理內存,但是每個連接都是由一個獨立的進程來處理的,所以如果你泄漏內存,它只會持續一個連接的生命週期(授予,可能會很長)。

通常情況下,一個分配數據:

MyArray *myarr = (MyArray*) VARDATA(data); 

一旦你完成,你可以:

PG_RETURN_POINTER(data); 

如果返回

void *data = palloc(size_of_your_data + VARHDRSZ); 
SET_VARSIZE(data, size_of_your_data + VARHDRSZ); 

,然後使用訪問您的數據數據,你不會釋放它。如果你想要暫時儲存,你必須取消它。

現在,MyArray是不是你想要有一個float8[]。您需要使用ArrayType,如 34.9.11. Polymorphic Arguments and Return Types中所述。