libpq: lo_open() returns 0
libpq: lo_open() returns 0
我在尝试使用 libpq 创建大对象时遇到了问题。在以下代码中:
Oid oid;
int fd;
oid = lo_creat( pgConn, INV_READ | INV_WRITE );
fd = lo_open( pgConn, oid , INV_WRITE );
lo_open() returns 0,根据文档,这不是错误,但会导致后续 lo_write() 失败并出现 "Invalid descriptor" 错误。
我阅读了函数 "taking place within an SQL transaction block" 并试图将我的代码包含在
中
PQexec( pgConn, "BEGIN" );
...
PQexec( pgConn, "COMMIT" );
事情变了。 lo_open() 仍然返回 0,但如果我立即再次调用它,它就成功了!
阅读也是如此
我觉得我错过了什么,但猜不出是什么。
UPD:在 运行 下面的答案中的代码之后,我想到 0 是一个有效的描述符,我得到了初始错误,因为我没有明确地启动事务。
令人惊讶的是,我在读取大对象时也必须调用 "BEGIN" 和 "COMMIT"。
如果你不检查或引用你的错误信息,就很难告诉你任何事情。
请试试这个 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);
}
我在尝试使用 libpq 创建大对象时遇到了问题。在以下代码中:
Oid oid;
int fd;
oid = lo_creat( pgConn, INV_READ | INV_WRITE );
fd = lo_open( pgConn, oid , INV_WRITE );
lo_open() returns 0,根据文档,这不是错误,但会导致后续 lo_write() 失败并出现 "Invalid descriptor" 错误。
我阅读了函数 "taking place within an SQL transaction block" 并试图将我的代码包含在
中PQexec( pgConn, "BEGIN" );
...
PQexec( pgConn, "COMMIT" );
事情变了。 lo_open() 仍然返回 0,但如果我立即再次调用它,它就成功了!
阅读也是如此
我觉得我错过了什么,但猜不出是什么。
UPD:在 运行 下面的答案中的代码之后,我想到 0 是一个有效的描述符,我得到了初始错误,因为我没有明确地启动事务。 令人惊讶的是,我在读取大对象时也必须调用 "BEGIN" 和 "COMMIT"。
如果你不检查或引用你的错误信息,就很难告诉你任何事情。
请试试这个 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);
}