- Added support functions for the Large Objects API
authorMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 19 Oct 2006 06:08:12 +0000 (06:08 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 19 Oct 2006 06:08:12 +0000 (06:08 +0000)
- Fixed all cases of JS_GetStringBytes() and JS_NewDouble...() functions
  which required error checking
- Fixed all cases where INT_TO_JSVAL() macros had functions called into
  them, leading to possible macro side-effects

mmsoftware/js/classes/js_pgsql.c

index e88a435..c09f584 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: js_pgsql.c,v 1.10 2006/10/18 05:07:42 mmondor Exp $ */
+/* $Id: js_pgsql.c,v 1.11 2006/10/19 06:08:12 mmondor Exp $ */
 
 /*
  * Copyright (c) 2006, Matthew Mondor
@@ -8,17 +8,10 @@
 /*
  * XXX TODO XXX
  * - Verify if JS_GetStringLength() really safe to continue using
- * - Perhaps provide simpler replacement functions for query functions
- *   allowing separate parameters to be set (perhaps not necessary considering
- *   that we can provide null to an array), and expand the object in JS.
- * - All functions creating doubles or strings should check if NULL is
- *   returned.  Verify this.
  * - (maybe) make reentrant by causing optimization buffers to be part of
  *   generated objects instances's private data (using structures as necessary
  *   instead of simply wrapping around the native object's pointer
  *   (actually PGconn object).
- * - Large objects API
- * - Compare to PHP library to verify if missing any nice functions ideas
  * - See what to do about the following functions:
  *   - PQgetssl() (returns an SSL object!)
  */
@@ -36,6 +29,7 @@
 #include <jsapi.h>
 
 #include <libpq-fe.h>
+#include <libpq/libpq-fs.h>    /* Large Objects API */
 
 #include <js_pgsql.h>
 #include <js_file.h>
@@ -201,6 +195,28 @@ static void        notice_receiver(void *, const PGresult *);
 static JSBool  pgconn_m_PQsetNoticeProcessor(JSContext *, JSObject *, uintN,
                    jsval *, jsval *);
 static void    notice_processor(void *, const char *);
+static JSBool  pgconn_m_lo_creat(JSContext *, JSObject *, uintN, jsval *,
+                   jsval *);
+static JSBool  pgconn_m_lo_create(JSContext *, JSObject *, uintN, jsval *,
+                   jsval *);
+static JSBool  pgconn_m_lo_import(JSContext *, JSObject *, uintN, jsval *,
+                   jsval *);
+static JSBool  pgconn_m_lo_export(JSContext *, JSObject *, uintN, jsval *,
+                   jsval *);
+static JSBool  pgconn_m_lo_open(JSContext *, JSObject *, uintN, jsval *,
+                   jsval *);
+static JSBool  pgconn_m_lo_write(JSContext *, JSObject *, uintN, jsval *,
+                   jsval *);
+static JSBool  pgconn_m_lo_read(JSContext *, JSObject *, uintN, jsval *,
+                   jsval *);
+static JSBool  pgconn_m_lo_lseek(JSContext *, JSObject *, uintN, jsval *,
+                   jsval *);
+static JSBool  pgconn_m_lo_tell(JSContext *, JSObject *, uintN, jsval *,
+                   jsval *);
+static JSBool  pgconn_m_lo_close(JSContext *, JSObject *, uintN, jsval *,
+                   jsval *);
+static JSBool  pgconn_m_lo_unlink(JSContext *, JSObject *, uintN, jsval *,
+                   jsval *);
 
 static JSObject        *js_InitPGresultClass(JSContext *, JSObject *);
 static JSBool  pgresult_constructor(JSContext *, JSObject *, uintN, jsval *,
@@ -352,6 +368,11 @@ static struct property_spec        pg_sprops[] = {
        SP(PQERRORS_TERSE),
        SP(PQERRORS_DEFAULT),
        SP(PQERRORS_VERBOSE),
+       SP(INV_READ),
+       SP(INV_WRITE),
+       SP(SEEK_SET),
+       SP(SEEK_CUR),
+       SP(SEEK_END),
        { NULL, 0 }
 };
 
@@ -414,6 +435,17 @@ static JSFunctionSpec pgconn_methods[] = {
        { "getCopyData", pgconn_m_PQgetCopyData, 1, 0, 0 },
        { "setNoticeReceiver", pgconn_m_PQsetNoticeReceiver, 2, 0, 0 },
        { "setNoticeProcessor", pgconn_m_PQsetNoticeProcessor, 2, 0, 0 },
+       { "loCreat", pgconn_m_lo_creat, 1, 0, 0 },
+       { "loCreate", pgconn_m_lo_create, 1, 0, 0 },
+       { "loImport", pgconn_m_lo_import, 1, 0, 0 },
+       { "loExport", pgconn_m_lo_export, 2, 0, 0 },
+       { "loOpen", pgconn_m_lo_open, 2, 0, 0 },
+       { "loWrite", pgconn_m_lo_write, 2, 0, 0 },
+       { "loRead", pgconn_m_lo_read, 2, 0, 0 },
+       { "loSeek", pgconn_m_lo_lseek, 3, 0, 0 },
+       { "loTell", pgconn_m_lo_tell, 1, 0, 0 },
+       { "loClose", pgconn_m_lo_close, 1, 0, 0 },
+       { "loUnlink", pgconn_m_lo_unlink, 1, 0, 0 },
        { NULL, NULL, 0, 0, 0 }
 };
 
@@ -762,11 +794,11 @@ pg_sm_PQconnectdb(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                QUEUE_EXCEPTION("Wrong number of arguments");
                goto err;
        }
-       if (!JSVAL_IS_STRING(argv[0])) {
+       if (!JSVAL_IS_STRING(argv[0]) ||
+           (str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
                QUEUE_EXCEPTION("Argument not a String");
                goto err;
        }
-       str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
 
        if ((o = JS_NewObject(cx, &pgconn_class, NULL, NULL)) == NULL) {
                QUEUE_EXCEPTION("Internal error!");
@@ -812,11 +844,11 @@ pg_sm_PQconnectStart(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                QUEUE_EXCEPTION("Wrong number of arguments");
                goto err;
        }
-       if (!JSVAL_IS_STRING(argv[0])) {
+       if (!JSVAL_IS_STRING(argv[0]) ||
+           (str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
                QUEUE_EXCEPTION("Argument not a String");
                goto err;
        }
-       str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
 
        if ((o = JS_NewObject(cx, &pgconn_class, NULL, NULL)) == NULL) {
                QUEUE_EXCEPTION("Internal error!");
@@ -895,7 +927,8 @@ pg_sm_PQunescapeBytea(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                QUEUE_EXCEPTION("Wrong number of arguments");
                goto err;
        }
-       if (!JSVAL_IS_STRING(argv[0])) {
+       if (!JSVAL_IS_STRING(argv[0]) ||
+           (from = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
                QUEUE_EXCEPTION("Argument not a String");
                goto err;
        }
@@ -903,8 +936,6 @@ pg_sm_PQunescapeBytea(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       from = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
-
        if ((res = PQunescapeBytea(from, &reslen)) == NULL) {
                QUEUE_EXCEPTION("PQescapeByteaConn()");
                goto err;
@@ -1027,7 +1058,7 @@ static JSBool
 pgconn_m_PQreset(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
-       PGconn                          *pgc;
+       PGconn  *pgc;
 
        if (argc != 0) {
                QUEUE_EXCEPTION("Function allows no arguments");
@@ -1049,6 +1080,7 @@ pgconn_m_PQresetStart(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
        PGconn  *pgc;
+       int     ret;
 
        if (argc != 0) {
                QUEUE_EXCEPTION("Function allows no arguments");
@@ -1059,7 +1091,8 @@ pgconn_m_PQresetStart(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       *rval = INT_TO_JSVAL(PQconnectPoll(pgc));
+       ret = PQresetStart(pgc);
+       *rval = INT_TO_JSVAL((int)ret);
 
        return JS_TRUE;
 }
@@ -1298,11 +1331,11 @@ pgconn_m_PQparameterStatus(JSContext *cx, JSObject *obj, uintN argc,
                QUEUE_EXCEPTION("Wrong number of arguments");
                return JS_FALSE;
        }
-       if (!JSVAL_IS_STRING(argv[0])) {
+       if (!JSVAL_IS_STRING(argv[0]) ||
+           (param = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
                QUEUE_EXCEPTION("Argument not a String");
                return JS_FALSE;
        }
-       param = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
 
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
@@ -1318,6 +1351,7 @@ pgconn_m_PQprotocolVersion(JSContext *cx, JSObject *obj, uintN argc,
     jsval *argv, jsval *rval)
 {
        PGconn  *pgc;
+       int     v;
 
        if (argc != 0) {
                QUEUE_EXCEPTION("Function allows no arguments");
@@ -1328,7 +1362,8 @@ pgconn_m_PQprotocolVersion(JSContext *cx, JSObject *obj, uintN argc,
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       *rval = INT_TO_JSVAL(PQprotocolVersion(pgc));
+       v = PQprotocolVersion(pgc);
+       *rval = INT_TO_JSVAL(v);
 
        return JS_TRUE;
 }
@@ -1338,6 +1373,7 @@ pgconn_m_PQserverVersion(JSContext *cx, JSObject *obj, uintN argc,
     jsval *argv, jsval *rval)
 {
        PGconn  *pgc;
+       int     v;
 
        if (argc != 0) {
                QUEUE_EXCEPTION("Function allows no arguments");
@@ -1348,7 +1384,8 @@ pgconn_m_PQserverVersion(JSContext *cx, JSObject *obj, uintN argc,
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       *rval = INT_TO_JSVAL(PQserverVersion(pgc));
+       v = PQserverVersion(pgc);
+       *rval = INT_TO_JSVAL(v);
 
        return JS_TRUE;
 }
@@ -1380,6 +1417,7 @@ pgconn_m_PQsocket(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
        PGconn  *pgc;
+       int     fd;
 
        if (argc != 0) {
                QUEUE_EXCEPTION("Function allows no arguments");
@@ -1390,7 +1428,8 @@ pgconn_m_PQsocket(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       *rval = INT_TO_JSVAL(PQsocket(pgc));
+       fd = PQsocket(pgc);
+       *rval = INT_TO_JSVAL(fd);
 
        return JS_TRUE;
 }
@@ -1400,6 +1439,7 @@ pgconn_m_PQbackendPID(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
        PGconn  *pgc;
+       int     v;
 
        if (argc != 0) {
                QUEUE_EXCEPTION("Function allows no arguments");
@@ -1410,7 +1450,8 @@ pgconn_m_PQbackendPID(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       *rval = INT_TO_JSVAL(PQbackendPID(pgc));
+       v = PQbackendPID(pgc);
+       *rval = INT_TO_JSVAL(v);
 
        return JS_TRUE;
 }
@@ -1429,11 +1470,11 @@ pgconn_m_PQexec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                goto err;
        }
 
-       if (!JSVAL_IS_STRING(argv[0])) {
+       if (!JSVAL_IS_STRING(argv[0]) ||
+           (str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
                QUEUE_EXCEPTION("Argument not a String");
                goto err;
        }
-       str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
 
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
@@ -1476,22 +1517,24 @@ pgconn_m_PQsendQuery(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
 {
        PGconn          *pgc;
        char            *str;
+       int             v;
 
        if (argc != 1) {
                QUEUE_EXCEPTION("Wrong number of arguments");
                goto err;
        }
 
-       if (!JSVAL_IS_STRING(argv[0])) {
+       if (!JSVAL_IS_STRING(argv[0]) ||
+           (str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
                QUEUE_EXCEPTION("Argument not a String");
                goto err;
        }
-       str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
 
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       *rval = INT_TO_JSVAL(PQsendQuery(pgc, str));
+       v = PQsendQuery(pgc, str);
+       *rval = INT_TO_JSVAL(v);
 
        return JS_TRUE;
 
@@ -1644,8 +1687,11 @@ pgconn_m_PQexecParams2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                                        QUEUE_EXCEPTION(str);
                                        goto err;
                                }
-                               values[i2++] = JS_GetStringBytes(
-                                   JSVAL_TO_STRING(val));
+                               if ((values[i2++] = JS_GetStringBytes(
+                                   JSVAL_TO_STRING(val))) == NULL) {
+                                       QUEUE_EXCEPTION("Internal error!");
+                                       goto err;
+                               }
                        }
                }
                JS_DestroyIdArray(cx, a);
@@ -1712,11 +1758,17 @@ pgconn_m_PQexecParams2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        assert(pgc != NULL);
 
        if (!async) {
+               char    *str;
 
-               if ((pgr = PQexecParams(pgc,
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[0])),
-                   nargs, types, (const char * const *)values, lengths,
-                   formats, JSVAL_TO_INT(argv[6]))) == NULL) {
+               if ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
+                   == NULL) {
+                       QUEUE_EXCEPTION("Internal error!");
+                       goto err;
+               }
+
+               if ((pgr = PQexecParams(pgc, str, nargs, types,
+                   (const char * const *)values, lengths, formats,
+                   JSVAL_TO_INT(argv[6]))) == NULL) {
                        QUEUE_EXCEPTION("PQexecParams()");
                        goto err;
                }
@@ -1740,12 +1792,19 @@ pgconn_m_PQexecParams2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                }
 
        } else {
+               int     v;
+               char    *str;
 
-               *rval = INT_TO_JSVAL(PQsendQueryParams(pgc,
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[0])),
-                   nargs, types, (const char * const *)values, lengths,
-                   formats, JSVAL_TO_INT(argv[6])));
+               if ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
+                   == NULL) {
+                       QUEUE_EXCEPTION("Internal error!");
+                       goto err;
+               }
 
+               v = PQsendQueryParams(pgc, str, nargs, types,
+                   (const char * const *)values, lengths, formats,
+                   JSVAL_TO_INT(argv[6]));
+               *rval = INT_TO_JSVAL(v);
        }
 
        return JS_TRUE;
@@ -1882,11 +1941,16 @@ pgconn_m_PQprepare2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        assert(pgc != NULL);
 
        if (!async) {
+               char    *str1, *str2;
 
-               if ((pgr = PQprepare(pgc,
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[0])),
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[1])),
-                   nargs, types)) == NULL) {
+               if ((str1 = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
+                   == NULL || (str2 = JS_GetStringBytes(JSVAL_TO_STRING(
+                   argv[1]))) == NULL) {
+                       QUEUE_EXCEPTION("Internal error!");
+                       goto err;
+               }
+
+               if ((pgr = PQprepare(pgc, str1, str2, nargs, types)) == NULL) {
                        QUEUE_EXCEPTION("PQprepare()");
                        goto err;
                }
@@ -1910,11 +1974,18 @@ pgconn_m_PQprepare2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                }
 
        } else {
+               int     v;
+               char    *str1, *str2;
+
+               if ((str1 = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
+                   == NULL || (str2 = JS_GetStringBytes(JSVAL_TO_STRING(
+                   argv[1]))) == NULL) {
+                       QUEUE_EXCEPTION("Internal error!");
+                       goto err;
+               }
 
-               *rval = INT_TO_JSVAL(PQsendPrepare(pgc,
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[0])),
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[1])),
-                   nargs, types));
+               v = PQsendPrepare(pgc, str1, str2, nargs, types);
+               *rval = INT_TO_JSVAL(v);
 
        }
 
@@ -2055,8 +2126,11 @@ pgconn_m_PQexecPrepared2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                                        QUEUE_EXCEPTION(str);
                                        goto err;
                                }
-                               values[i2++] = JS_GetStringBytes(
-                                   JSVAL_TO_STRING(val));
+                               if ((values[i2++] = JS_GetStringBytes(
+                                   JSVAL_TO_STRING(val))) == NULL) {
+                                       QUEUE_EXCEPTION("Internal error!");
+                                       goto err;
+                               }
                        }
                }
                JS_DestroyIdArray(cx, a);
@@ -2123,10 +2197,16 @@ pgconn_m_PQexecPrepared2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        assert(pgc != NULL);
 
        if (!async) {
+               char    *str;
 
-               if ((pgr = PQexecPrepared(pgc,
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[0])),
-                   nargs, (const char * const *)values, lengths, formats,
+               if ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
+                   == NULL) {
+                       QUEUE_EXCEPTION("Internal error!");
+                       goto err;
+               }
+
+               if ((pgr = PQexecPrepared(pgc, str, nargs,
+                   (const char * const *)values, lengths, formats,
                    JSVAL_TO_INT(argv[5]))) == NULL) {
                        QUEUE_EXCEPTION("PQexecPrepared()");
                        goto err;
@@ -2151,12 +2231,19 @@ pgconn_m_PQexecPrepared2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                }
 
        } else {
+               int     v;
+               char    *str;
 
-               *rval = INT_TO_JSVAL(PQsendQueryPrepared(pgc,
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[0])),
-                   nargs, (const char * const *)values, lengths, formats,
-                   JSVAL_TO_INT(argv[5])));
+               if ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
+                   == NULL) {
+                       QUEUE_EXCEPTION("Internal error!");
+                       goto err;
+               }
 
+               v = PQsendQueryPrepared(pgc, str, nargs,
+                   (const char * const *)values, lengths, formats,
+                   JSVAL_TO_INT(argv[5]));
+               *rval = INT_TO_JSVAL(v);
        }
 
        return JS_TRUE;
@@ -2272,7 +2359,10 @@ pgconn_m_PQescapeStringConn(JSContext *cx, JSObject *obj, uintN argc,
        assert(pgc != NULL);
 
        str = JSVAL_TO_STRING(argv[0]);
-       from = JS_GetStringBytes(str);
+       if ((from = JS_GetStringBytes(str)) == NULL) {
+               QUEUE_EXCEPTION("Internal error!");
+               goto err;
+       }
        len = JS_GetStringLength(str);
 
        if (buffer_grow((len * 2) + 2) == -1) {
@@ -2330,7 +2420,10 @@ pgconn_m_PQescapeByteaConn(JSContext *cx, JSObject *obj, uintN argc,
        assert(pgc != NULL);
 
        str = JSVAL_TO_STRING(argv[0]);
-       from = JS_GetStringBytes(str);
+       if ((from = JS_GetStringBytes(str)) == NULL) {
+               QUEUE_EXCEPTION("Internal error!");
+               goto err;
+       }
        fromlen = JS_GetStringLength(str);
 
        if ((res = PQescapeByteaConn(pgc, from, fromlen, &reslen)) == NULL) {
@@ -2519,7 +2612,8 @@ static JSBool
 pgconn_m_PQconsumeInput(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
-       PGconn          *pgc;
+       PGconn  *pgc;
+       int     v;
 
        if (argc != 0) {
                QUEUE_EXCEPTION("Function allows no arguments");
@@ -2530,7 +2624,8 @@ pgconn_m_PQconsumeInput(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       *rval = INT_TO_JSVAL(PQconsumeInput(pgc));
+       v = PQconsumeInput(pgc);
+       *rval = INT_TO_JSVAL(v);
 
        return JS_TRUE;
 }
@@ -2539,7 +2634,8 @@ static JSBool
 pgconn_m_PQisBusy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
-       PGconn          *pgc;
+       PGconn  *pgc;
+       int     v;
 
        if (argc != 0) {
                QUEUE_EXCEPTION("Function allows no arguments");
@@ -2550,7 +2646,8 @@ pgconn_m_PQisBusy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       *rval = INT_TO_JSVAL(PQisBusy(pgc));
+       v = PQisBusy(pgc);
+       *rval = INT_TO_JSVAL(v);
 
        return JS_TRUE;
 }
@@ -2559,7 +2656,8 @@ static JSBool
 pgconn_m_PQsetnonblocking(JSContext *cx, JSObject *obj, uintN argc,
     jsval *argv, jsval *rval)
 {
-       PGconn          *pgc;
+       PGconn  *pgc;
+       int     v;
 
        if (argc != 1) {
                QUEUE_EXCEPTION("Wrong number of arguments");
@@ -2573,7 +2671,8 @@ pgconn_m_PQsetnonblocking(JSContext *cx, JSObject *obj, uintN argc,
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       *rval = INT_TO_JSVAL(PQsetnonblocking(pgc, JSVAL_TO_INT(argv[0])));
+       v = PQsetnonblocking(pgc, JSVAL_TO_INT(argv[0]));
+       *rval = INT_TO_JSVAL(v);
 
        return JS_TRUE;
 
@@ -2587,7 +2686,8 @@ static JSBool
 pgconn_m_PQisnonblocking(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
-       PGconn          *pgc;
+       PGconn  *pgc;
+       int     v;
 
        if (argc != 0) {
                QUEUE_EXCEPTION("Function allows no arguments");
@@ -2598,7 +2698,8 @@ pgconn_m_PQisnonblocking(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       *rval = INT_TO_JSVAL(PQisnonblocking(pgc));
+       v = PQisnonblocking(pgc);
+       *rval = INT_TO_JSVAL(v);
 
        return JS_TRUE;
 }
@@ -2607,7 +2708,8 @@ static JSBool
 pgconn_m_PQflush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
-       PGconn          *pgc;
+       PGconn  *pgc;
+       int     v;
 
        if (argc != 0) {
                QUEUE_EXCEPTION("Function allows no arguments");
@@ -2618,7 +2720,8 @@ pgconn_m_PQflush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       *rval = INT_TO_JSVAL(PQflush(pgc));
+       v = PQflush(pgc);
+       *rval = INT_TO_JSVAL(v);
 
        return JS_TRUE;
 }
@@ -2628,6 +2731,7 @@ pgconn_m_PQsetErrorVerbosity(JSContext *cx, JSObject *obj, uintN argc,
     jsval *argv, jsval *rval)
 {
        PGconn  *pgc;
+       int     v;
 
        if (argc != 1) {
                QUEUE_EXCEPTION("Wrong number of arguments");
@@ -2641,7 +2745,8 @@ pgconn_m_PQsetErrorVerbosity(JSContext *cx, JSObject *obj, uintN argc,
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       *rval = INT_TO_JSVAL(PQsetErrorVerbosity(pgc, JSVAL_TO_INT(argv[0])));
+       v = PQsetErrorVerbosity(pgc, JSVAL_TO_INT(argv[0]));
+       *rval = INT_TO_JSVAL(v);
 
        return JS_TRUE;
 
@@ -2734,6 +2839,8 @@ pgconn_m_PQputCopyData(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
 {
        PGconn          *pgc;
        JSString        *str;
+       char            *bytes;
+       int             v;
 
        if (argc != 1) {
                QUEUE_EXCEPTION("Wrong number of arguments");
@@ -2748,8 +2855,12 @@ pgconn_m_PQputCopyData(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        assert(pgc != NULL);
 
        str = JSVAL_TO_STRING(argv[0]);
-       *rval = INT_TO_JSVAL(PQputCopyData(pgc, JS_GetStringBytes(str),
-           JS_GetStringLength(str)));
+       if ((bytes = JS_GetStringBytes(str)) == NULL) {
+               QUEUE_EXCEPTION("Internal error!");
+               goto err;
+       }
+       v = PQputCopyData(pgc, bytes, JS_GetStringLength(str));
+       *rval = INT_TO_JSVAL(v);
 
        return JS_TRUE;
 
@@ -2763,7 +2874,8 @@ static JSBool
 pgconn_m_PQputCopyEnd(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
-       PGconn          *pgc;
+       PGconn  *pgc;
+       int     v;
 
        if (argc != 1) {
                QUEUE_EXCEPTION("Wrong number of arguments");
@@ -2777,8 +2889,9 @@ pgconn_m_PQputCopyEnd(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
        assert(pgc != NULL);
 
-       *rval = INT_TO_JSVAL(PQputCopyEnd(pgc, (JSVAL_IS_NULL(argv[0]) ? NULL :
-           JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))));
+       v = PQputCopyEnd(pgc, (JSVAL_IS_NULL(argv[0]) ? NULL :
+           JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))));
+       *rval = INT_TO_JSVAL(v);
 
        return JS_TRUE;
 
@@ -2863,11 +2976,11 @@ pgconn_m_PQsetNoticeReceiver(JSContext *cx, JSObject *obj, uintN argc,
        PGconn  *pgc;
 
        /*
-        * Verify if our connection object has the np_function property set,
+        * Verify if our connection object has the nr_function property set,
         * in which case we set it as the return code.  If it doesn't have
         * any, return null.
         */
-       if (!JS_GetProperty(cx, obj, "np_function", &rval[0]))
+       if (!JS_GetProperty(cx, obj, "nr_function", &rval[0]))
                *rval = OBJECT_TO_JSVAL(NULL);
 
        if (argc != 2) {
@@ -2885,16 +2998,16 @@ pgconn_m_PQsetNoticeReceiver(JSContext *cx, JSObject *obj, uintN argc,
        }
 
        /*
-        * Set the np_function and np_udata properties.  This simplifies
+        * Set the nr_function and nr_udata properties.  This simplifies
         * things while ensuring that the ojects live as long as the
         * connection object does.  We don't make them enumerable.
         */
-       if (!JS_DefineProperty(cx, obj, "np_function", argv[0], NULL, NULL,
+       if (!JS_DefineProperty(cx, obj, "nr_function", argv[0], NULL, NULL,
            JSPROP_READONLY | JSPROP_PERMANENT)) {
                QUEUE_EXCEPTION("Internal error!");
                return JS_FALSE;
        }
-       if (!JS_DefineProperty(cx, obj, "np_udata", argv[1], NULL, NULL,
+       if (!JS_DefineProperty(cx, obj, "nr_udata", argv[1], NULL, NULL,
            JSPROP_READONLY | JSPROP_PERMANENT)) {
                QUEUE_EXCEPTION("Internal error!");
                return JS_FALSE;
@@ -2926,7 +3039,7 @@ static void
 notice_receiver(void *udata, const PGresult *pgr)
 {
        omap_t  *omap;
-       jsval   args[2], ret, pgrv, np_function, np_udata;
+       jsval   args[2], ret, pgrv, nr_function, nr_udata;
 
        omap = js_map_lookup((void *)pgr);
        assert(omap != NULL);
@@ -2945,23 +3058,23 @@ notice_receiver(void *udata, const PGresult *pgr)
         * We get out the udata and function to call from the connection
         * object.
         */
-       if (!JS_DefineProperty(omap->cx, omap->udata, "np_pgresult", pgrv,
+       if (!JS_DefineProperty(omap->cx, omap->udata, "nr_pgresult", pgrv,
            NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT))
                return;
 
-       if (!JS_GetProperty(omap->cx, omap->udata, "np_function",
-           &np_function) || !JS_GetProperty(omap->cx, omap->udata,
-           "np_udata", &np_udata))
+       if (!JS_GetProperty(omap->cx, omap->udata, "nr_function",
+           &nr_function) || !JS_GetProperty(omap->cx, omap->udata,
+           "nr_udata", &nr_udata))
                goto err;
 
-       args[0] = np_udata;
+       args[0] = nr_udata;
        args[1] = pgrv;
 
-       (void) JS_CallFunctionValue(omap->cx, omap->udata, np_function, 2,
+       (void) JS_CallFunctionValue(omap->cx, omap->udata, nr_function, 2,
            args, &ret);
 
 err:
-       (void) JS_DeleteProperty(omap->cx, omap->udata, "np_pgresult");
+       (void) JS_DeleteProperty(omap->cx, omap->udata, "nr_pgresult");
 }
 
 static JSBool
@@ -3082,6 +3195,425 @@ err:
        (void) JS_DeleteProperty(omap->cx, omap->obj, "np_message");
 }
 
+static JSBool
+pgconn_m_lo_creat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+    jsval *rval)
+{
+       PGconn  *pgc;
+       Oid     oid;
+
+       if (argc != 1) {
+               QUEUE_EXCEPTION("Wrong number of arguments");
+               goto err;
+       }
+       if (!JSVAL_IS_INT(argv[0])) {
+               QUEUE_EXCEPTION("Argument 1 not an Integer");
+               goto err;
+       }
+
+       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
+       assert(pgc != NULL);
+
+       oid = lo_creat(pgc, JSVAL_TO_INT(argv[0]));
+
+       if (!JS_NewDoubleValue(cx, (jsdouble)oid, rval)) {
+               QUEUE_EXCEPTION("Internal error!");
+               goto err;
+       }
+
+       return JS_TRUE;
+
+err:
+       *rval = OBJECT_TO_JSVAL(NULL);
+
+       return JS_FALSE;
+}
+
+static JSBool
+pgconn_m_lo_create(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+    jsval *rval)
+{
+       PGconn          *pgc;
+       Oid             oid;
+       jsdouble        v;
+
+       if (argc != 1) {
+               QUEUE_EXCEPTION("Wrong number of arguments");
+               goto err;
+       }
+       if (!JSVAL_IS_NUMBER(argv[0]) || !JS_ValueToNumber(cx, argv[0], &v)) {
+               QUEUE_EXCEPTION("Argument 1 not a number");
+               goto err;
+       }
+
+       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
+       assert(pgc != NULL);
+
+       oid = lo_create(pgc, (Oid)v);
+
+       if (!JS_NewDoubleValue(cx, (jsdouble)oid, rval)) {
+               QUEUE_EXCEPTION("Internal error!");
+               goto err;
+       }
+
+       return JS_TRUE;
+
+err:
+       *rval = OBJECT_TO_JSVAL(NULL);
+
+       return JS_FALSE;
+}
+
+static JSBool
+pgconn_m_lo_import(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+    jsval *rval)
+{
+       PGconn          *pgc;
+       Oid             oid;
+       char            *str;
+
+       if (argc != 1) {
+               QUEUE_EXCEPTION("Wrong number of arguments");
+               goto err;
+       }
+       if (!JSVAL_IS_STRING(argv[0]) ||
+           ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))) == NULL) {
+               QUEUE_EXCEPTION("Argument 1 not a String");
+               goto err;
+       }
+
+       /* XXX Perform path/access sanity checking */
+
+       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
+       assert(pgc != NULL);
+
+       oid = lo_import(pgc, str);
+
+       if (!JS_NewDoubleValue(cx, (jsdouble)oid, rval)) {
+               QUEUE_EXCEPTION("Internal error!");
+               goto err;
+       }
+
+       return JS_TRUE;
+
+err:
+       *rval = OBJECT_TO_JSVAL(NULL);
+
+       return JS_FALSE;
+}
+
+static JSBool
+pgconn_m_lo_export(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+    jsval *rval)
+{
+       PGconn          *pgc;
+       jsdouble        v;
+       char            *str;
+       int             r;
+
+       if (argc != 2) {
+               QUEUE_EXCEPTION("Wrong number of arguments");
+               goto err;
+       }
+       if (!JSVAL_IS_NUMBER(argv[0]) || !JS_ValueToNumber(cx, argv[0], &v)) {
+               QUEUE_EXCEPTION("Argument 1 not a number");
+               goto err;
+       }
+       if (!JSVAL_IS_STRING(argv[1]) ||
+           ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[1])))) == NULL) {
+               QUEUE_EXCEPTION("Argument 2 not a String");
+               goto err;
+       }
+
+       /* XXX Perform path/access sanity checking */
+
+       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
+       assert(pgc != NULL);
+
+       r = lo_export(pgc, (Oid)v, str);
+       *rval = INT_TO_JSVAL(r);
+
+       return JS_TRUE;
+
+err:
+       *rval = OBJECT_TO_JSVAL(NULL);
+
+       return JS_FALSE;
+}
+
+/*
+ * Unlike FD.open(), we don't wrap the provided integer descriptor into an
+ * object and define read()/write() function as object methods.
+ * This integer descriptor automatically becomes invalid once the transaction
+ * terminates and as such doesn't require automatic finalization.
+ */
+static JSBool
+pgconn_m_lo_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+    jsval *rval)
+{
+       PGconn          *pgc;
+       jsdouble        v;
+       int             r;
+
+       if (argc != 2) {
+               QUEUE_EXCEPTION("Wrong number of arguments");
+               goto err;
+       }
+       if (!JSVAL_IS_NUMBER(argv[0]) || !JS_ValueToNumber(cx, argv[0], &v)) {
+               QUEUE_EXCEPTION("Argument 1 not a number");
+               goto err;
+       }
+       if (!JSVAL_IS_INT(argv[1])) {
+               QUEUE_EXCEPTION("Argument 2 not an Integer");
+               goto err;
+       }
+
+       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
+       assert(pgc != NULL);
+
+       r = lo_open(pgc, (Oid)v, JSVAL_TO_INT(argv[1]));
+       *rval = INT_TO_JSVAL(r);
+
+       return JS_TRUE;
+
+err:
+       *rval = OBJECT_TO_JSVAL(NULL);
+
+       return JS_FALSE;
+}
+
+/*
+ * Unlike lo_write(), does not need a length argument, since we can obtain it
+ * using the JS string length.  Moreover, we convert to a string whatever type
+ * of data was provided to us.
+ */
+static JSBool
+pgconn_m_lo_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+    jsval *rval)
+{
+       PGconn          *pgc;
+       JSString        *str;
+       char            *bytes;
+       size_t          size;
+       int             r;
+
+       if (argc != 2) {
+               QUEUE_EXCEPTION("Wrong number of arguments");
+               goto err;
+       }
+       if (!JSVAL_IS_INT(argv[0])) {
+               QUEUE_EXCEPTION("Argument 1 not an Integer");
+               goto err;
+       }
+
+       /* Convert argv[1] to a JSString */
+       if ((str = JS_ValueToString(cx, argv[1])) == NULL ||
+           (bytes = JS_GetStringBytes(str)) == NULL) {
+               QUEUE_EXCEPTION("Internal error!");
+               goto err;
+       }
+       size = JS_GetStringLength(str);
+
+       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
+       assert(pgc != NULL);
+
+       r = lo_write(pgc, JSVAL_TO_INT(argv[0]), bytes, size);
+       *rval = INT_TO_JSVAL(r);
+
+       return JS_TRUE;
+
+err:
+       *rval = OBJECT_TO_JSVAL(NULL);
+
+       return JS_FALSE;
+}
+
+/*
+ * Unlike lo_read(), returns a JS String object rather than being provided a
+ * buffer to fill.
+ */
+static JSBool
+pgconn_m_lo_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+    jsval *rval)
+{
+       PGconn          *pgc;
+       JSString        *str;
+       uint32          size;
+       int             ret;
+
+       if (argc != 2) {
+               QUEUE_EXCEPTION("Wrong number of arguments");
+               goto err;
+       }
+       if (!JSVAL_IS_INT(argv[0])) {
+               QUEUE_EXCEPTION("Argument 1 not an Integer");
+               goto err;
+       }
+       if (!JSVAL_IS_NUMBER(argv[1]) ||
+           !JS_ValueToECMAUint32(cx, argv[1], &size)) {
+               QUEUE_EXCEPTION("Argument 1 not a number");
+               goto err;
+       }
+
+       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
+       assert(pgc != NULL);
+
+       if (buffer_grow((size_t)size) == -1) {
+               QUEUE_EXCEPTION("Out of memory!");
+               goto err;
+       }
+
+       if ((ret = lo_read(pgc, JSVAL_TO_INT(argv[0]), buffer, (size_t)size))
+           < 0) {
+               QUEUE_EXCEPTION("lo_read()");
+               goto err;
+       }
+
+       if ((str = JS_NewStringCopyN(cx, buffer, (size_t)size)) == NULL) {
+               QUEUE_EXCEPTION("Out of memory!");
+               goto err;
+       }
+
+       *rval = STRING_TO_JSVAL(str);
+
+       return JS_TRUE;
+
+err:
+       *rval = OBJECT_TO_JSVAL(NULL);
+
+       return JS_FALSE;
+}
+
+static JSBool
+pgconn_m_lo_lseek(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+    jsval *rval)
+{
+       PGconn  *pgc;
+       int     r;
+
+       if (argc != 3) {
+               QUEUE_EXCEPTION("Wrong number of arguments");
+               goto err;
+       }
+       if (!JSVAL_IS_INT(argv[0])) {
+               QUEUE_EXCEPTION("Argument 1 not an Integer");
+               goto err;
+       }
+       if (!JSVAL_IS_INT(argv[1])) {
+               QUEUE_EXCEPTION("Argument 2 not an Integer");
+               goto err;
+       }
+       if (!JSVAL_IS_INT(argv[2])) {
+               QUEUE_EXCEPTION("Argument 3 not an Integer");
+               goto err;
+       }
+
+       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
+       assert(pgc != NULL);
+
+       r = lo_lseek(pgc, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]),
+           JSVAL_TO_INT(argv[2]));
+       *rval = INT_TO_JSVAL(r);
+
+       return JS_TRUE;
+
+err:
+       *rval = OBJECT_TO_JSVAL(NULL);
+
+       return JS_FALSE;
+}
+
+static JSBool
+pgconn_m_lo_tell(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+    jsval *rval)
+{
+       PGconn  *pgc;
+       int     r;
+
+       if (argc != 1) {
+               QUEUE_EXCEPTION("Wrong number of arguments");
+               goto err;
+       }
+       if (!JSVAL_IS_INT(argv[0])) {
+               QUEUE_EXCEPTION("Argument 1 not an Integer");
+               goto err;
+       }
+
+       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
+       assert(pgc != NULL);
+
+       r = lo_tell(pgc, JSVAL_TO_INT(argv[0]));
+       *rval = INT_TO_JSVAL(r);
+
+       return JS_TRUE;
+
+err:
+       *rval = OBJECT_TO_JSVAL(NULL);
+
+       return JS_FALSE;
+}
+
+static JSBool
+pgconn_m_lo_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+    jsval *rval)
+{
+       PGconn  *pgc;
+       int     r;
+
+       if (argc != 1) {
+               QUEUE_EXCEPTION("Wrong number of arguments");
+               goto err;
+       }
+       if (!JSVAL_IS_INT(argv[0])) {
+               QUEUE_EXCEPTION("Argument 1 not an Integer");
+               goto err;
+       }
+
+       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
+       assert(pgc != NULL);
+
+       r = lo_close(pgc, JSVAL_TO_INT(argv[0]));
+       *rval = INT_TO_JSVAL(r);
+
+       return JS_TRUE;
+
+err:
+       *rval = OBJECT_TO_JSVAL(NULL);
+
+       return JS_FALSE;
+}
+
+static JSBool
+pgconn_m_lo_unlink(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+    jsval *rval)
+{
+       PGconn          *pgc;
+       jsdouble        v;
+       int             r;
+
+       if (argc != 1) {
+               QUEUE_EXCEPTION("Wrong number of arguments");
+               goto err;
+       }
+       if (!JSVAL_IS_NUMBER(argv[0]) || !JS_ValueToNumber(cx, argv[0], &v)) {
+               QUEUE_EXCEPTION("Argument 1 not a number");
+               goto err;
+       }
+
+       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
+       assert(pgc != NULL);
+
+       r = lo_unlink(pgc, (Oid)v);
+       *rval = INT_TO_JSVAL(r);
+
+       return JS_TRUE;
+
+err:
+       *rval = OBJECT_TO_JSVAL(NULL);
+
+       return JS_FALSE;
+}
+
 
 /*
  * PGresult object control
@@ -3233,6 +3765,7 @@ pgresult_m_PQntuples(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
        PGresult        *pgr;
+       int             r;
 
        if (argc != 0) {
                QUEUE_EXCEPTION("Function allows no arguments");
@@ -3243,7 +3776,8 @@ pgresult_m_PQntuples(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
        assert(pgr != NULL);
 
-       *rval = INT_TO_JSVAL(PQntuples(pgr));
+       r = PQntuples(pgr);
+       *rval = INT_TO_JSVAL(r);
 
        return JS_TRUE;
 }
@@ -3253,6 +3787,7 @@ pgresult_m_PQnfields(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
        PGresult        *pgr;
+       int             r;
 
        if (argc != 0) {
                QUEUE_EXCEPTION("Function allows no arguments");
@@ -3263,7 +3798,8 @@ pgresult_m_PQnfields(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
        assert(pgr != NULL);
 
-       *rval = INT_TO_JSVAL(PQnfields(pgr));
+       r = PQnfields(pgr);
+       *rval = INT_TO_JSVAL(r);
 
        return JS_TRUE;
 }
@@ -3304,21 +3840,23 @@ pgresult_m_PQfnumber(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
 {
        PGresult        *pgr;
        char            *str;
+       int             r;
 
        if (argc != 1) {
                QUEUE_EXCEPTION("Wrong number of arguments");
                goto err;
        }
-       if (!JSVAL_IS_STRING(argv[0])) {
+       if (!JSVAL_IS_STRING(argv[0]) ||
+           (str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
                QUEUE_EXCEPTION("Argument not a String");
                goto err;
        }
-       str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
 
        pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
        assert(pgr != NULL);
 
-       *rval = INT_TO_JSVAL(PQfnumber(pgr, str));
+       r = PQfnumber(pgr, str);
+       *rval = INT_TO_JSVAL(r);
 
        return JS_TRUE;
 err:
@@ -3370,6 +3908,7 @@ pgresult_m_PQftablecol(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
        PGresult        *pgr;
+       int             r;
 
        if (argc != 1) {
                QUEUE_EXCEPTION("Wrong number of arguments");
@@ -3383,7 +3922,8 @@ pgresult_m_PQftablecol(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
        assert(pgr != NULL);
 
-       *rval = INT_TO_JSVAL(PQftablecol(pgr, JSVAL_TO_INT(argv[0])));
+       r = PQftablecol(pgr, JSVAL_TO_INT(argv[0]));
+       *rval = INT_TO_JSVAL(r);
 
        return JS_TRUE;
 
@@ -3403,6 +3943,7 @@ pgresult_m_PQfformat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
        PGresult        *pgr;
+       int             r;
 
        if (argc != 1) {
                QUEUE_EXCEPTION("Wrong number of arguments");
@@ -3416,7 +3957,8 @@ pgresult_m_PQfformat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
        assert(pgr != NULL);
 
-       *rval = INT_TO_JSVAL(PQfformat(pgr, JSVAL_TO_INT(argv[0])));
+       r = PQfformat(pgr, JSVAL_TO_INT(argv[0]));
+       *rval = INT_TO_JSVAL(r);
 
        return JS_TRUE;
 
@@ -3469,6 +4011,7 @@ pgresult_m_PQfmod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
        PGresult        *pgr;
+       int             r;
 
        if (argc != 1) {
                QUEUE_EXCEPTION("Wrong number of arguments");
@@ -3482,7 +4025,8 @@ pgresult_m_PQfmod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
        assert(pgr != NULL);
 
-       *rval = INT_TO_JSVAL(PQfmod(pgr, JSVAL_TO_INT(argv[0])));
+       r = PQfmod(pgr, JSVAL_TO_INT(argv[0]));
+       *rval = INT_TO_JSVAL(r);
 
        return JS_TRUE;
 
@@ -3497,6 +4041,7 @@ pgresult_m_PQfsize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
        PGresult        *pgr;
+       int             r;
 
        if (argc != 1) {
                QUEUE_EXCEPTION("Wrong number of arguments");
@@ -3510,7 +4055,8 @@ pgresult_m_PQfsize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
        assert(pgr != NULL);
 
-       *rval = INT_TO_JSVAL(PQfsize(pgr, JSVAL_TO_INT(argv[0])));
+       r = PQfsize(pgr, JSVAL_TO_INT(argv[0]));
+       *rval = INT_TO_JSVAL(r);
 
        return JS_TRUE;
 
@@ -3525,6 +4071,7 @@ pgresult_m_PQbinaryTuples(JSContext *cx, JSObject *obj, uintN argc,
     jsval *argv, jsval *rval)
 {
        PGresult        *pgr;
+       int             r;
 
        if (argc != 0) {
                QUEUE_EXCEPTION("Function allows no arguments");
@@ -3535,7 +4082,8 @@ pgresult_m_PQbinaryTuples(JSContext *cx, JSObject *obj, uintN argc,
        pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
        assert(pgr != NULL);
 
-       *rval = INT_TO_JSVAL(PQbinaryTuples(pgr));
+       r = PQbinaryTuples(pgr);
+       *rval = INT_TO_JSVAL(r);
 
        return JS_TRUE;
 }
@@ -3644,6 +4192,7 @@ pgresult_m_PQgetlength(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
     jsval *rval)
 {
        PGresult        *pgr;
+       int             r;
 
        if (argc != 2) {
                QUEUE_EXCEPTION("Wrong number of arguments");
@@ -3661,8 +4210,8 @@ pgresult_m_PQgetlength(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
        assert(pgr != NULL);
 
-       *rval = INT_TO_JSVAL(PQgetlength(pgr, JSVAL_TO_INT(argv[0]),
-           JSVAL_TO_INT(argv[1])));
+       r = PQgetlength(pgr, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]));
+       *rval = INT_TO_JSVAL(r);
 
        return JS_TRUE;
 
@@ -3998,6 +4547,7 @@ pgcancel_m_PQcancel(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        char            *str;
        size_t          len;
        JSString        *s;
+       int             r;
 
        if (argc != 1) {
                QUEUE_EXCEPTION("Wrong number of arguments");
@@ -4012,10 +4562,14 @@ pgcancel_m_PQcancel(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        assert(pgc != NULL);
 
        s = JSVAL_TO_STRING(argv[0]);
-       str = JS_GetStringBytes(s);
+       if ((str = JS_GetStringBytes(s)) == NULL) {
+               QUEUE_EXCEPTION("Internal error!");
+               goto err;
+       }
        len = JS_GetStringLength(s);
 
-       *rval = INT_TO_JSVAL(PQcancel(pgc, str, len));
+       r = PQcancel(pgc, str, len);
+       *rval = INT_TO_JSVAL(r);
 
        return JS_TRUE;