|
|
|
|
@ -597,27 +597,39 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image |
|
|
|
|
<example id="lo-example"> |
|
|
|
|
<title>Large Objects with <application>libpq</application> Example Program</title> |
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
|
/*-------------------------------------------------------------- |
|
|
|
|
/*------------------------------------------------------------------------- |
|
|
|
|
* |
|
|
|
|
* testlo.c-- |
|
|
|
|
* testlo.c |
|
|
|
|
* test using large objects with libpq |
|
|
|
|
* |
|
|
|
|
* Copyright (c) 1994, Regents of the University of California |
|
|
|
|
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group |
|
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California |
|
|
|
|
* |
|
|
|
|
*-------------------------------------------------------------- |
|
|
|
|
* |
|
|
|
|
* IDENTIFICATION |
|
|
|
|
* src/test/examples/testlo.c |
|
|
|
|
* |
|
|
|
|
*------------------------------------------------------------------------- |
|
|
|
|
*/ |
|
|
|
|
#include <stdio.h> |
|
|
|
|
#include <stdlib.h> |
|
|
|
|
|
|
|
|
|
#include <sys/types.h> |
|
|
|
|
#include <sys/stat.h> |
|
|
|
|
#include <fcntl.h> |
|
|
|
|
#include <unistd.h> |
|
|
|
|
|
|
|
|
|
#include "libpq-fe.h" |
|
|
|
|
#include "libpq/libpq-fs.h" |
|
|
|
|
|
|
|
|
|
#define BUFSIZE 1024 |
|
|
|
|
#define BUFSIZE 1024 |
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
* importFile |
|
|
|
|
* importFile - |
|
|
|
|
* import file "in_filename" into database as large object "lobjOid" |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
Oid |
|
|
|
|
static Oid |
|
|
|
|
importFile(PGconn *conn, char *filename) |
|
|
|
|
{ |
|
|
|
|
Oid lobjId; |
|
|
|
|
@ -633,7 +645,7 @@ importFile(PGconn *conn, char *filename) |
|
|
|
|
fd = open(filename, O_RDONLY, 0666); |
|
|
|
|
if (fd < 0) |
|
|
|
|
{ /* error */ |
|
|
|
|
fprintf(stderr, "cannot open unix file %s\n", filename); |
|
|
|
|
fprintf(stderr, "cannot open unix file\"%s\"\n", filename); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
@ -641,7 +653,7 @@ importFile(PGconn *conn, char *filename) |
|
|
|
|
*/ |
|
|
|
|
lobjId = lo_creat(conn, INV_READ | INV_WRITE); |
|
|
|
|
if (lobjId == 0) |
|
|
|
|
fprintf(stderr, "cannot create large object\n"); |
|
|
|
|
fprintf(stderr, "cannot create large object"); |
|
|
|
|
|
|
|
|
|
lobj_fd = lo_open(conn, lobjId, INV_WRITE); |
|
|
|
|
|
|
|
|
|
@ -652,16 +664,16 @@ importFile(PGconn *conn, char *filename) |
|
|
|
|
{ |
|
|
|
|
tmp = lo_write(conn, lobj_fd, buf, nbytes); |
|
|
|
|
if (tmp < nbytes) |
|
|
|
|
fprintf(stderr, "error while reading large object\n"); |
|
|
|
|
fprintf(stderr, "error while reading \"%s\"", filename); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
(void) close(fd); |
|
|
|
|
(void) lo_close(conn, lobj_fd); |
|
|
|
|
close(fd); |
|
|
|
|
lo_close(conn, lobj_fd); |
|
|
|
|
|
|
|
|
|
return lobjId; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
static void |
|
|
|
|
pickout(PGconn *conn, Oid lobjId, int start, int len) |
|
|
|
|
{ |
|
|
|
|
int lobj_fd; |
|
|
|
|
@ -671,10 +683,7 @@ pickout(PGconn *conn, Oid lobjId, int start, int len) |
|
|
|
|
|
|
|
|
|
lobj_fd = lo_open(conn, lobjId, INV_READ); |
|
|
|
|
if (lobj_fd < 0) |
|
|
|
|
{ |
|
|
|
|
fprintf(stderr, "cannot open large object %d\n", |
|
|
|
|
lobjId); |
|
|
|
|
} |
|
|
|
|
fprintf(stderr, "cannot open large object %u", lobjId); |
|
|
|
|
|
|
|
|
|
lo_lseek(conn, lobj_fd, start, SEEK_SET); |
|
|
|
|
buf = malloc(len + 1); |
|
|
|
|
@ -683,16 +692,18 @@ pickout(PGconn *conn, Oid lobjId, int start, int len) |
|
|
|
|
while (len - nread > 0) |
|
|
|
|
{ |
|
|
|
|
nbytes = lo_read(conn, lobj_fd, buf, len - nread); |
|
|
|
|
buf[nbytes] = ' '; |
|
|
|
|
buf[nbytes] = '\0'; |
|
|
|
|
fprintf(stderr, ">>> %s", buf); |
|
|
|
|
nread += nbytes; |
|
|
|
|
if (nbytes <= 0) |
|
|
|
|
break; /* no more data? */ |
|
|
|
|
} |
|
|
|
|
free(buf); |
|
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
lo_close(conn, lobj_fd); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
static void |
|
|
|
|
overwrite(PGconn *conn, Oid lobjId, int start, int len) |
|
|
|
|
{ |
|
|
|
|
int lobj_fd; |
|
|
|
|
@ -703,35 +714,38 @@ overwrite(PGconn *conn, Oid lobjId, int start, int len) |
|
|
|
|
|
|
|
|
|
lobj_fd = lo_open(conn, lobjId, INV_WRITE); |
|
|
|
|
if (lobj_fd < 0) |
|
|
|
|
{ |
|
|
|
|
fprintf(stderr, "cannot open large object %d\n", |
|
|
|
|
lobjId); |
|
|
|
|
} |
|
|
|
|
fprintf(stderr, "cannot open large object %u", lobjId); |
|
|
|
|
|
|
|
|
|
lo_lseek(conn, lobj_fd, start, SEEK_SET); |
|
|
|
|
buf = malloc(len + 1); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) |
|
|
|
|
buf[i] = 'X'; |
|
|
|
|
buf[i] = ' '; |
|
|
|
|
buf[i] = '\0'; |
|
|
|
|
|
|
|
|
|
nwritten = 0; |
|
|
|
|
while (len - nwritten > 0) |
|
|
|
|
{ |
|
|
|
|
nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten); |
|
|
|
|
nwritten += nbytes; |
|
|
|
|
if (nbytes <= 0) |
|
|
|
|
{ |
|
|
|
|
fprintf(stderr, "\nWRITE FAILED!\n"); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
free(buf); |
|
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
lo_close(conn, lobj_fd); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
* exportFile |
|
|
|
|
* exportFile - |
|
|
|
|
* export large object "lobjOid" to file "out_filename" |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
void |
|
|
|
|
static void |
|
|
|
|
exportFile(PGconn *conn, Oid lobjId, char *filename) |
|
|
|
|
{ |
|
|
|
|
int lobj_fd; |
|
|
|
|
@ -745,18 +759,15 @@ exportFile(PGconn *conn, Oid lobjId, char *filename) |
|
|
|
|
*/ |
|
|
|
|
lobj_fd = lo_open(conn, lobjId, INV_READ); |
|
|
|
|
if (lobj_fd < 0) |
|
|
|
|
{ |
|
|
|
|
fprintf(stderr, "cannot open large object %d\n", |
|
|
|
|
lobjId); |
|
|
|
|
} |
|
|
|
|
fprintf(stderr, "cannot open large object %u", lobjId); |
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
* open the file to be written to |
|
|
|
|
*/ |
|
|
|
|
fd = open(filename, O_CREAT | O_WRONLY, 0666); |
|
|
|
|
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666); |
|
|
|
|
if (fd < 0) |
|
|
|
|
{ /* error */ |
|
|
|
|
fprintf(stderr, "cannot open unix file %s\n", |
|
|
|
|
fprintf(stderr, "cannot open unix file\"%s\"", |
|
|
|
|
filename); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -768,18 +779,18 @@ exportFile(PGconn *conn, Oid lobjId, char *filename) |
|
|
|
|
tmp = write(fd, buf, nbytes); |
|
|
|
|
if (tmp < nbytes) |
|
|
|
|
{ |
|
|
|
|
fprintf(stderr, "error while writing %s\n", |
|
|
|
|
fprintf(stderr, "error while writing \"%s\"", |
|
|
|
|
filename); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
(void) lo_close(conn, lobj_fd); |
|
|
|
|
(void) close(fd); |
|
|
|
|
lo_close(conn, lobj_fd); |
|
|
|
|
close(fd); |
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
static void |
|
|
|
|
exit_nicely(PGconn *conn) |
|
|
|
|
{ |
|
|
|
|
PQfinish(conn); |
|
|
|
|
@ -813,37 +824,40 @@ main(int argc, char **argv) |
|
|
|
|
conn = PQsetdb(NULL, NULL, NULL, NULL, database); |
|
|
|
|
|
|
|
|
|
/* check to see that the backend connection was successfully made */ |
|
|
|
|
if (PQstatus(conn) == CONNECTION_BAD) |
|
|
|
|
if (PQstatus(conn) != CONNECTION_OK) |
|
|
|
|
{ |
|
|
|
|
fprintf(stderr, "Connection to database '%s' failed.\n", database); |
|
|
|
|
fprintf(stderr, "%s", PQerrorMessage(conn)); |
|
|
|
|
fprintf(stderr, "Connection to database failed: %s", |
|
|
|
|
PQerrorMessage(conn)); |
|
|
|
|
exit_nicely(conn); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
res = PQexec(conn, "begin"); |
|
|
|
|
PQclear(res); |
|
|
|
|
|
|
|
|
|
printf("importing file %s\n", in_filename); |
|
|
|
|
printf("importing file \"%s\" ...\n", in_filename); |
|
|
|
|
/* lobjOid = importFile(conn, in_filename); */ |
|
|
|
|
lobjOid = lo_import(conn, in_filename); |
|
|
|
|
/* |
|
|
|
|
printf("as large object %d.\n", lobjOid); |
|
|
|
|
if (lobjOid == 0) |
|
|
|
|
fprintf(stderr, "%s\n", PQerrorMessage(conn)); |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
printf("\tas large object %u.\n", lobjOid); |
|
|
|
|
|
|
|
|
|
printf("picking out bytes 1000-2000 of the large object\n"); |
|
|
|
|
pickout(conn, lobjOid, 1000, 1000); |
|
|
|
|
printf("picking out bytes 1000-2000 of the large object\n"); |
|
|
|
|
pickout(conn, lobjOid, 1000, 1000); |
|
|
|
|
|
|
|
|
|
printf("overwriting bytes 1000-2000 of the large object with X's\n"); |
|
|
|
|
overwrite(conn, lobjOid, 1000, 1000); |
|
|
|
|
*/ |
|
|
|
|
printf("overwriting bytes 1000-2000 of the large object with X's\n"); |
|
|
|
|
overwrite(conn, lobjOid, 1000, 1000); |
|
|
|
|
|
|
|
|
|
printf("exporting large object to file %s\n", out_filename); |
|
|
|
|
/* exportFile(conn, lobjOid, out_filename); */ |
|
|
|
|
lo_export(conn, lobjOid, out_filename); |
|
|
|
|
printf("exporting large object to file \"%s\" ...\n", out_filename); |
|
|
|
|
/* exportFile(conn, lobjOid, out_filename); */ |
|
|
|
|
if (lo_export(conn, lobjOid, out_filename) < 0) |
|
|
|
|
fprintf(stderr, "%s\n", PQerrorMessage(conn)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
res = PQexec(conn, "end"); |
|
|
|
|
PQclear(res); |
|
|
|
|
PQfinish(conn); |
|
|
|
|
exit(0); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
]]> |
|
|
|
|
</programlisting> |
|
|
|
|
|