Postgres - статьи




Общие замечания по программированию на С под PostgreSQL


Для понимания примеров мы приводим особенности написания пользовательских функций на языке C для PostgreSQL, полное описание можно найти в разделе C-Language Functions

документации.

Функции должны использовать интерфейс версии 1, версия 0 deprecated, хотя пока и поддерживается.

  • На уровне С PostgreSQL оперирует с базовыми типами данных

    или 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 );

  • Длинные значения типов с переменной длиной могут "тоститься", то есть нарезаться маленькими кусочками (TOAST - The Oversized Attribute Storage Technique, подробнее). Макросы для встроенных типов учитывают эту возможность, для user-defined это должно указываться непосредственно:
    SOMETYPE *ptr = (SOMETYPE*)PG_DETOAST_DATUM( DatumGetPointer(datum) );

  • Для работы с типами переменной длины есть дополнительные макросы:
    • VARSIZE( ptr ) - размер в байтах
    • VARDATA( ptr ) - возвращает указатель на данные после поля длины.
    • Т.е., если для типа определена структура: typedef struct { int32 length; char data[1]; } FOO; FOO *foo = f();

      то f->length == VARSIZE(f) и f->data == (char*)VARDATA(f) всегда. Заметим, что длина поля не может превышать 1Gb. Два бита в поле длина используются PostgreSQL в своих целях.

    • Функция должна возвращать тип Datum и объявляться как:




      Содержание  Назад  Вперед