PostgreSQL Сохранение и выбор файлов в виде больших объектов с помощью C libpq

Работаю над этим вопросом уже 2 недели безрезультатно. Кто-нибудь знает, как управлять lipq с блобами или байтами без потери формата и каких-либо данных? Размер экспортируемого файла 0B, я не могу понять шаги, которые я должен выполнить, чтобы загрузить файл в базу данных postgreSQL из C и снова выбрать его с правильным форматом и функциями. Любая помощь будет отличной. Я перепробовал почти все примеры и теории в сети, даже документы и руководства по PG, но никак. Я близок к тому, чтобы бросить программирование и заняться фермерством (не шучу xD). Заранее спасибо.

‹CODE EDITED поддерживает транзакцию открытой 24-5-21›

После модификации кода я выбираю файл на 59 байт выше, чем файл, загруженный как большой объект. Чувствую, что стал ближе, но передумал об использовании больших объектов.

#include "libpq/libpq-fs.h"
#include "libpq-fe.h"

int main(int argc, char* argv[])
{
    //*************************** IMPORT TEST **********
    manager.conn = manager.ConnectDB();  // my manager, working fine    

    Oid blob;
    char* picName = new char[]{ "powerup.png" };
    PGresult* res;

    ress = PQexec(manager.conn, "begin");
    PQclear(res);

    blob = lo_import(manager.conn, "powerup.png");
    cout << endl << "import returned oid " << blob;

    //res = PQexec(manager.conn, "end");
    //PQclear(res);

    string sentenceB = "INSERT INTO testblob(filename, fileoid) VALUES('powerup.png', '" + std::to_string(blob) + "')";

    manager.GenericQuery(manager.conn, sentenceB); //same as PQexec + result evaluation, works ok
    PQclear(res);

    //*************************** EXPORT TEST **********

    OidManager oidm;

    oidm.exportFile(manager.conn, blob, picName);  // Ill show the function content at the end

    res = PQexec(manager.conn, "end"); //SAME TRANSACTION TO AVOID LOSING THE OID, CHANGES AFTER TRANSACTION...
    PQclear(res);

    manager.CloseConn(manager.conn);   // my manager, works fine

    return true;
}

    // oidm.exportFile() FUNCTION DETAIL
    // code from: 35.5 Example Program Chapter 34 Large Objects
    // https://www.postgresql.org/docs/10/lo-examplesect.html

void OidManager::exportFile(PGconn* conn, Oid lobjId, char* filename)
{
    int         lobj_fd;
    char        buf[BUFSIZE];
    int         nbytes,
        tmp;
    int         fd;

    /*
     * open the large object
     */
    lobj_fd = lo_open(conn, lobjId, INV_READ);
    if (lobj_fd < 0)
        fprintf(stderr, "cannot open large object %u", lobjId);

    /*
     * open the file to be written to
     */
    fd = _open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
    if (fd < 0)
    {                           /* error */
        fprintf(stderr, "cannot open unix file\"%s\"",
            filename);
    }

    /*
     * read in from the inversion file and write to the Unix file
     */
    while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) > 0)
    {
        tmp = _write(fd, buf, nbytes);
        if (tmp < nbytes)
        {
            fprintf(stderr, "error while writing \"%s\"",
                filename);
        }
    }

    lo_close(conn, lobj_fd);
    _close(fd);

    return;
}


person Kornelius    schedule 20.05.2021    source источник
comment
Вы можете найти решение рекомендации, сделанной @Laurenz Albe, избегая использования BLOBS и выполняя работу с типом слота базы данных BYTEA по этой [ссылке] stackoverflow.com/questions/67673603/ Спасибо.   -  person Kornelius    schedule 27.05.2021


Ответы (1)


Например, в документации говорится:

Дескриптор действителен только в течение текущей транзакции.

Таким образом, вы должны вызывать lo_open и lo_read в одной и той же транзакции.

Не используйте большие предметы. Они работают медленно, сложны в использовании и дают у вас всякие серьезные проблемы (например, если у вас их много). Используйте bytea, тогда ваш код станет намного проще.

person Laurenz Albe    schedule 20.05.2021
comment
Большое спасибо за ответ, я помню, что читал некоторые ваши сообщения раньше :) Я попытался через минуту закрыть транзакцию после exportFile(). На этот раз размер экспортируемого файла больше на 59 байт ._.' и не может быть распознан как изображение. Мне нужно покинуть офис, но я проверю это первым делом завтра. - person Kornelius; 20.05.2021
comment
В случае, если мне удалось выбрать файл с правильными двоичными данными, работающими правильно, мне придется выяснить, как найти mi oids, если сохраненные идентификаторы не совпадают с теми, которые я храню в таблице «testblob» после завершения транзакций. Я много работал раньше, пытаясь сделать это с таблицей со слотом bytea с необработанными байтами, но безуспешно. Завтра я подготовлю фрагмент кода, показывающий, что я пытался сделать с проблемой bytea. Я надеюсь понять, что я делаю плохо, прежде чем меня уволят xDDD - person Kornelius; 20.05.2021
comment
Я изучу все ваши ссылки, прежде чем публиковать свои попытки bytea. Еще раз спасибо @Laurenz Albe ;) - person Kornelius; 20.05.2021