Postgresql libpq:lo_open()返回0

Postgresql libpq:lo_open()返回0,postgresql,libpq,Postgresql,Libpq,我试图使用libpq创建大型对象,但遇到了这个问题。在以下代码中: Oid oid; int fd; oid = lo_creat( pgConn, INV_READ | INV_WRITE ); fd = lo_open( pgConn, oid , INV_WRITE ); lou open()返回0,根据文档,这不是一个错误,但会导致后续的lou write()失败,并出现“Invalid descriptor”错误 我读

我试图使用libpq创建大型对象,但遇到了这个问题。在以下代码中:

Oid                 oid;
int                 fd;

oid = lo_creat( pgConn, INV_READ | INV_WRITE );
fd = lo_open( pgConn, oid , INV_WRITE );
lou open()返回0,根据文档,这不是一个错误,但会导致后续的lou write()失败,并出现“Invalid descriptor”错误

我读过关于函数“发生在SQL事务块中”的文章,并试图将代码封装在其中

PQexec( pgConn, "BEGIN" );
...
PQexec( pgConn, "COMMIT" );
事情变了。lo_open()仍然返回0,但如果我立即再次调用它,它就工作了

阅读也是如此

我觉得我错过了什么,但猜不出是什么

UPD:从下面的答案运行代码后,我突然发现0是一个有效的描述符,我得到了初始错误,因为我没有显式启动事务。
令人惊讶的是,在读取大型对象时,我也必须调用“开始”和“提交”。

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

请尝试此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);
}
#包括
#包括
#包括
#包括
无效检查\u PGconn(PGconn*conn,ConnStatusType status\u ok,char*errmsg)
{
如果(PQstatus(conn)!=状态\正常){
如果(errmsg!=NULL){
fprintf(stderr,“%s:%s”、errmsg、PQerrorMessage(conn));
}否则{
fprintf(stderr,“%s”,PQerrorMessage(conn));
}
PQfinish(conn);
出口(1);
}
}
int check_PGresult(PGconn*conn,PGresult*res,ExecStatusType status_ok,char*errmsg)
{
如果(PQresultStatus(res)!=状态\正常){
如果(errmsg!=NULL){
fprintf(stderr,“%s:%s”、errmsg、PQerrorMessage(conn));
}否则{
fprintf(stderr,“%s”,PQerrorMessage(conn));
}
返回0;
}
返回1;
}
int main(int argc,字符**argv)
{
char*coninfo;
PGconn*conn;
PGresult*res;
int res_ok;
单倍体;
int lofd;
国际劳工组织;
静态碳含量[]=“Lorem ipsum door sit amet,fabulas conclusionemque ius ad.”;
如果(argc>1)conninfo=argv[1];否则conninfo=“”;
conn=PQconnectdb(conninfo);
检查_PGconn(conn,CONNECTION_OK,“连接到数据库失败”);
/*创建大型对象*/
res=PQexec(连接,“开始”);
res_ok=检查结果(conn、res、PGRES_命令_ok,“开始失败”);
如果(!res_ok)退出(1);
PQclear(res);
loid=lo_创建(conn,INV_读取| INV_写入);
if(loid==0){
fprintf(标准,“lo_创建失败:%s”,PQerrorMessage(conn));
出口(1);
}
lofd=lo_打开(连接、loid、INV_写入);
如果(lofd==-1){
fprintf(标准,“lo_open failed:%s”,PQerrorMessage(conn));
出口(1);
}
lo_res=lo_写入(conn、lofd、lo_内容、sizeof(lo_内容));
如果(低分辨率==-1){
fprintf(标准,“lo_写入失败:%s”,PQerrorMessage(conn));
出口(1);
}
lo_res=lo_close(连接、lofd);
如果(低分辨率==-1){
fprintf(标准,“lo_关闭失败:%s”,PQerrorMessage(conn));
出口(1);
}
res=PQexec(conn,“提交”);
res_ok=检查结果(conn、res、PGRES_命令_ok,“提交失败”);
如果(!res_ok)退出(1);
PQclear(res);
/*删除大对象*/
res=PQexec(连接,“开始”);
res_ok=检查结果(conn、res、PGRES_命令_ok,“开始失败”);
如果(!res_ok)退出(1);
PQclear(res);
lo_res=lo_unlink(连接,loid);
如果(低分辨率==-1){
fprintf(标准,“lo_unlink failed:%s”,PQerrorMessage(conn));
出口(1);
}
res=PQexec(conn,“提交”);
res_ok=检查结果(conn、res、PGRES_命令_ok,“提交失败”);
如果(!res_ok)退出(1);
PQclear(res);
PQfinish(conn);
}

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

请尝试此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);
}
#包括
#包括
#包括
#包括
无效检查\u PGconn(PGconn*conn,ConnStatusType status\u ok,char*errmsg)
{
如果(PQstatus(conn)!=状态\正常){
如果(errmsg!=NULL){
fprintf(stderr,“%s:%s”、errmsg、PQerrorMessage(conn));
}否则{
fprintf(stderr,“%s”,PQerrorMessage(conn));
}
PQfinish(conn);
出口(1);
}
}
int check_PGresult(PGconn*conn,PGresult*res,ExecStatusType status_ok,char*errmsg)
{
如果(PQresultStatus(res)!=状态\正常){
如果(errmsg!=NULL){
fprintf(stderr,“%s:%s”、errmsg、PQerrorMessage(conn));
}否则{
fprintf(stderr,“%s”,PQerrorMessage(conn));
}
返回0;
}
返回1;
}
int main(int argc,字符**argv)
{
char*coninfo;
PGconn*conn;
PGresult*res;
int res_ok;
单倍体;
int lofd;
国际劳工组织;
静态碳含量[]=“Lorem ipsum door sit amet,fabulas conclusionemque ius ad.”;
如果(argc>1)conninfo=argv[1];否则conninfo=“”;
conn=PQconnectdb(conninfo);
检查_PGconn(conn,CONNECTION_OK,“连接到数据库失败”);
/*创建大型对象*/
res=PQexec(连接,“开始”);
res_ok=检查结果(conn、res、PGRES_命令_ok,“开始失败”);
如果(!res_ok)退出(1);
PQclear(res);
loid=lo_创建(conn,INV_读取| INV_写入);
if(loid==0){
fprintf(标准,“lo_创建失败:%s”,PQerrorMessage(conn));
出口(1);
}
lofd=lo_打开(连接、loid、INV_写入);
如果(lofd==-1){
fprintf(标准,“lo_open failed:%s”,PQerrorMessage(conn));
出口(1);
}
lo_res=lo_写入(conn、lofd、lo_内容、sizeof(lo_内容));
如果(低分辨率==-1){
fprintf(标准,“lo_写入失败:%s”,PQerrorMessage(conn));
出口(1);
}
lo_res=lo_close(连接、lofd);
如果(低分辨率==-1){
fprintf(标准,“lo_关闭失败:%s”,PQerrorMessage(conn));
出口(1);
}
res=PQexec(conn,“提交”);
res_ok=检查结果(conn、res、PGRES_命令_ok,“提交失败”);
如果(!res_ok)退出(1);
PQclear(res);
/*删除大对象*/
物件