Гость
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Как вернуть массив массивов из C-фунции для Postgres / 4 сообщений из 4, страница 1 из 1
02.07.2018, 00:20
    #39668110
Azimuth
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как вернуть массив массивов из C-фунции для Postgres
Возвращать массив (1) я научился, а как положить его внутрь другого (2) не получается.
1: CREATE TYPE libc_collect_item AS (goods_id bigint, priority integer);
2: CREATE TYPE libc_collect AS (collect_number integer, collect_items libc_collect_item[]);

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
//CREATE OR REPLACE FUNCTION f_get_collects() RETURNS SETOF libc_collect_item[]  AS 'lib', 'f_get_collects' LANGUAGE C STRICT STABLE;
PG_FUNCTION_INFO_V1(f_get_collects);
Datum
f_get_collects(PG_FUNCTION_ARGS)
{
    //....
    TupleDesc tupleDesc;
    Oid outputTypeId;
    get_call_result_type(fcinfo, &outputTypeId, &tupleDesc);
 
    Oid outputBaseTypeId = get_base_element_type(outputTypeId);
    Oid outputBaseTypRelId = get_typ_typrelid(outputBaseTypeId);
 
    int16 typlen;
    bool typbyval;
    char typalign;
    get_typlenbyvalalign(outputBaseTypeId, &typlen, &typbyval, &typalign);
 
    const char* attributeNameOne = get_relid_attribute_name(outputBaseTypRelId, 1);
    const char* attributeNameTwo = get_relid_attribute_name(outputBaseTypRelId, 2);
 
    Oid attributeOneOid = get_atttype(outputBaseTypRelId, 1);
    Oid attributeTwoOid = get_atttype(outputBaseTypRelId, 2);
 
    int32 attributeOneTypMod = get_atttypmod(outputBaseTypRelId, 1);
    int32 attributeTwoTypMod = get_atttypmod(outputBaseTypRelId, 2);
 
    TupleDesc my_tupleDesc = CreateTemplateTupleDesc(2, false);
    TupleDescInitEntry(my_tupleDesc, 1, attributeNameOne, attributeOneOid, attributeOneTypMod, 0);
    TupleDescInitEntry(my_tupleDesc, 2, attributeNameTwo, attributeTwoOid, attributeTwoTypMod, 0);
 
    my_tupleDesc = BlessTupleDesc(my_tupleDesc);
 
    vector<OutCollection> collectionList;
    OutCollection item(100002, 1);
    collectionList.push_back(item);
 
    OutCollection item2(100003, 2);
    collectionList.push_back(item2);
 
    Datum* pResultDatums = (Datum*)palloc(sizeof(Datum) * (int)collectionList.size());
    for(int i =0; i < (int)collectionList.size(); i++){
        Datum* valueItem = (Datum*) palloc(sizeof(Datum) *2);
        valueItem[0] = collectionList[i].orderItemId;
        valueItem[1] = collectionList[i].priority;
 
        bool* isNullItem = (bool*) palloc(sizeof(bool) * 2);
        isNullItem[0] = false;
        isNullItem[1] = false;
 
        HeapTuple resultHeapTupleItem = heap_form_tuple(my_tupleDesc, valueItem, isNullItem);
        my_tupleDesc = BlessTupleDesc(my_tupleDesc);
 
        pResultDatums[i] = HeapTupleGetDatum(resultHeapTupleItem);
    }
    ArrayType* pResult = construct_array(pResultDatums, collectionList.size(), outputBaseTypeId, typlen, typbyval, typalign);
    PG_RETURN_ARRAYTYPE_P(pResult);
}
...
Рейтинг: 0 / 0
03.07.2018, 22:33
    #39669139
Azimuth
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как вернуть массив массивов из C-фунции для Postgres
Сделал следующее:
// Генерим массив который будем вкладывать.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
ArrayType* createArray(/*FunctionCallInfo fcinfo, */vector collectionList)
{
Oid outputTypeId;

    //Типы пока захардкожены
    Oid outputBaseTypeId = 106553; get_base_element_type(outputTypeId);
    Oid outputBaseTypRelId = 106551; get_typ_typrelid(outputBaseTypeId);

    int16 typlen;
    bool typbyval;
    char typalign;
    get_typlenbyvalalign(outputBaseTypeId, &typlen, &typbyval, &typalign);

    const char* attributeNameOne = "goods_id"; get_relid_attribute_name(outputBaseTypRelId, 1);
    const char* attributeNameTwo = "priority"; get_relid_attribute_name(outputBaseTypRelId, 2);
    ereport(INFO, (errmsg("Attribute names: %s %s ", attributeNameOne, attributeNameTwo)));

    Oid attributeOneOid = 20; get_atttype(outputBaseTypRelId, 1);
    Oid attributeTwoOid = 23; get_atttype(outputBaseTypRelId, 2);

    int32 attributeOneTypMod = get_atttypmod(outputBaseTypRelId, 1);
    int32 attributeTwoTypMod = get_atttypmod(outputBaseTypRelId, 2);

    TupleDesc my_tupleDesc = CreateTemplateTupleDesc(2, false);
    TupleDescInitEntry(my_tupleDesc, 1, attributeNameOne, attributeOneOid, attributeOneTypMod, 0);
    TupleDescInitEntry(my_tupleDesc, 2, attributeNameTwo, attributeTwoOid, attributeTwoTypMod, 0);

    my_tupleDesc = BlessTupleDesc(my_tupleDesc);

    Datum* pResultDatums = (Datum*)palloc(sizeof(Datum) * (int)collectionList.size());
    return pResult;
}



Пытаюсь воткнуть массив в элемент массива, предварительно его разобрав, чтобы получить Datum
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
PG_FUNCTION_INFO_V1(f_sys_collects_generate_single_simple2);
Datum
f_sys_collects_generate_single_simple2(PG_FUNCTION_ARGS)
{
    vector<OutCollection> collectionList;
    OutCollection item(100002, 1);
    collectionList.push_back(item);

    OutCollection item2(100003, 2);
    collectionList.push_back(item2);

    TupleDesc tupleDesc;
    Oid outputTypeId;
    get_call_result_type(fcinfo, &outputTypeId, &tupleDesc);

    Oid outputBaseTypeId = get_base_element_type(outputTypeId);
    Oid outputBaseTypRelId = get_typ_typrelid(outputBaseTypeId);

    int16 typlen;
    bool typbyval;
    char typalign;
    get_typlenbyvalalign(outputBaseTypeId, &typlen, &typbyval, &typalign);

    const char* attributeNameOne = get_relid_attribute_name(outputBaseTypRelId, 1);
    const char* attributeNameTwo = get_relid_attribute_name(outputBaseTypRelId, 2);

    Oid attributeOneOid = get_atttype(outputBaseTypRelId, 1);
    Oid attributeTwoOid = get_atttype(outputBaseTypRelId, 2);

    int32 attributeOneTypMod = get_atttypmod(outputBaseTypRelId, 1);
    int32 attributeTwoTypMod = get_atttypmod(outputBaseTypRelId, 2);
    ereport(INFO, (errmsg("Attribute type mods: %i %i ", attributeOneTypMod, attributeTwoTypMod)));

    TupleDesc my_tupleDesc = CreateTemplateTupleDesc(2, false);
    TupleDescInitEntry(my_tupleDesc, 1, attributeNameOne, attributeOneOid, attributeOneTypMod, 0);
    TupleDescInitEntry(my_tupleDesc, 2, attributeNameTwo, attributeTwoOid, attributeTwoTypMod, 0);

    my_tupleDesc = BlessTupleDesc(my_tupleDesc);

    Datum* pResultDatums = (Datum*)palloc(sizeof(Datum) * (int)collectionList.size());

    for(int i =0; i < (int)collectionList.size(); i++){
        Datum* valueItem = (Datum*) palloc(sizeof(Datum) *2);
        valueItem[0] = i;
        ArrayType* pResult2 = createArray(/*fcinfo, */collectionList);
        Datum* datums;
        Oid elemType = 106553;
        int16    elemWidth;
        bool    elemTypeByVal;
        char    elemAlignmentCode;
        bool*    nulls;
        int        count;

        get_typlenbyvalalign(elemType, &elemWidth, &elemTypeByVal, &elemAlignmentCode);
        ereport(INFO, (errmsg("elemType: %i", elemType)));
        ereport(INFO, (errmsg("elemWidth: %i", elemWidth)));
        ereport(INFO, (errmsg("elemTypeByVal: %i", elemTypeByVal)));
        deconstruct_array(pResult2, elemType, elemWidth, elemTypeByVal, elemAlignmentCode, &datums, &nulls, &count);
        ereport(INFO, (errmsg("count: %i", count)));
        valueItem[1] = *datums;

        bool* isNullItem = (bool*) palloc(sizeof(bool) * 2);
        isNullItem[0] = false;
        isNullItem[1] = false;

        HeapTuple resultHeapTupleItem = heap_form_tuple(my_tupleDesc, valueItem, isNullItem);
        my_tupleDesc = BlessTupleDesc(my_tupleDesc);

        pResultDatums[i] = HeapTupleGetDatum(resultHeapTupleItem);
        ereport(INFO, (errmsg("outputBaseTypeId: %d", outputBaseTypeId)));
    }
    ArrayType* pResult = construct_array(pResultDatums, collectionList.size(), outputBaseTypeId, typlen, typbyval, typalign);

    PG_RETURN_ARRAYTYPE_P(pResult);
}



Получаю:
......
ИНФОРМАЦИЯ: elemType: 106553
ИНФОРМАЦИЯ: elemWidth: -1
ИНФОРМАЦИЯ: elemTypeByVal: 0
ИНФОРМАЦИЯ: count: 2
ИНФОРМАЦИЯ: outputBaseTypeId: 106556
ИНФОРМАЦИЯ: Object type of the return type: 0
ИНФОРМАЦИЯ: Object base type of the return type: 106553
ИНФОРМАЦИЯ: Object base type rel id of the return type: 106551
ИНФОРМАЦИЯ: Attribute names: goods_id priority
ИНФОРМАЦИЯ: Attribute oids: 20 23
ИНФОРМАЦИЯ: Attribute type mods: -1 -1
ИНФОРМАЦИЯ: elemType: 106553
ИНФОРМАЦИЯ: elemWidth: -1
ИНФОРМАЦИЯ: elemTypeByVal: 0
ИНФОРМАЦИЯ: count: 2
ИНФОРМАЦИЯ: outputBaseTypeId: 106556
ОШИБКА: cache lookup failed for type 4294967295

Понятное дело, что этого типа в базе нет и быть не может.
...
Рейтинг: 0 / 0
04.07.2018, 10:29
    #39669293
kolobok0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как вернуть массив массивов из C-фунции для Postgres
AzimuthСделал следующее:.....

старый добрый постгресс, потроха движка... песня одним словом...

по поводу форумов - не скажу как сейчас а раньше было мало инфы по данной теме(написание своих инлайн функций).

по поводу вопроса - рекомендую заглянуть внутрь исходников самого постгресса. многие вещи приходилось тянуть оттуда. и разбираться "как оно по уму"...

удачи вам
(круглый)
...
Рейтинг: 0 / 0
04.07.2018, 16:09
    #39669565
Azimuth
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как вернуть массив массивов из C-фунции для Postgres
И снова-здорова. Сам спросил, сам отвечаю:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
ArrayType* createArray(const vector<OutCollection> collectionList, const Oid attributeTwoOid)
{
    int16 typlen = 0;;
    bool typbyval = false;
    char typalign;
    get_typlenbyvalalign(attributeTwoOid, &typlen, &typbyval, &typalign);

    const char* attributeNameOne = "a1";
    const char* attributeNameTwo = "a2";

    TupleDesc my_tupleDesc = CreateTemplateTupleDesc(2, false);
    TupleDescInitEntry(my_tupleDesc, 1, attributeNameOne, INT8OID, -1, 0);
    TupleDescInitEntry(my_tupleDesc, 2, attributeNameTwo, INT4OID, -1, 0);

    my_tupleDesc = BlessTupleDesc(my_tupleDesc);

    Datum* pResultDatums = (Datum*)palloc(sizeof(Datum) * (int)collectionList.size());
    for(int i =0; i < (int)collectionList.size(); i++){
        Datum* valueItem = (Datum*) palloc(sizeof(Datum) * 2);
        valueItem[0] = Int64GetDatum(collectionList[i].orderItemId);
        valueItem[1] = Int32GetDatum(collectionList[i].priority);

        bool* isNullItem = (bool*) palloc(sizeof(bool) * 2);
        isNullItem[0] = false;
        isNullItem[1] = false;

        HeapTuple resultHeapTupleItem = heap_form_tuple(my_tupleDesc, valueItem, isNullItem);
        pResultDatums[i] = HeapTupleGetDatum(resultHeapTupleItem);
        pfree(valueItem);
    }
    pfree(pResultDatums);
    return construct_array(pResultDatums, collectionList.size(), attributeTwoOid, typlen, typbyval, typalign);
}

PG_FUNCTION_INFO_V1(f_sys_collects_generate_simple);
Datum
f_sys_collects_generate_simple(PG_FUNCTION_ARGS)
{
    vector< vector<OutCollection> > baskets;
    baskets.push_back(collectionList);
    baskets.push_back(collectionList);

    TupleDesc tupleDesc = NULL;
    Oid outputTypeId = 0;
    get_call_result_type(fcinfo, &outputTypeId, &tupleDesc);

    Oid outputBaseTypeId = get_base_element_type(outputTypeId);
    Oid outputBaseTypRelId = get_typ_typrelid(outputBaseTypeId);

    int16 typlen = 0;
    bool typbyval = false;
    char typalign;
    get_typlenbyvalalign(outputBaseTypeId, &typlen, &typbyval, &typalign);

    const char* attributeNameOne = get_relid_attribute_name(outputBaseTypRelId, 1);
    const char* attributeNameTwo = get_relid_attribute_name(outputBaseTypRelId, 2);

    const Oid attributeOneOid = get_atttype(outputBaseTypRelId, 1);
    const Oid attributeTwoOid = get_atttype(outputBaseTypRelId, 2);

    const int32 attributeOneTypMod = get_atttypmod(outputBaseTypRelId, 1);
    const int32 attributeTwoTypMod = get_atttypmod(outputBaseTypRelId, 2);

    TupleDesc my_tupleDesc = CreateTemplateTupleDesc(2, false);
    TupleDescInitEntry(my_tupleDesc, 1, attributeNameOne, attributeOneOid, attributeOneTypMod, 0);
    TupleDescInitEntry(my_tupleDesc, 2, attributeNameTwo, attributeTwoOid, attributeTwoTypMod, 0);

    my_tupleDesc = BlessTupleDesc(my_tupleDesc);

    Datum* pResultDatums = (Datum*)palloc(sizeof(Datum) * (int)collectionList.size());

    for(int i =0; i < (int)baskets.size(); i++){
        Datum* valueItem = (Datum*) palloc(sizeof(Datum) *2);
        valueItem[0] = Int32GetDatum(i);

        ArrayType*    pResult2 = createArray(baskets.at(i), outputBaseTypeId);
        valueItem[1] = PointerGetDatum(pResult2);

        bool* isNullItem = (bool*) palloc(sizeof(bool) * 2);
        isNullItem[0] = false;
        isNullItem[1] = false;

        HeapTuple resultHeapTupleItem = heap_form_tuple(my_tupleDesc, valueItem, isNullItem);
        pResultDatums[i] = HeapTupleGetDatum(resultHeapTupleItem);
        pfree(isNullItem);
        pfree(valueItem);
    }
    pfree(pResultDatums);
    PG_RETURN_ARRAYTYPE_P(construct_array(pResultDatums, baskets.size(), outputBaseTypeId, typlen, typbyval, typalign));
}
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Как вернуть массив массивов из C-фунции для Postgres / 4 сообщений из 4, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]