libpq:lo_open()返回0

时间:2018-02-17 11:48:00

标签: postgresql libpq

我正在尝试使用libpq创建大对象并遇到问题。在以下代码中:

Oid                 oid;
int                 fd;

oid = lo_creat( pgConn, INV_READ | INV_WRITE );
fd = lo_open( pgConn, oid , INV_WRITE );

lo_open()返回0,这不是根据文档的错误,但是导致后续的lo_write()失败并且"无效的描述符"错误。

我读到了关于函数"在SQL事务块中发生的事情"并试图在

中包围我的代码
PQexec( pgConn, "BEGIN" );
...
PQexec( pgConn, "COMMIT" );

事情发生了变化。 lo_open()仍然返回0,但是如果我再次立即调用它,它就可以了!

阅读也是如此。

我觉得我错过了什么,但无法猜出是什么。

UPD:从下面的答案运行代码后,我发现0是一个有效的描述符,我得到了初始错误,因为我没有明确启动事务。 令人惊讶的是,我必须打电话给#34; BEGIN"和" COMMIT"在阅读大型物品时也是如此。

1 个答案:

答案 0 :(得分:1)

如果您没有检查或引用错误消息,很难告诉您任何事情。

请尝试此SSCCE并从那里开始:

#include <stdio.h>
#include <stdlib.h>

#include <libpq-fe.h>
#include <libpq/libpq-fs.h>

void check_PGconn(PGconn *conn, ConnStatusType status_ok, char* errmsg)
{
    if (PQstatus(conn) != status_ok) {
        if (errmsg!=NULL) {
            fprintf(stderr, "%s: %s", errmsg, PQerrorMessage(conn));
        } else {
            fprintf(stderr, "%s", PQerrorMessage(conn));
        }
        PQfinish(conn);
        exit(1);
    }
}

int check_PGresult(PGconn *conn, PGresult *res, ExecStatusType status_ok, char* errmsg)
{
    if (PQresultStatus(res) != status_ok) {
        if (errmsg!=NULL) {
            fprintf(stderr, "%s: %s", errmsg, PQerrorMessage(conn));
        } else {
            fprintf(stderr, "%s", PQerrorMessage(conn));
        }
        return 0;
    }
    return 1;
}

int main(int argc, char** argv)
{
    char* conninfo;
    PGconn* conn;
    PGresult* res;
    int res_ok;
    Oid loid;
    int lofd;
    int lo_res;
    static char lo_content[] = "Lorem ipsum dolor sit amet, fabulas conclusionemque ius ad.";

    if (argc > 1) conninfo = argv[1]; else conninfo = "";

    conn = PQconnectdb(conninfo);
    check_PGconn(conn, CONNECTION_OK, "Connection to database failed");

    /* Create large object */

    res = PQexec(conn, "BEGIN");
    res_ok = check_PGresult(conn, res, PGRES_COMMAND_OK, "BEGIN failed");
    if ( !res_ok ) exit(1);
    PQclear(res);

    loid = lo_creat(conn, INV_READ|INV_WRITE);
    if (loid == 0) {
        fprintf(stderr, "lo_creat failed: %s", PQerrorMessage(conn));
        exit(1);
    }

    lofd = lo_open(conn, loid, INV_WRITE);
    if ( lofd == -1 ) {
        fprintf(stderr, "lo_open failed: %s", PQerrorMessage(conn));
        exit(1);
    }

    lo_res = lo_write(conn, lofd, lo_content, sizeof(lo_content));
    if ( lo_res == -1 ) {
        fprintf(stderr, "lo_write failed: %s", PQerrorMessage(conn));
        exit(1);
    }

    lo_res = lo_close(conn, lofd);
    if ( lo_res == -1 ) {
        fprintf(stderr, "lo_close failed: %s", PQerrorMessage(conn));
        exit(1);
    }

    res = PQexec(conn, "COMMIT");
    res_ok = check_PGresult(conn, res, PGRES_COMMAND_OK, "COMMIT failed");
    if ( !res_ok ) exit(1);
    PQclear(res);

    /* Delete large object */

    res = PQexec(conn, "BEGIN");
    res_ok = check_PGresult(conn, res, PGRES_COMMAND_OK, "BEGIN failed");
    if ( !res_ok ) exit(1);
    PQclear(res);

    lo_res = lo_unlink(conn, loid);
    if ( lo_res == -1 ) {
        fprintf(stderr, "lo_unlink failed: %s", PQerrorMessage(conn));
        exit(1);
    }

    res = PQexec(conn, "COMMIT");
    res_ok = check_PGresult(conn, res, PGRES_COMMAND_OK, "COMMIT failed");
    if ( !res_ok ) exit(1);
    PQclear(res);

    PQfinish(conn);
}