]> granicus.if.org Git - postgresql/commitdiff
Code review for 64-bit-large-object patch.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 8 Oct 2012 22:24:06 +0000 (18:24 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 8 Oct 2012 22:24:32 +0000 (18:24 -0400)
Fix broken-on-bigendian-machines byte-swapping functions, add missed update
of alternate regression expected file, improve error reporting, remove some
unnecessary code, sync testlo64.c with current testlo.c (it seems to have
been cloned from a very old copy of that), assorted cosmetic improvements.

src/backend/libpq/be-fsstubs.c
src/backend/storage/large_object/inv_api.c
src/backend/utils/errcodes.txt
src/include/catalog/pg_proc.h
src/interfaces/libpq/fe-lobj.c
src/test/examples/testlo64.c
src/test/regress/input/largeobject.source
src/test/regress/output/largeobject.source
src/test/regress/output/largeobject_1.source

index 4bc81ba9f4d11230c8ea8c003d0b61ec16c8e813..c4ac1a650f505cfa1582a19797cf9621a4c80f46 100644 (file)
@@ -39,7 +39,6 @@
 #include "postgres.h"
 
 #include <fcntl.h>
-#include <limits.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
@@ -57,7 +56,9 @@
  */
 bool           lo_compat_privileges;
 
-/*#define FSDB 1*/
+/* define this to enable debug logging */
+/* #define FSDB 1 */
+/* chunk size for lo_import/lo_export transfers */
 #define BUFSIZE                        8192
 
 /*
@@ -210,7 +211,6 @@ lo_write(int fd, const char *buf, int len)
        return status;
 }
 
-
 Datum
 lo_lseek(PG_FUNCTION_ARGS)
 {
@@ -226,42 +226,31 @@ lo_lseek(PG_FUNCTION_ARGS)
 
        status = inv_seek(cookies[fd], offset, whence);
 
-       if (INT_MAX < status)
-       {
+       /* guard against result overflow */
+       if (status != (int32) status)
                ereport(ERROR,
-                               (errcode(ERRCODE_BLOB_OFFSET_OVERFLOW),
-                                errmsg("offset overflow: %d", fd)));
-               PG_RETURN_INT32(-1);
-       }
+                               (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+                                errmsg("lo_lseek result out of range for large-object descriptor %d",
+                                               fd)));
 
-       PG_RETURN_INT32(status);
+       PG_RETURN_INT32((int32) status);
 }
 
-
 Datum
 lo_lseek64(PG_FUNCTION_ARGS)
 {
        int32           fd = PG_GETARG_INT32(0);
        int64           offset = PG_GETARG_INT64(1);
        int32           whence = PG_GETARG_INT32(2);
-       MemoryContext currentContext;
-       int64                   status;
+       int64           status;
 
        if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL)
-       {
                ereport(ERROR,
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
                                 errmsg("invalid large-object descriptor: %d", fd)));
-               PG_RETURN_INT64(-1);
-       }
-
-       Assert(fscxt != NULL);
-       currentContext = MemoryContextSwitchTo(fscxt);
 
        status = inv_seek(cookies[fd], offset, whence);
 
-       MemoryContextSwitchTo(currentContext);
-
        PG_RETURN_INT64(status);
 }
 
@@ -301,7 +290,7 @@ Datum
 lo_tell(PG_FUNCTION_ARGS)
 {
        int32           fd = PG_GETARG_INT32(0);
-       int64           offset = 0;
+       int64           offset;
 
        if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL)
                ereport(ERROR,
@@ -310,37 +299,30 @@ lo_tell(PG_FUNCTION_ARGS)
 
        offset = inv_tell(cookies[fd]);
 
-       if (INT_MAX < offset)
-       {
+       /* guard against result overflow */
+       if (offset != (int32) offset)
                ereport(ERROR,
-                               (errcode(ERRCODE_BLOB_OFFSET_OVERFLOW),
-                                errmsg("offset overflow: %d", fd)));
-               PG_RETURN_INT32(-1);
-       }
+                               (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+                                errmsg("lo_tell result out of range for large-object descriptor %d",
+                                               fd)));
 
-       PG_RETURN_INT32(offset);
+       PG_RETURN_INT32((int32) offset);
 }
 
-
 Datum
 lo_tell64(PG_FUNCTION_ARGS)
 {
        int32           fd = PG_GETARG_INT32(0);
+       int64           offset;
 
        if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL)
-       {
                ereport(ERROR,
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
                                 errmsg("invalid large-object descriptor: %d", fd)));
-               PG_RETURN_INT64(-1);
-       }
 
-       /*
-        * We assume we do not need to switch contexts for inv_tell. That is
-        * true for now, but is probably more than this module ought to
-        * assume...
-        */
-       PG_RETURN_INT64(inv_tell(cookies[fd]));
+       offset = inv_tell(cookies[fd]);
+
+       PG_RETURN_INT64(offset);
 }
 
 Datum
index 3f5688b939b0c09b629b3419f531f1b0dd23d6fb..5dd17823c2312f088a4a6c64ad58ab7668f2e1b2 100644 (file)
@@ -30,6 +30,8 @@
  */
 #include "postgres.h"
 
+#include <limits.h>
+
 #include "access/genam.h"
 #include "access/heapam.h"
 #include "access/sysattr.h"
@@ -264,7 +266,10 @@ inv_open(Oid lobjId, int flags, MemoryContext mcxt)
                retval->flags = IFS_RDLOCK;
        }
        else
-               elog(ERROR, "invalid flags: %d", flags);
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("invalid flags for opening a large object: %d",
+                                               flags)));
 
        /* Can't use LargeObjectExists here because it always uses SnapshotNow */
        if (!myLargeObjectExists(lobjId, retval->snapshot))
@@ -381,34 +386,45 @@ inv_getsize(LargeObjectDesc *obj_desc)
 int64
 inv_seek(LargeObjectDesc *obj_desc, int64 offset, int whence)
 {
+       int64           newoffset;
+
        Assert(PointerIsValid(obj_desc));
 
+       /*
+        * Note: overflow in the additions is possible, but since we will reject
+        * negative results, we don't need any extra test for that.
+        */
        switch (whence)
        {
                case SEEK_SET:
-                       if (offset < 0 || offset >= MAX_LARGE_OBJECT_SIZE)
-                               elog(ERROR, "invalid seek offset: " INT64_FORMAT, offset);
-                       obj_desc->offset = offset;
+                       newoffset = offset;
                        break;
                case SEEK_CUR:
-                       if ((offset + obj_desc->offset) < 0 ||
-                          (offset + obj_desc->offset) >= MAX_LARGE_OBJECT_SIZE)
-                               elog(ERROR, "invalid seek offset: " INT64_FORMAT, offset);
-                       obj_desc->offset += offset;
+                       newoffset = obj_desc->offset + offset;
                        break;
                case SEEK_END:
-                       {
-                               int64           pos = inv_getsize(obj_desc) + offset;
-
-                               if (pos < 0 || pos >= MAX_LARGE_OBJECT_SIZE)
-                                       elog(ERROR, "invalid seek offset: " INT64_FORMAT, offset);
-                               obj_desc->offset = pos;
-                       }
+                       newoffset = inv_getsize(obj_desc) + offset;
                        break;
                default:
-                       elog(ERROR, "invalid whence: %d", whence);
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                        errmsg("invalid whence setting: %d", whence)));
+                       newoffset = 0;          /* keep compiler quiet */
+                       break;
        }
-       return obj_desc->offset;
+
+       /*
+        * use errmsg_internal here because we don't want to expose INT64_FORMAT
+        * in translatable strings; doing better is not worth the trouble
+        */
+       if (newoffset < 0 || newoffset > MAX_LARGE_OBJECT_SIZE)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg_internal("invalid large object seek target: " INT64_FORMAT,
+                                                                newoffset)));
+
+       obj_desc->offset = newoffset;
+       return newoffset;
 }
 
 int64
@@ -438,9 +454,6 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
        if (nbytes <= 0)
                return 0;
 
-       if ((nbytes + obj_desc->offset) > MAX_LARGE_OBJECT_SIZE)
-               elog(ERROR, "invalid read request size: %d", nbytes);
-
        open_lo_relation();
 
        ScanKeyInit(&skey[0],
@@ -559,13 +572,18 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
        if (!LargeObjectExists(obj_desc->id))
                ereport(ERROR,
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
-                          errmsg("large object %u was already dropped", obj_desc->id)));
+                                errmsg("large object %u was already dropped",
+                                               obj_desc->id)));
 
        if (nbytes <= 0)
                return 0;
 
+       /* this addition can't overflow because nbytes is only int32 */
        if ((nbytes + obj_desc->offset) > MAX_LARGE_OBJECT_SIZE)
-               elog(ERROR, "invalid write request size: %d", nbytes);
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("invalid large object write request size: %d",
+                                               nbytes)));
 
        open_lo_relation();
 
@@ -759,7 +777,18 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
        if (!LargeObjectExists(obj_desc->id))
                ereport(ERROR,
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
-                          errmsg("large object %u was already dropped", obj_desc->id)));
+                                errmsg("large object %u was already dropped",
+                                               obj_desc->id)));
+
+       /*
+        * use errmsg_internal here because we don't want to expose INT64_FORMAT
+        * in translatable strings; doing better is not worth the trouble
+        */
+       if (len < 0 || len > MAX_LARGE_OBJECT_SIZE)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg_internal("invalid large object truncation target: " INT64_FORMAT,
+                                                                len)));
 
        open_lo_relation();
 
index db8ab53af26b7536ea45c8151ea6defe832c25b3..3e04164956303f6fcdef84a15c617e3075956b05 100644 (file)
@@ -199,7 +199,6 @@ Section: Class 22 - Data Exception
 2200N    E    ERRCODE_INVALID_XML_CONTENT                                    invalid_xml_content
 2200S    E    ERRCODE_INVALID_XML_COMMENT                                    invalid_xml_comment
 2200T    E    ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION                     invalid_xml_processing_instruction
-22P07    E    ERRCODE_BLOB_OFFSET_OVERFLOW                                   blob_offset_overflow
 
 Section: Class 23 - Integrity Constraint Violation
 
index a2da836ff2cdd02a497571b875ae6d6e66481d44..d8352f180d3235e6082a1c8a400121cbed2dfb86 100644 (file)
@@ -1040,7 +1040,7 @@ DATA(insert OID = 955 (  lowrite             PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 23
 DESCR("large object write");
 DATA(insert OID = 956 (  lo_lseek                 PGNSP PGUID 12 1 0 0 0 f f f f t f v 3 0 23 "23 23 23" _null_ _null_ _null_ _null_   lo_lseek _null_ _null_ _null_ ));
 DESCR("large object seek");
-DATA(insert OID = 3170 (  lo_lseek64              PGNSP PGUID 12 1 0 0 0 f f f f t f v 3 0 20 "23 20 23" _null_ _null_ _null_ _null_   lo_lseek64 _null_ _null_ _null_ ));
+DATA(insert OID = 3170 (  lo_lseek64      PGNSP PGUID 12 1 0 0 0 f f f f t f v 3 0 20 "23 20 23" _null_ _null_ _null_ _null_   lo_lseek64 _null_ _null_ _null_ ));
 DESCR("large object seek (64 bit)");
 DATA(insert OID = 957 (  lo_creat                 PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 26 "23" _null_ _null_ _null_ _null_ lo_creat _null_ _null_ _null_ ));
 DESCR("large object create");
index 7c40100b86bf055e600af01afe542c273d9a5f63..cf6fe3e128bb0d644b499d4db9e198fd40c907ce 100644 (file)
 
 #include <fcntl.h>
 #include <sys/stat.h>
+#include <netinet/in.h>                        /* for ntohl/htonl */
+#include <arpa/inet.h>
 
 #include "libpq-fe.h"
 #include "libpq-int.h"
 #include "libpq/libpq-fs.h"            /* must come after sys/stat.h */
 
-/* for ntohl/htonl */
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
 #define LO_BUFSIZE               8192
 
 static int     lo_initialize(PGconn *conn);
 static Oid     lo_import_internal(PGconn *conn, const char *filename, Oid oid);
-static pg_int64        lo_hton64(pg_int64 host64);
-static pg_int64        lo_ntoh64(pg_int64 net64);
+static pg_int64 lo_hton64(pg_int64 host64);
+static pg_int64 lo_ntoh64(pg_int64 net64);
 
 /*
  * lo_open
@@ -373,7 +371,7 @@ lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence)
 {
        PQArgBlock      argv[3];
        PGresult   *res;
-       pg_int64                retval;
+       pg_int64        retval;
        int                     result_len;
 
        if (conn == NULL || conn->lobjfuncs == NULL)
@@ -403,11 +401,11 @@ lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence)
        argv[2].u.integer = whence;
 
        res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek64,
-                          (int *)&retval, &result_len, 0, argv, 3);
+                          (int *) &retval, &result_len, 0, argv, 3);
        if (PQresultStatus(res) == PGRES_COMMAND_OK)
        {
                PQclear(res);
-               return lo_ntoh64((pg_int64)retval);
+               return lo_ntoh64(retval);
        }
        else
        {
@@ -506,9 +504,7 @@ lo_create(PGconn *conn, Oid lobjId)
 /*
  * lo_tell
  *       returns the current seek location of the large object
- *
  */
-
 int
 lo_tell(PGconn *conn, int fd)
 {
@@ -575,7 +571,7 @@ lo_tell64(PGconn *conn, int fd)
        if (PQresultStatus(res) == PGRES_COMMAND_OK)
        {
                PQclear(res);
-               return lo_ntoh64((pg_int64) retval);
+               return lo_ntoh64(retval);
        }
        else
        {
@@ -935,7 +931,9 @@ lo_initialize(PGconn *conn)
        PQclear(res);
 
        /*
-        * Finally check that we really got all large object interface functions
+        * Finally check that we got all required large object interface functions
+        * (ones that have been added later than the stone age are instead checked
+        * only if used)
         */
        if (lobjfuncs->fn_lo_open == 0)
        {
@@ -993,30 +991,6 @@ lo_initialize(PGconn *conn)
                free(lobjfuncs);
                return -1;
        }
-       if (conn->sversion >= 90300)
-       {
-               if (lobjfuncs->fn_lo_lseek64 == 0)
-               {
-                       printfPQExpBuffer(&conn->errorMessage,
-                                       libpq_gettext("cannot determine OID of function lo_lseek64\n"));
-                       free(lobjfuncs);
-                       return -1;
-               }
-               if (lobjfuncs->fn_lo_tell64 == 0)
-               {
-                       printfPQExpBuffer(&conn->errorMessage,
-                                       libpq_gettext("cannot determine OID of function lo_tell64\n"));
-                       free(lobjfuncs);
-                       return -1;
-               }
-               if (lobjfuncs->fn_lo_truncate64 == 0)
-               {
-                       printfPQExpBuffer(&conn->errorMessage,
-                                       libpq_gettext("cannot determine OID of function lo_truncate64\n"));
-                       free(lobjfuncs);
-                       return -1;
-               }
-       }
 
        /*
         * Put the structure into the connection control
@@ -1027,43 +1001,48 @@ lo_initialize(PGconn *conn)
 
 /*
  * lo_hton64
- *       converts an 64-bit integer from host byte order to network byte order
+ *       converts a 64-bit integer from host byte order to network byte order
  */
 static pg_int64
 lo_hton64(pg_int64 host64)
 {
-       pg_int64        result;
-       uint32  h32, l32;
+       union
+       {
+               pg_int64        i64;
+               uint32          i32[2];
+       }                       swap;
+       uint32          t;
 
        /* High order half first, since we're doing MSB-first */
-       h32 = (uint32) (host64 >> 32);
+       t = (uint32) (host64 >> 32);
+       swap.i32[0] = htonl(t);
 
        /* Now the low order half */
-       l32 = (uint32) (host64 & 0xffffffff);
-
-       result = htonl(l32);
-       result <<= 32;
-       result |= htonl(h32);
+       t = (uint32) host64;
+       swap.i32[1] = htonl(t);
 
-       return result;
+       return swap.i64;
 }
 
 /*
  * lo_ntoh64
- *       converts an 64-bit integer from network byte order to host byte order
+ *       converts a 64-bit integer from network byte order to host byte order
  */
 static pg_int64
 lo_ntoh64(pg_int64 net64)
 {
-       pg_int64        result;
-       uint32  h32, l32;
+       union
+       {
+               pg_int64        i64;
+               uint32          i32[2];
+       }                       swap;
+       pg_int64        result;
 
-       l32 = (uint32) (net64 >> 32);
-       h32 = (uint32) (net64 & 0xffffffff);
+       swap.i64 = net64;
 
-       result = ntohl(h32);
+       result = (uint32) ntohl(swap.i32[0]);
        result <<= 32;
-       result |= ntohl(l32);
+       result |= (uint32) ntohl(swap.i32[1]);
 
        return result;
 }
index 6ab7f524caafabb1591598f6111cd042a634ac8e..c10c3e013858d7ac46f7c8b0bb6b9bdd649843bf 100644 (file)
@@ -3,7 +3,7 @@
  * testlo64.c
  *       test using large objects with libpq using 64-bit APIs
  *
- * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
@@ -46,7 +46,7 @@ importFile(PGconn *conn, char *filename)
        fd = open(filename, O_RDONLY, 0666);
        if (fd < 0)
        {                                                       /* error */
-               fprintf(stderr, "can't open unix file\"%s\"\n", filename);
+               fprintf(stderr, "cannot open unix file\"%s\"\n", filename);
        }
 
        /*
@@ -54,7 +54,7 @@ importFile(PGconn *conn, char *filename)
         */
        lobjId = lo_creat(conn, INV_READ | INV_WRITE);
        if (lobjId == 0)
-               fprintf(stderr, "can't create large object");
+               fprintf(stderr, "cannot create large object");
 
        lobj_fd = lo_open(conn, lobjId, INV_WRITE);
 
@@ -81,24 +81,16 @@ pickout(PGconn *conn, Oid lobjId, pg_int64 start, int len)
        char       *buf;
        int                     nbytes;
        int                     nread;
-       pg_int64                pos;
 
        lobj_fd = lo_open(conn, lobjId, INV_READ);
        if (lobj_fd < 0)
-               fprintf(stderr, "can't open large object %u", lobjId);
+               fprintf(stderr, "cannot open large object %u", lobjId);
 
-       if (lo_tell64(conn, lobj_fd) < 0)
-       {
-               fprintf(stderr, "error lo_tell64: %s\n", PQerrorMessage(conn));
-       }
-
-       if ((pos=lo_lseek64(conn, lobj_fd, start, SEEK_SET)) < 0)
-       {
-               fprintf(stderr, "error lo_lseek64: %s\n", PQerrorMessage(conn));
-               return;
-       }
+       if (lo_lseek64(conn, lobj_fd, start, SEEK_SET) < 0)
+               fprintf(stderr, "error in lo_lseek64: %s", PQerrorMessage(conn));
 
-       fprintf(stderr, "before read: retval of lo_lseek64 : %lld\n", (long long int) pos);
+       if (lo_tell64(conn, lobj_fd) != start)
+               fprintf(stderr, "error in lo_tell64: %s", PQerrorMessage(conn));
 
        buf = malloc(len + 1);
 
@@ -114,10 +106,6 @@ pickout(PGconn *conn, Oid lobjId, pg_int64 start, int len)
        }
        free(buf);
        fprintf(stderr, "\n");
-
-       pos = lo_tell64(conn, lobj_fd);
-       fprintf(stderr, "after read: retval of lo_tell64 : %lld\n\n", (long long int) pos);
-
        lo_close(conn, lobj_fd);
 }
 
@@ -129,18 +117,13 @@ overwrite(PGconn *conn, Oid lobjId, pg_int64 start, int len)
        int                     nbytes;
        int                     nwritten;
        int                     i;
-       pg_int64                pos;
 
-       lobj_fd = lo_open(conn, lobjId, INV_READ | INV_WRITE);
+       lobj_fd = lo_open(conn, lobjId, INV_WRITE);
        if (lobj_fd < 0)
-               fprintf(stderr, "can't open large object %u", lobjId);
+               fprintf(stderr, "cannot open large object %u", lobjId);
 
-       if ((pos=lo_lseek64(conn, lobj_fd, start, SEEK_SET)) < 0)
-       {
-               fprintf(stderr, "error lo_lseek64: %s\n", PQerrorMessage(conn));
-               return;
-       }
-       fprintf(stderr, "before write: retval of lo_lseek64 : %lld\n", (long long int) pos);
+       if (lo_lseek64(conn, lobj_fd, start, SEEK_SET) < 0)
+               fprintf(stderr, "error in lo_lseek64: %s", PQerrorMessage(conn));
 
        buf = malloc(len + 1);
 
@@ -160,30 +143,22 @@ overwrite(PGconn *conn, Oid lobjId, pg_int64 start, int len)
                }
        }
        free(buf);
-
-       pos = lo_tell64(conn, lobj_fd);
-       fprintf(stderr, "after write: retval of lo_tell64 : %lld\n\n", (long long int) pos);
-
+       fprintf(stderr, "\n");
        lo_close(conn, lobj_fd);
 }
 
 static void
-my_truncate(PGconn *conn, Oid lobjId, size_t len)
+my_truncate(PGconn *conn, Oid lobjId, pg_int64 len)
 {
        int                     lobj_fd;
 
        lobj_fd = lo_open(conn, lobjId, INV_READ | INV_WRITE);
        if (lobj_fd < 0)
-               fprintf(stderr, "can't open large object %u", lobjId);
+               fprintf(stderr, "cannot open large object %u", lobjId);
 
        if (lo_truncate64(conn, lobj_fd, len) < 0)
-       {
-               fprintf(stderr, "error lo_truncate64: %s\n", PQerrorMessage(conn));
-               return;
-       }
+               fprintf(stderr, "error in lo_truncate64: %s", PQerrorMessage(conn));
 
-
-       fprintf(stderr, "\n");
        lo_close(conn, lobj_fd);
 }
 
@@ -203,11 +178,11 @@ exportFile(PGconn *conn, Oid lobjId, char *filename)
        int                     fd;
 
        /*
-        * create an inversion "object"
+        * open the large object
         */
        lobj_fd = lo_open(conn, lobjId, INV_READ);
        if (lobj_fd < 0)
-               fprintf(stderr, "can't open large object %u", lobjId);
+               fprintf(stderr, "cannot open large object %u", lobjId);
 
        /*
         * open the file to be written to
@@ -215,12 +190,12 @@ exportFile(PGconn *conn, Oid lobjId, char *filename)
        fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
        if (fd < 0)
        {                                                       /* error */
-               fprintf(stderr, "can't open unix file\"%s\"",
+               fprintf(stderr, "cannot open unix file\"%s\"",
                                filename);
        }
 
        /*
-        * read in from the Unix file and write to the inversion file
+        * read in from the inversion file and write to the Unix file
         */
        while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) > 0)
        {
@@ -293,24 +268,22 @@ main(int argc, char **argv)
                printf("\tas large object %u.\n", lobjOid);
 
                printf("picking out bytes 4294967000-4294968000 of the large object\n");
-               pickout(conn, lobjOid, 4294967000ULL, 1000);
+               pickout(conn, lobjOid, 4294967000U, 1000);
 
                printf("overwriting bytes 4294967000-4294968000 of the large object with X's\n");
-               overwrite(conn, lobjOid, 4294967000ULL, 1000);
-
+               overwrite(conn, lobjOid, 4294967000U, 1000);
 
                printf("exporting large object to file \"%s\" ...\n", out_filename);
 /*             exportFile(conn, lobjOid, out_filename); */
                if (!lo_export(conn, lobjOid, out_filename))
                        fprintf(stderr, "%s\n", PQerrorMessage(conn));
 
-               printf("truncating to 3294968000 byte\n");
-               my_truncate(conn, lobjOid, 3294968000ULL);
+               printf("truncating to 3294968000 bytes\n");
+               my_truncate(conn, lobjOid, 3294968000U);
 
                printf("exporting truncated large object to file \"%s\" ...\n", out_filename2);
                if (!lo_export(conn, lobjOid, out_filename2))
                        fprintf(stderr, "%s\n", PQerrorMessage(conn));
-
        }
 
        res = PQexec(conn, "end");
index 4984d78a0694490cf53621efc854cde1f26d12b2..f0ea7a2e17346f62f266b0b6997b943a71529ea9 100644 (file)
@@ -125,7 +125,7 @@ SELECT lo_tell(fd) FROM lotest_stash_values;
 SELECT lo_close(fd) FROM lotest_stash_values;
 END;
 
--- Test 64-bit largelbject functions.
+-- Test 64-bit large object functions.
 BEGIN;
 UPDATE lotest_stash_values SET fd = lo_open(loid, CAST(x'20000' | x'40000' AS integer));
 
index 74c4772b03aba5cc3cdc75a546f3819bb26b62a5..a25ac2a91255d584888a8403507728b6f65462c4 100644 (file)
@@ -210,7 +210,7 @@ SELECT lo_close(fd) FROM lotest_stash_values;
 (1 row)
 
 END;
--- Test 64-bit largelbject functions.
+-- Test 64-bit large object functions.
 BEGIN;
 UPDATE lotest_stash_values SET fd = lo_open(loid, CAST(x'20000' | x'40000' AS integer));
 SELECT lo_lseek64(fd, 4294967296, 0) FROM lotest_stash_values;
index 5c69eff03b91530ef2ffcd7d27d8298084ffa5dd..bae74f6c268bc15954aad291f0207f08f47cff26 100644 (file)
@@ -209,6 +209,88 @@ SELECT lo_close(fd) FROM lotest_stash_values;
         0
 (1 row)
 
+END;
+-- Test 64-bit large object functions.
+BEGIN;
+UPDATE lotest_stash_values SET fd = lo_open(loid, CAST(x'20000' | x'40000' AS integer));
+SELECT lo_lseek64(fd, 4294967296, 0) FROM lotest_stash_values;
+ lo_lseek64 
+------------
+ 4294967296
+(1 row)
+
+SELECT lowrite(fd, 'offset:4GB') FROM lotest_stash_values;
+ lowrite 
+---------
+      10
+(1 row)
+
+SELECT lo_tell64(fd) FROM lotest_stash_values;
+ lo_tell64  
+------------
+ 4294967306
+(1 row)
+
+SELECT lo_lseek64(fd, -10, 1) FROM lotest_stash_values;
+ lo_lseek64 
+------------
+ 4294967296
+(1 row)
+
+SELECT lo_tell64(fd) FROM lotest_stash_values;
+ lo_tell64  
+------------
+ 4294967296
+(1 row)
+
+SELECT loread(fd, 10) FROM lotest_stash_values;
+   loread   
+------------
+ offset:4GB
+(1 row)
+
+SELECT lo_truncate64(fd, 5000000000) FROM lotest_stash_values;
+ lo_truncate64 
+---------------
+             0
+(1 row)
+
+SELECT lo_lseek64(fd, 0, 2) FROM lotest_stash_values;
+ lo_lseek64 
+------------
+ 5000000000
+(1 row)
+
+SELECT lo_tell64(fd) FROM lotest_stash_values;
+ lo_tell64  
+------------
+ 5000000000
+(1 row)
+
+SELECT lo_truncate64(fd, 3000000000) FROM lotest_stash_values;
+ lo_truncate64 
+---------------
+             0
+(1 row)
+
+SELECT lo_lseek64(fd, 0, 2) FROM lotest_stash_values;
+ lo_lseek64 
+------------
+ 3000000000
+(1 row)
+
+SELECT lo_tell64(fd) FROM lotest_stash_values;
+ lo_tell64  
+------------
+ 3000000000
+(1 row)
+
+SELECT lo_close(fd) FROM lotest_stash_values;
+ lo_close 
+----------
+        0
+(1 row)
+
 END;
 -- lo_unlink(lobjId oid) returns integer
 -- return value appears to always be 1