Как написать Postgres пользовательский тип с массивом - PullRequest
1 голос
/ 11 марта 2020

Я пишу пользовательский тип в Postgres с именем personname:

#define FLXIBLE_ARRAY_MEMBER 0

PG_MODULE_MAGIC;

typedef struct personname{
    int familyLen;
    int givenLen;
    int givenStart;
    char pname[FLXIBLE_ARRAY_MEMBER];
}personname;

Я пишу свои функции personname_in и personname_out примерно так:

PG_FUNCTION_INFO_V1(pname_in);

Datum
pname_in(PG_FUNCTION_ARGS){
    char* str = PG_GETARG_CSTRING(0);
    personname *name;
    ...
    name = (personname*) palloc(sizeof(personname) + strlen(str) + 1);
    name->familyLen = familyNameLen;
    name->givenLen = givenNameLen;
    name->givenStart = givenNameStart;

    strcpy(name->pname, str);

    PG_RETURN_POINTER(name);
}

PG_FUNCTION_INFO_V1(pname_out);

Datum
pname_out(PG_FUNCTION_ARGS){
    personname *name = (personname*) PG_GETARG_POINTER(0);

    char* family = getFamily(name);
    char* given = getGiven(name);
    char* nameStr;   
    nameStr = psprintf("%s,%s", family, given);

    pfree(family);
    pfree(given);

    PG_RETURN_CSTRING(nameStr);
}

И мой sql выглядит следующим образом:

CREATE FUNCTION pname_in(cstring)
   RETURNS personname
   AS '_OBJWD_/pname'
   LANGUAGE C IMMUTABLE STRICT;

CREATE FUNCTION pname_out(personname)
   RETURNS cstring
   AS '_OBJWD_/pname'
   LANGUAGE C IMMUTABLE STRICT;

CREATE TYPE personname (
   internallength = 12,
   input = pname_in,
   output = pname_out
);

Теперь мой код может правильно ответить select "NAME" :: personname;, а когда я вставляю и выбираю, он может правильно обращаться ко всем аргументам в namename, кроме массива pname.

Я создаю таблицу с именем users, которая содержит массив pname, когда я набираю select * from users; это показывает это:

enter image description here

Однако, когда я копирую и вставляю свой код personname_in и personname_out в другой файл c, замените pallo c на mallo c и протестируйте его с некоторой входной строкой из терминала, он может вывести правильное значение pname.

Может кто-нибудь сказать мне, где я сделал неправильно, или как правильно создать новый тип в PostgreSQL с массивом?

1 Ответ

1 голос
/ 11 марта 2020

Оператор CREATE TYPE не соответствует коду, а 4-байтовый заголовок varlena отсутствует.

Какова документация :

Хотя детали внутреннего представления нового типа известны только функциям ввода-вывода и другим функциям, которые вы создаете для работы с типом, существует несколько свойств внутреннего представления, которые должны быть объявлены в PostgreSQL. Прежде всего это internallength. Базовые типы данных могут быть фиксированной длины, в этом случае internallength - это положительное целое число или переменная длина, указанная установкой internallength до VARIABLE. (Внутренне это представляется установкой typlen в -1.) Внутреннее представление всех типов переменной длины должно начинаться с 4-байтового целого числа, дающего общую длину этого значения типа. (Обратите внимание, что поле длины часто кодируется, как описано в разделе 68.2; неразумно обращаться к нему напрямую.)

Вы должны определить тип с помощью

INTERNALLENGTH = VARIABLE

и Структура должна начинаться с 4-байтового целого числа.

Я не проверял другие ошибки.

...