Как вернуть массив в массив с пользовательским типом в Postgres C Function? - PullRequest
0 голосов
/ 02 июля 2018

Пожалуйста, помогите мне решить проблему возврата встроенного массива. Простой массив для возврата изученного, а затем проблема.

// CREATE TYPE libc_collect_item AS (goods_id bigint, priority integer); -- succsess.
// CREATE TYPE libc_collect AS (collect_number integer, collect_items libc_collect_item[]); -- how to?

//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);
}

Вероятно, вам нужно как-то создать встроенный массив и вставить его вместо valueItem [1]. Он изучал различные примеры, но ни один из них не подходит.

Мне нужна функция, которая будет возвращать libc_collect []:

//CREATE OR REPLACE FUNCTION f_get_collects() RETURNS SETOF libc_collect[]  AS 'lib', 'f_get_collects' LANGUAGE C STRICT STABLE;

================================= Я стараюсь:

ArrayType* createArray(/*FunctionCallInfo fcinfo, */vector collectionList)
{
Oid outputTypeId;

    //Temporary hadrcoded
    Oid outputBaseTypeId = 106553;
    Oid outputBaseTypRelId = 106551;

    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;
}

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);
}

И получите ошибку: ..... Информация: кол-во: 2 Информация: outputBaseTypeId: 106556

ОШИБКА: ошибка поиска в кэше для типа 4294967295

1 Ответ

0 голосов
/ 04 июля 2018
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));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...