Общие замечания по программированию на С под PostgreSQL
Для понимания примеров мы приводим особенности написания пользовательских функций на языке C для PostgreSQL, полное описание можно найти в разделе C-Language Functions
документации.
Функции должны использовать интерфейс версии 1, версия 0 deprecated, хотя пока и поддерживается.
или SQL-типами в представлении С-типа Datum. Datum имеет размер, равный размеру указателя на данной архитектуре (PostgreSQL не поддерживает архитектуры с указателем, меньшим 32 бит). SQL-типы в PostgreSQL делятся на передаваемые по значению и по указателю. Передаваемые по значению типы не должны превышать размер 32 бита. Передаваемые по указателю типы подразделяются на типы с фиксированной длиной и переменной. Для типов с переменной длиной первым полем всегда должна быть длина значения int4 (в байтах, с учетом размера поля длины). Для преобразования Datum в тип и обратно существует набор макросов, см.,например, файлы postgres.h, fmgr.h:
- int32 i = DatumGetInt32(datum);
- Datum datum = BoolGetDatum( true );
- text *sometext = DatumGetTextP( datum );
- Для абстрактного типа, передаваемого по указателю, можно использовать преобразование в указатель:
- SOMETYPE *ptr = (SOMETYPE*)DatumGetPointer(datum);
- Datum datum = PointerGetDatum( ptr );
SOMETYPE *ptr = (SOMETYPE*)PG_DETOAST_DATUM( DatumGetPointer(datum) );
Т.е., если для типа определена структура: typedef struct { int32 length; char data[1]; } FOO; FOO *foo = f();
то f->length == VARSIZE(f) и f->data == (char*)VARDATA(f) всегда. Заметим, что длина поля не может превышать 1Gb. Два бита в поле длина используются PostgreSQL в своих целях.
PG_FUNCTION_INFO_V1(function);
Datum function(PG_FUNCTION_ARGS);
....
/* * после того, как работа произведена, не плохо бы очистить память * "потостенных" значений, Аргументы: * первый - имя переменной-параметра функции, * второй - порядковый номер */ PG_FREE_IF_COPY(t,2); PG_FREE_IF_COPY(f,3);
PG_RETURN_INT32( i ); }