繁体   English   中英

PostgreSQL 使用 C libpq 将文件保存并选择为大对象

[英]PostgreSQL Save and Pick files as large objects with C libpq

我自 2 周以来一直在处理这个问题,但没有任何结果。 有人知道如何在不丢失格式和任何数据的情况下使用带有 blob 或 bytea 的 lipq 进行管理吗? 导出的文件大小为 0B,我无法理解从 C 将文件上传到 postgreSQL 数据库并使用正确的格式和功能再次选择它必须遵循的步骤。 任何帮助都会很棒。 我尝试了网上的每一个例子和理论,甚至是 PG 文档和手册,没有办法。 我即将退出编程和 go 农民(不是开玩笑 xD)。 先感谢您。

<CODE EDITED mantaining transaction open 24-5-21>

修改代码后,我选择了一个比上传为大 object 的文件高 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;
}

就像文档说的那样:

描述符仅在当前事务期间有效。

所以你必须在同一个事务中调用lo_openlo_read

不要使用大物体。 它们速度慢,使用复杂,会给你带来各种严重的麻烦(例如, 如果你有很多)。 使用bytea ,你的代码会变得简单很多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM