I define a variable length user-defined data type in postgresql according to the docs (http://www.postgresql.org/docs/9.0/static/xtypes.html)
C definition:
typedef struct MyType {
char vl_len_[4];
char data[1];
} mytype;
CREATE TYPE statements
CREATE TYPE mytype;
CREATE FUNCTION mytype_in(cstring) RETURNS mytype AS 'mytype' LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION mytype_out(mytype) RETURNS cstring AS 'mytype' LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION mytype_recv(internal) RETURNS mytype AS 'mytype' LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION mytype_send(mytype) RETURNS bytea AS 'mytype' LANGUAGE C IMMUTABLE STRICT;
CREATE TYPE mytype (
internallength = VARIABLE,
input = mytype_in,
output = mytype_out,
receive = mytype_recv,
send = mytype_send,
alignment = int4
,storage = plain
);
And I also define the functions in C. All of these work well. However, since my data could be very long, I change the storage from plain to external or extended . Then it outputs wrong result. Is there some TOAST function I need to use in my C-functions?
For example:
I have an operator to merge two values as follows:
PG_FUNCTION_INFO_V1(mytype_add);
Datum
mytype_add(PG_FUNCTION_ARGS)
{
mytype *anno1 = (mytype *) PG_GETARG_POINTER(0);
mytype *anno2 = (mytype *) PG_GETARG_POINTER(1);
mytype *result;
int newsize;
newsize = VARSIZE(anno1) + VARSIZE(anno2) - VARHDRSZ;
result = (mytype *) palloc(newsize);
SET_VARSIZE(result, newsize);
memcpy(result->data, anno1->data, VARSIZE(anno1) - VARHDRSZ);
memcpy((result->data + VARSIZE(anno1) - VARHDRSZ), anno2->data, VARSIZE(anno2) - VARHDRSZ);
PG_RETURN_POINTER(result);
}
The values in the anno1->data (12 bytes, 3 integers) are: 10, -1, -1, the values in anno2->data are: 20, -1, -1
So the values in result->data (24 bytes) are: 10,-1,-1,20,-1,-1
If I set the storage as plain, I got above correct result. If I set the storage as external, the output is totally wrong: -256,-1,1317887 ...
Thanks very much if anyone can give any hint. I have spend many hours on this