mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
Improve error detection and recovery in lo_import()/lo_export().
Problems noted while experimenting with new control-C code for psql.
This commit is contained in:
parent
067e40cc6d
commit
ace93353ea
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-lobj.c,v 1.56 2006/03/05 15:59:09 momjian Exp $
|
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-lobj.c,v 1.57 2006/06/14 01:28:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -58,6 +58,12 @@ lo_open(PGconn *conn, Oid lobjId, int mode)
|
|||||||
PQArgBlock argv[2];
|
PQArgBlock argv[2];
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
|
|
||||||
|
if (conn->lobjfuncs == NULL)
|
||||||
|
{
|
||||||
|
if (lo_initialize(conn) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
argv[0].isint = 1;
|
argv[0].isint = 1;
|
||||||
argv[0].len = 4;
|
argv[0].len = 4;
|
||||||
argv[0].u.integer = lobjId;
|
argv[0].u.integer = lobjId;
|
||||||
@ -66,12 +72,6 @@ lo_open(PGconn *conn, Oid lobjId, int mode)
|
|||||||
argv[1].len = 4;
|
argv[1].len = 4;
|
||||||
argv[1].u.integer = mode;
|
argv[1].u.integer = mode;
|
||||||
|
|
||||||
if (conn->lobjfuncs == NULL)
|
|
||||||
{
|
|
||||||
if (lo_initialize(conn) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2);
|
res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2);
|
||||||
if (PQresultStatus(res) == PGRES_COMMAND_OK)
|
if (PQresultStatus(res) == PGRES_COMMAND_OK)
|
||||||
{
|
{
|
||||||
@ -438,6 +438,7 @@ lo_import(PGconn *conn, const char *filename)
|
|||||||
char buf[LO_BUFSIZE];
|
char buf[LO_BUFSIZE];
|
||||||
Oid lobjOid;
|
Oid lobjOid;
|
||||||
int lobj;
|
int lobj;
|
||||||
|
char sebuf[256];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* open the file to be read in
|
* open the file to be read in
|
||||||
@ -445,8 +446,6 @@ lo_import(PGconn *conn, const char *filename)
|
|||||||
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
|
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{ /* error */
|
{ /* error */
|
||||||
char sebuf[256];
|
|
||||||
|
|
||||||
printfPQExpBuffer(&conn->errorMessage,
|
printfPQExpBuffer(&conn->errorMessage,
|
||||||
libpq_gettext("could not open file \"%s\": %s\n"),
|
libpq_gettext("could not open file \"%s\": %s\n"),
|
||||||
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||||
@ -454,7 +453,7 @@ lo_import(PGconn *conn, const char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* create an inversion "object"
|
* create an inversion object
|
||||||
*/
|
*/
|
||||||
lobjOid = lo_creat(conn, INV_READ | INV_WRITE);
|
lobjOid = lo_creat(conn, INV_READ | INV_WRITE);
|
||||||
if (lobjOid == InvalidOid)
|
if (lobjOid == InvalidOid)
|
||||||
@ -477,24 +476,46 @@ lo_import(PGconn *conn, const char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* read in from the Unix file and write to the inversion file
|
* read in from the file and write to the large object
|
||||||
*/
|
*/
|
||||||
while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0)
|
while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0)
|
||||||
{
|
{
|
||||||
tmp = lo_write(conn, lobj, buf, nbytes);
|
tmp = lo_write(conn, lobj, buf, nbytes);
|
||||||
if (tmp < nbytes)
|
if (tmp != nbytes)
|
||||||
{
|
{
|
||||||
printfPQExpBuffer(&conn->errorMessage,
|
/*
|
||||||
libpq_gettext("error while reading file \"%s\"\n"),
|
* If the lo_write failed, we are probably in an aborted
|
||||||
filename);
|
* transaction and so lo_close will fail. Try it anyway for
|
||||||
(void) close(fd);
|
* cleanliness, but don't let it determine the returned error
|
||||||
|
* message.
|
||||||
|
*/
|
||||||
(void) lo_close(conn, lobj);
|
(void) lo_close(conn, lobj);
|
||||||
|
|
||||||
|
printfPQExpBuffer(&conn->errorMessage,
|
||||||
|
libpq_gettext("error while writing large object %u\n"),
|
||||||
|
lobjOid);
|
||||||
|
(void) close(fd);
|
||||||
return InvalidOid;
|
return InvalidOid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nbytes < 0)
|
||||||
|
{
|
||||||
|
printfPQExpBuffer(&conn->errorMessage,
|
||||||
|
libpq_gettext("could not read from file \"%s\": %s\n"),
|
||||||
|
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||||
|
lobjOid = InvalidOid;
|
||||||
|
}
|
||||||
|
|
||||||
(void) close(fd);
|
(void) close(fd);
|
||||||
(void) lo_close(conn, lobj);
|
|
||||||
|
if (lo_close(conn, lobj) != 0)
|
||||||
|
{
|
||||||
|
printfPQExpBuffer(&conn->errorMessage,
|
||||||
|
libpq_gettext("error while writing large object %u\n"),
|
||||||
|
lobjOid);
|
||||||
|
return InvalidOid;
|
||||||
|
}
|
||||||
|
|
||||||
return lobjOid;
|
return lobjOid;
|
||||||
}
|
}
|
||||||
@ -502,16 +523,18 @@ lo_import(PGconn *conn, const char *filename)
|
|||||||
/*
|
/*
|
||||||
* lo_export -
|
* lo_export -
|
||||||
* exports an (inversion) large object.
|
* exports an (inversion) large object.
|
||||||
* returns -1 upon failure, 1 otherwise
|
* returns -1 upon failure, 1 if OK
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
lo_export(PGconn *conn, Oid lobjId, const char *filename)
|
lo_export(PGconn *conn, Oid lobjId, const char *filename)
|
||||||
{
|
{
|
||||||
|
int result = 1;
|
||||||
int fd;
|
int fd;
|
||||||
int nbytes,
|
int nbytes,
|
||||||
tmp;
|
tmp;
|
||||||
char buf[LO_BUFSIZE];
|
char buf[LO_BUFSIZE];
|
||||||
int lobj;
|
int lobj;
|
||||||
|
char sebuf[256];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* open the large object.
|
* open the large object.
|
||||||
@ -530,8 +553,6 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
|
|||||||
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
|
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{ /* error */
|
{ /* error */
|
||||||
char sebuf[256];
|
|
||||||
|
|
||||||
printfPQExpBuffer(&conn->errorMessage,
|
printfPQExpBuffer(&conn->errorMessage,
|
||||||
libpq_gettext("could not open file \"%s\": %s\n"),
|
libpq_gettext("could not open file \"%s\": %s\n"),
|
||||||
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||||
@ -540,33 +561,39 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* read in from the inversion file and write to the Unix file
|
* read in from the large object and write to the file
|
||||||
*/
|
*/
|
||||||
while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0)
|
while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0)
|
||||||
{
|
{
|
||||||
tmp = write(fd, buf, nbytes);
|
tmp = write(fd, buf, nbytes);
|
||||||
if (tmp < nbytes)
|
if (tmp != nbytes)
|
||||||
{
|
{
|
||||||
printfPQExpBuffer(&conn->errorMessage,
|
printfPQExpBuffer(&conn->errorMessage,
|
||||||
libpq_gettext("error while writing to file \"%s\"\n"),
|
libpq_gettext("error while writing to file \"%s\": %s\n"),
|
||||||
filename);
|
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||||
(void) lo_close(conn, lobj);
|
(void) lo_close(conn, lobj);
|
||||||
(void) close(fd);
|
(void) close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) lo_close(conn, lobj);
|
if (lo_close(conn, lobj) != 0 || nbytes < 0)
|
||||||
|
{
|
||||||
|
printfPQExpBuffer(&conn->errorMessage,
|
||||||
|
libpq_gettext("error while reading large object %u\n"),
|
||||||
|
lobjId);
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (close(fd))
|
if (close(fd))
|
||||||
{
|
{
|
||||||
printfPQExpBuffer(&conn->errorMessage,
|
printfPQExpBuffer(&conn->errorMessage,
|
||||||
libpq_gettext("error while writing to file \"%s\"\n"),
|
libpq_gettext("error while writing to file \"%s\": %s\n"),
|
||||||
filename);
|
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||||
return -1;
|
result = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user