Changeset 986 for trunk


Ignore:
Timestamp:
Apr 24, 2019, 9:23:31 AM (3 months ago)
Author:
cito
Message:

Split pgmodule.c into separate files

With 6320 lines the file had become way too large.

Location:
trunk
Files:
6 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

    • Property svn:ignore
      •  

        old new  
        55.tox
        66.vagrant
         7.vs
        78BETA
        89MANIFEST
  • trunk/pgmodule.c

    r985 r986  
    11/*
    22 * $Id$
    3  * PyGres, version 2.2 A Python interface for PostgreSQL database. Written by
    4  * D'Arcy J.M. Cain, (darcy@druid.net).  Based heavily on code written by
    5  * Pascal Andre, andre@chimay.via.ecp.fr. Copyright (c) 1995, Pascal Andre
    6  * (andre@via.ecp.fr).
     3 *
     4 * PyGreSQL - a Python interface for the PostgreSQL database.
     5 *
     6 * Written by D'Arcy J.M. Cain (darcy@druid.net)
     7 * Based heavily on code written by Pascal Andre (andre@chimay.via.ecp.fr)
     8 * Copyright (c) 1995, Pascal Andre
     9 * Further modifications copyright (c) 1997-2008 by D'Arcy J.M. Cain
     10 * (darcy@PyGreSQL.org)
     11 * Further modifications copyright (c) 2009-2019 by the PyGreSQL team
     12 *
     13 * PyGreSQL is released under the PostgreSQL License, a liberal Open Source
     14 * license, similar to the BSD or MIT licenses:
    715 *
    816 * Permission to use, copy, modify, and distribute this software and its
     
    2230 * AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
    2331 * ENHANCEMENTS, OR MODIFICATIONS.
    24  *
    25  * Further modifications copyright 1997 to 2019 by D'Arcy J.M. Cain
    26  * (darcy@PyGreSQL.org) subject to the same terms and conditions as above.
    27  *
    2832 */
    2933
     
    127131
    128132/* forward declarations for types */
    129 static PyTypeObject noticeType;
    130 static PyTypeObject queryType;
    131 static PyTypeObject sourceType;
    132 static PyTypeObject largeType;
    133 static PyTypeObject connType;
     133static PyTypeObject connType, sourceType, queryType, noticeType, largeType;
    134134
    135135/* forward static declarations */
    136136static void notice_receiver(void *, const PGresult *);
    137137
    138 /* --------------------------------------------------------------------- */
    139 /* Object declarations                                                   */
    140 /* --------------------------------------------------------------------- */
     138/* object declarations */
     139
    141140typedef struct
    142141{
     
    197196#endif /* LARGE_OBJECTS */
    198197
    199 /* PyGreSQL internal types */
    200 
    201 /* simple types */
    202 #define PYGRES_INT 1
    203 #define PYGRES_LONG 2
    204 #define PYGRES_FLOAT 3
    205 #define PYGRES_DECIMAL 4
    206 #define PYGRES_MONEY 5
    207 #define PYGRES_BOOL 6
    208 /* text based types */
    209 #define PYGRES_TEXT 8
    210 #define PYGRES_BYTEA 9
    211 #define PYGRES_JSON 10
    212 #define PYGRES_OTHER 11
    213 /* array types */
    214 #define PYGRES_ARRAY 16
    215 
    216 /* --------------------------------------------------------------------- */
    217 /* Internal Functions                                                    */
    218 /* --------------------------------------------------------------------- */
    219 
    220 /* shared function for encoding and decoding strings */
    221 
    222 static PyObject *
    223 get_decoded_string(const char *str, Py_ssize_t size, int encoding)
    224 {
    225     if (encoding == pg_encoding_utf8)
    226         return PyUnicode_DecodeUTF8(str, size, "strict");
    227     if (encoding == pg_encoding_latin1)
    228         return PyUnicode_DecodeLatin1(str, size, "strict");
    229     if (encoding == pg_encoding_ascii)
    230         return PyUnicode_DecodeASCII(str, size, "strict");
    231     /* encoding name should be properly translated to Python here */
    232     return PyUnicode_Decode(str, size,
    233         pg_encoding_to_char(encoding), "strict");
    234 }
    235 
    236 static PyObject *
    237 get_encoded_string(PyObject *unicode_obj, int encoding)
    238 {
    239     if (encoding == pg_encoding_utf8)
    240         return PyUnicode_AsUTF8String(unicode_obj);
    241     if (encoding == pg_encoding_latin1)
    242         return PyUnicode_AsLatin1String(unicode_obj);
    243     if (encoding == pg_encoding_ascii)
    244         return PyUnicode_AsASCIIString(unicode_obj);
    245     /* encoding name should be properly translated to Python here */
    246     return PyUnicode_AsEncodedString(unicode_obj,
    247         pg_encoding_to_char(encoding), "strict");
    248 }
    249 
    250 /* helper functions */
    251 
    252 /* get PyGreSQL internal types for a PostgreSQL type */
    253 static int
    254 get_type(Oid pgtype)
    255 {
    256     int t;
    257 
    258     switch (pgtype) {
    259         /* simple types */
    260 
    261         case INT2OID:
    262         case INT4OID:
    263         case CIDOID:
    264         case OIDOID:
    265         case XIDOID:
    266             t = PYGRES_INT;
    267             break;
    268 
    269         case INT8OID:
    270             t = PYGRES_LONG;
    271             break;
    272 
    273         case FLOAT4OID:
    274         case FLOAT8OID:
    275             t = PYGRES_FLOAT;
    276             break;
    277 
    278         case NUMERICOID:
    279             t = PYGRES_DECIMAL;
    280             break;
    281 
    282         case CASHOID:
    283             t = decimal_point ? PYGRES_MONEY : PYGRES_TEXT;
    284             break;
    285 
    286         case BOOLOID:
    287             t = PYGRES_BOOL;
    288             break;
    289 
    290         case BYTEAOID:
    291             t = bytea_escaped ? PYGRES_TEXT : PYGRES_BYTEA;
    292             break;
    293 
    294         case JSONOID:
    295         case JSONBOID:
    296             t = jsondecode ? PYGRES_JSON : PYGRES_TEXT;
    297             break;
    298 
    299         case BPCHAROID:
    300         case CHAROID:
    301         case TEXTOID:
    302         case VARCHAROID:
    303         case NAMEOID:
    304         case REGTYPEOID:
    305             t = PYGRES_TEXT;
    306             break;
    307 
    308         /* array types */
    309 
    310         case INT2ARRAYOID:
    311         case INT4ARRAYOID:
    312         case CIDARRAYOID:
    313         case OIDARRAYOID:
    314         case XIDARRAYOID:
    315             t = array_as_text ? PYGRES_TEXT : (PYGRES_INT | PYGRES_ARRAY);
    316             break;
    317 
    318         case INT8ARRAYOID:
    319             t = array_as_text ? PYGRES_TEXT : (PYGRES_LONG | PYGRES_ARRAY);
    320             break;
    321 
    322         case FLOAT4ARRAYOID:
    323         case FLOAT8ARRAYOID:
    324             t = array_as_text ? PYGRES_TEXT : (PYGRES_FLOAT | PYGRES_ARRAY);
    325             break;
    326 
    327         case NUMERICARRAYOID:
    328             t = array_as_text ? PYGRES_TEXT : (PYGRES_DECIMAL | PYGRES_ARRAY);
    329             break;
    330 
    331         case MONEYARRAYOID:
    332             t = array_as_text ? PYGRES_TEXT : ((decimal_point ?
    333                 PYGRES_MONEY : PYGRES_TEXT) | PYGRES_ARRAY);
    334             break;
    335 
    336         case BOOLARRAYOID:
    337             t = array_as_text ? PYGRES_TEXT : (PYGRES_BOOL | PYGRES_ARRAY);
    338             break;
    339 
    340         case BYTEAARRAYOID:
    341             t = array_as_text ? PYGRES_TEXT : ((bytea_escaped ?
    342                 PYGRES_TEXT : PYGRES_BYTEA) | PYGRES_ARRAY);
    343             break;
    344 
    345         case JSONARRAYOID:
    346         case JSONBARRAYOID:
    347             t = array_as_text ? PYGRES_TEXT : ((jsondecode ?
    348                 PYGRES_JSON : PYGRES_TEXT) | PYGRES_ARRAY);
    349             break;
    350 
    351         case BPCHARARRAYOID:
    352         case CHARARRAYOID:
    353         case TEXTARRAYOID:
    354         case VARCHARARRAYOID:
    355         case NAMEARRAYOID:
    356         case REGTYPEARRAYOID:
    357             t = array_as_text ? PYGRES_TEXT : (PYGRES_TEXT | PYGRES_ARRAY);
    358             break;
    359 
    360         default:
    361             t = PYGRES_OTHER;
    362     }
    363 
    364     return t;
    365 }
    366 
    367 /* get PyGreSQL column types for all result columns */
    368 static int *
    369 get_col_types(PGresult *result, int nfields)
    370 {
    371     int *types, *t, j;
    372 
    373     if (!(types = PyMem_Malloc(sizeof(int) * nfields))) {
    374         return (int*) PyErr_NoMemory();
    375     }
    376 
    377     for (j = 0, t = types; j < nfields; ++j) {
    378         *t++ = get_type(PQftype(result, j));
    379     }
    380 
    381     return types;
    382 }
    383 
    384 /* Cast a bytea encoded text based type to a Python object.
    385    This assumes the text is null-terminated character string. */
    386 static PyObject *
    387 cast_bytea_text(char *s)
    388 {
    389     PyObject *obj;
    390     char *tmp_str;
    391     size_t str_len;
    392 
    393     /* this function should not be called when bytea_escaped is set */
    394     tmp_str = (char *) PQunescapeBytea((unsigned char*) s, &str_len);
    395     obj = PyBytes_FromStringAndSize(tmp_str, str_len);
    396     if (tmp_str) {
    397         PQfreemem(tmp_str);
    398     }
    399     return obj;
    400 }
    401 
    402 /* Cast a text based type to a Python object.
    403    This needs the character string, size and encoding. */
    404 static PyObject *
    405 cast_sized_text(char *s, Py_ssize_t size, int encoding, int type)
    406 {
    407     PyObject *obj, *tmp_obj;
    408     char *tmp_str;
    409     size_t str_len;
    410 
    411     switch (type) { /* this must be the PyGreSQL internal type */
    412 
    413         case PYGRES_BYTEA:
    414             /* this type should not be passed when bytea_escaped is set */
    415             /* we need to add a null byte */
    416             tmp_str = (char *) PyMem_Malloc(size + 1);
    417             if (!tmp_str) {
    418                 return PyErr_NoMemory();
    419             }
    420             memcpy(tmp_str, s, size);
    421             s = tmp_str; *(s + size) = '\0';
    422             tmp_str = (char *) PQunescapeBytea((unsigned char*) s, &str_len);
    423             PyMem_Free(s);
    424             if (!tmp_str) return PyErr_NoMemory();
    425             obj = PyBytes_FromStringAndSize(tmp_str, str_len);
    426             if (tmp_str) {
    427                 PQfreemem(tmp_str);
    428             }
    429             break;
    430 
    431         case PYGRES_JSON:
    432             /* this type should only be passed when jsondecode is set */
    433             obj = get_decoded_string(s, size, encoding);
    434             if (obj && jsondecode) { /* was able to decode */
    435                 tmp_obj = Py_BuildValue("(O)", obj);
    436                 obj = PyObject_CallObject(jsondecode, tmp_obj);
    437                 Py_DECREF(tmp_obj);
    438             }
    439             break;
    440 
    441         default:  /* PYGRES_TEXT */
    442 #if IS_PY3
    443             obj = get_decoded_string(s, size, encoding);
    444             if (!obj) /* cannot decode */
     198/* internal functions */
     199#include "internal.c"
     200
     201/* connection object */
     202#include "conn.c"
     203
     204/* query object */
     205#include "query.c"
     206
     207/* source object */
     208#include "source.c"
     209
     210/* notice object */
     211#include "notice.c"
     212
     213/* large objects */
     214#ifdef LARGE_OBJECTS
     215#include "large.c"
    445216#endif
    446             obj = PyBytes_FromStringAndSize(s, size);
    447     }
    448 
    449     return obj;
    450 }
    451 
    452 /* Cast an arbitrary type to a Python object using a callback function.
    453    This needs the character string, size, encoding, the Postgres type
    454    and the external typecast function to be called. */
    455 static PyObject *
    456 cast_other(char *s, Py_ssize_t size, int encoding, Oid pgtype,
    457            PyObject *cast_hook)
    458 {
    459     PyObject *obj;
    460 
    461     obj = cast_sized_text(s, size, encoding, PYGRES_TEXT);
    462 
    463     if (cast_hook) {
    464         PyObject *tmp_obj = obj;
    465         obj = PyObject_CallFunction(cast_hook, "(OI)", obj, pgtype);
    466         Py_DECREF(tmp_obj);
    467     }
    468     return obj;
    469 }
    470 
    471 /* Cast a simple type to a Python object.
    472    This needs a character string representation with a given size. */
    473 static PyObject *
    474 cast_sized_simple(char *s, Py_ssize_t size, int type)
    475 {
    476     PyObject *obj, *tmp_obj;
    477     char buf[64], *t;
    478     int i, j, n;
    479 
    480     switch (type) { /* this must be the PyGreSQL internal type */
    481 
    482         case PYGRES_INT:
    483             n = sizeof(buf) / sizeof(buf[0]) - 1;
    484             if ((int) size < n) {
    485                 n = (int) size;
    486             }
    487             for (i = 0, t = buf; i < n; ++i) {
    488                 *t++ = *s++;
    489             }
    490             *t = '\0';
    491             obj = PyInt_FromString(buf, NULL, 10);
    492             break;
    493 
    494         case PYGRES_LONG:
    495             n = sizeof(buf) / sizeof(buf[0]) - 1;
    496             if ((int) size < n) {
    497                 n = (int) size;
    498             }
    499             for (i = 0, t = buf; i < n; ++i) {
    500                 *t++ = *s++;
    501             }
    502             *t = '\0';
    503             obj = PyLong_FromString(buf, NULL, 10);
    504             break;
    505 
    506         case PYGRES_FLOAT:
    507             tmp_obj = PyStr_FromStringAndSize(s, size);
    508             obj = PyFloat_FromString(tmp_obj);
    509             Py_DECREF(tmp_obj);
    510             break;
    511 
    512         case PYGRES_MONEY:
    513             /* this type should only be passed when decimal_point is set */
    514             n = sizeof(buf) / sizeof(buf[0]) - 1;
    515             for (i = 0, j = 0; i < size && j < n; ++i, ++s) {
    516                 if (*s >= '0' && *s <= '9') {
    517                     buf[j++] = *s;
    518                 }
    519                 else if (*s == decimal_point) {
    520                     buf[j++] = '.';
    521                 }
    522                 else if (*s == '(' || *s == '-') {
    523                     buf[j++] = '-';
    524                 }
    525             }
    526             if (decimal) {
    527                 buf[j] = '\0';
    528                 obj = PyObject_CallFunction(decimal, "(s)", buf);
    529             }
    530             else {
    531                 tmp_obj = PyStr_FromString(buf);
    532                 obj = PyFloat_FromString(tmp_obj);
    533                 Py_DECREF(tmp_obj);
    534 
    535             }
    536             break;
    537 
    538         case PYGRES_DECIMAL:
    539             tmp_obj = PyStr_FromStringAndSize(s, size);
    540             obj = decimal ? PyObject_CallFunctionObjArgs(
    541                 decimal, tmp_obj, NULL) : PyFloat_FromString(tmp_obj);
    542             Py_DECREF(tmp_obj);
    543             break;
    544 
    545         case PYGRES_BOOL:
    546             /* convert to bool only if bool_as_text is not set */
    547             if (bool_as_text) {
    548                 obj = PyStr_FromString(*s == 't' ? "t" : "f");
    549             }
    550             else {
    551                 obj = *s == 't' ? Py_True : Py_False;
    552                 Py_INCREF(obj);
    553             }
    554             break;
    555 
    556         default:
    557             /* other types should never be passed, use cast_sized_text */
    558             obj = PyStr_FromStringAndSize(s, size);
    559     }
    560 
    561     return obj;
    562 }
    563 
    564 /* Cast a simple type to a Python object.
    565    This needs a null-terminated character string representation. */
    566 static PyObject *
    567 cast_unsized_simple(char *s, int type)
    568 {
    569     PyObject *obj, *tmp_obj;
    570     char buf[64];
    571     int j, n;
    572 
    573     switch (type) { /* this must be the PyGreSQL internal type */
    574 
    575         case PYGRES_INT:
    576             obj = PyInt_FromString(s, NULL, 10);
    577             break;
    578 
    579         case PYGRES_LONG:
    580             obj = PyLong_FromString(s, NULL, 10);
    581             break;
    582 
    583         case PYGRES_FLOAT:
    584             tmp_obj = PyStr_FromString(s);
    585             obj = PyFloat_FromString(tmp_obj);
    586             Py_DECREF(tmp_obj);
    587             break;
    588 
    589         case PYGRES_MONEY:
    590             /* this type should only be passed when decimal_point is set */
    591             n = sizeof(buf) / sizeof(buf[0]) - 1;
    592             for (j = 0; *s && j < n; ++s) {
    593                 if (*s >= '0' && *s <= '9') {
    594                     buf[j++] = *s;
    595                 }
    596                 else if (*s == decimal_point) {
    597                     buf[j++] = '.';
    598                 }
    599                 else if (*s == '(' || *s == '-') {
    600                     buf[j++] = '-';
    601                 }
    602             }
    603             buf[j] = '\0'; s = buf;
    604             /* FALLTHROUGH */ /* no break here */
    605 
    606         case PYGRES_DECIMAL:
    607             if (decimal) {
    608                 obj = PyObject_CallFunction(decimal, "(s)", s);
    609             }
    610             else {
    611                 tmp_obj = PyStr_FromString(s);
    612                 obj = PyFloat_FromString(tmp_obj);
    613                 Py_DECREF(tmp_obj);
    614             }
    615             break;
    616 
    617         case PYGRES_BOOL:
    618             /* convert to bool only if bool_as_text is not set */
    619             if (bool_as_text) {
    620                 obj = PyStr_FromString(*s == 't' ? "t" : "f");
    621             }
    622             else {
    623                 obj = *s == 't' ? Py_True : Py_False;
    624                 Py_INCREF(obj);
    625             }
    626             break;
    627 
    628         default:
    629             /* other types should never be passed, use cast_sized_text */
    630             obj = PyStr_FromString(s);
    631     }
    632 
    633     return obj;
    634 }
    635 
    636 /* quick case insensitive check if given sized string is null */
    637 #define STR_IS_NULL(s, n) (n == 4 && \
    638     (s[0] == 'n' || s[0] == 'N') && \
    639     (s[1] == 'u' || s[1] == 'U') && \
    640     (s[2] == 'l' || s[2] == 'L') && \
    641     (s[3] == 'l' || s[3] == 'L'))
    642 
    643 /* Cast string s with size and encoding to a Python list,
    644    using the input and output syntax for arrays.
    645    Use internal type or cast function to cast elements.
    646    The parameter delim specifies the delimiter for the elements,
    647    since some types do not use the default delimiter of a comma. */
    648 static PyObject *
    649 cast_array(char *s, Py_ssize_t size, int encoding,
    650      int type, PyObject *cast, char delim)
    651 {
    652     PyObject *result, *stack[MAX_ARRAY_DEPTH];
    653     char *end = s + size, *t;
    654     int depth, ranges = 0, level = 0;
    655 
    656     if (type) {
    657         type &= ~PYGRES_ARRAY; /* get the base type */
    658         if (!type) type = PYGRES_TEXT;
    659     }
    660     if (!delim) {
    661         delim = ',';
    662     }
    663     else if (delim == '{' || delim =='}' || delim=='\\') {
    664         PyErr_SetString(PyExc_ValueError, "Invalid array delimiter");
    665         return NULL;
    666     }
    667 
    668     /* strip blanks at the beginning */
    669     while (s != end && *s == ' ') ++s;
    670     if (*s == '[') { /* dimension ranges */
    671         int valid;
    672 
    673         for (valid = 0; !valid;) {
    674             if (s == end || *s++ != '[') break;
    675             while (s != end && *s == ' ') ++s;
    676             if (s != end && (*s == '+' || *s == '-')) ++s;
    677             if (s == end || *s < '0' || *s > '9') break;
    678             while (s != end && *s >= '0' && *s <= '9') ++s;
    679             if (s == end || *s++ != ':') break;
    680             if (s != end && (*s == '+' || *s == '-')) ++s;
    681             if (s == end || *s < '0' || *s > '9') break;
    682             while (s != end && *s >= '0' && *s <= '9') ++s;
    683             if (s == end || *s++ != ']') break;
    684             while (s != end && *s == ' ') ++s;
    685             ++ranges;
    686             if (s != end && *s == '=') {
    687                 do ++s; while (s != end && *s == ' ');
    688                 valid = 1;
    689             }
    690         }
    691         if (!valid) {
    692             PyErr_SetString(PyExc_ValueError, "Invalid array dimensions");
    693             return NULL;
    694         }
    695     }
    696     for (t = s, depth = 0; t != end && (*t == '{' || *t == ' '); ++t) {
    697         if (*t == '{') ++depth;
    698     }
    699     if (!depth) {
    700         PyErr_SetString(PyExc_ValueError,
    701                         "Array must start with a left brace");
    702         return NULL;
    703     }
    704     if (ranges && depth != ranges) {
    705         PyErr_SetString(PyExc_ValueError,
    706                         "Array dimensions do not match content");
    707         return NULL;
    708     }
    709     if (depth > MAX_ARRAY_DEPTH) {
    710         PyErr_SetString(PyExc_ValueError, "Array is too deeply nested");
    711         return NULL;
    712     }
    713     depth--; /* next level of parsing */
    714     result = PyList_New(0);
    715     if (!result) return NULL;
    716     do ++s; while (s != end && *s == ' ');
    717     /* everything is set up, start parsing the array */
    718     while (s != end) {
    719         if (*s == '}') {
    720             PyObject *subresult;
    721 
    722             if (!level) break; /* top level array ended */
    723             do ++s; while (s != end && *s == ' ');
    724             if (s == end) break; /* error */
    725             if (*s == delim) {
    726                 do ++s; while (s != end && *s == ' ');
    727                 if (s == end) break; /* error */
    728                 if (*s != '{') {
    729                     PyErr_SetString(PyExc_ValueError,
    730                                     "Subarray expected but not found");
    731                     Py_DECREF(result); return NULL;
    732                 }
    733             }
    734             else if (*s != '}') break; /* error */
    735             subresult = result;
    736             result = stack[--level];
    737             if (PyList_Append(result, subresult)) {
    738                 Py_DECREF(result); return NULL;
    739             }
    740         }
    741         else if (level == depth) { /* we expect elements at this level */
    742             PyObject *element;
    743             char *estr;
    744             Py_ssize_t esize;
    745             int escaped = 0;
    746 
    747             if (*s == '{') {
    748                 PyErr_SetString(PyExc_ValueError,
    749                                 "Subarray found where not expected");
    750                 Py_DECREF(result); return NULL;
    751             }
    752             if (*s == '"') { /* quoted element */
    753                 estr = ++s;
    754                 while (s != end && *s != '"') {
    755                     if (*s == '\\') {
    756                         ++s; if (s == end) break;
    757                         escaped = 1;
    758                     }
    759                     ++s;
    760                 }
    761                 esize = s - estr;
    762                 do ++s; while (s != end && *s == ' ');
    763             }
    764             else { /* unquoted element */
    765                 estr = s;
    766                 /* can contain blanks inside */
    767                 while (s != end && *s != '"' &&
    768                        *s != '{' && *s != '}' && *s != delim)
    769                 {
    770                     if (*s == '\\') {
    771                         ++s; if (s == end) break;
    772                         escaped = 1;
    773                     }
    774                     ++s;
    775                 }
    776                 t = s; while (t > estr && *(t - 1) == ' ') --t;
    777                 if (!(esize = t - estr)) {
    778                     s = end; break; /* error */
    779                 }
    780                 if (STR_IS_NULL(estr, esize)) /* NULL gives None */
    781                     estr = NULL;
    782             }
    783             if (s == end) break; /* error */
    784             if (estr) {
    785                 if (escaped) {
    786                     char *r;
    787                     Py_ssize_t i;
    788 
    789                     /* create unescaped string */
    790                     t = estr;
    791                     estr = (char *) PyMem_Malloc(esize);
    792                     if (!estr) {
    793                         Py_DECREF(result); return PyErr_NoMemory();
    794                     }
    795                     for (i = 0, r = estr; i < esize; ++i) {
    796                         if (*t == '\\') ++t, ++i;
    797                         *r++ = *t++;
    798                     }
    799                     esize = r - estr;
    800                 }
    801                 if (type) { /* internal casting of base type */
    802                     if (type & PYGRES_TEXT)
    803                         element = cast_sized_text(estr, esize, encoding, type);
    804                     else
    805                         element = cast_sized_simple(estr, esize, type);
    806                 }
    807                 else { /* external casting of base type */
    808 #if IS_PY3
    809                     element = encoding == pg_encoding_ascii ? NULL :
    810                         get_decoded_string(estr, esize, encoding);
    811                     if (!element) /* no decoding necessary or possible */
    812 #endif
    813                     element = PyBytes_FromStringAndSize(estr, esize);
    814                     if (element && cast) {
    815                         PyObject *tmp = element;
    816                         element = PyObject_CallFunctionObjArgs(
    817                             cast, element, NULL);
    818                         Py_DECREF(tmp);
    819                     }
    820                 }
    821                 if (escaped) PyMem_Free(estr);
    822                 if (!element) {
    823                     Py_DECREF(result); return NULL;
    824                 }
    825             }
    826             else {
    827                 Py_INCREF(Py_None); element = Py_None;
    828             }
    829             if (PyList_Append(result, element)) {
    830                 Py_DECREF(element); Py_DECREF(result); return NULL;
    831             }
    832             Py_DECREF(element);
    833             if (*s == delim) {
    834                 do ++s; while (s != end && *s == ' ');
    835                 if (s == end) break; /* error */
    836             }
    837             else if (*s != '}') break; /* error */
    838         }
    839         else { /* we expect arrays at this level */
    840             if (*s != '{') {
    841                 PyErr_SetString(PyExc_ValueError,
    842                                 "Subarray must start with a left brace");
    843                 Py_DECREF(result); return NULL;
    844             }
    845             do ++s; while (s != end && *s == ' ');
    846             if (s == end) break; /* error */
    847             stack[level++] = result;
    848             if (!(result = PyList_New(0))) return NULL;
    849         }
    850     }
    851     if (s == end || *s != '}') {
    852         PyErr_SetString(PyExc_ValueError,
    853                         "Unexpected end of array");
    854         Py_DECREF(result); return NULL;
    855     }
    856     do ++s; while (s != end && *s == ' ');
    857     if (s != end) {
    858         PyErr_SetString(PyExc_ValueError,
    859                         "Unexpected characters after end of array");
    860         Py_DECREF(result); return NULL;
    861     }
    862     return result;
    863 }
    864 
    865 /* Cast string s with size and encoding to a Python tuple.
    866    using the input and output syntax for composite types.
    867    Use array of internal types or cast function or sequence of cast
    868    functions to cast elements. The parameter len is the record size.
    869    The parameter delim can specify a delimiter for the elements,
    870    although composite types always use a comma as delimiter. */
    871 
    872 static PyObject *
    873 cast_record(char *s, Py_ssize_t size, int encoding,
    874      int *type, PyObject *cast, Py_ssize_t len, char delim)
    875 {
    876     PyObject *result, *ret;
    877     char *end = s + size, *t;
    878     Py_ssize_t i;
    879 
    880     if (!delim) {
    881         delim = ',';
    882     }
    883     else if (delim == '(' || delim ==')' || delim=='\\') {
    884         PyErr_SetString(PyExc_ValueError, "Invalid record delimiter");
    885         return NULL;
    886     }
    887 
    888     /* strip blanks at the beginning */
    889     while (s != end && *s == ' ') ++s;
    890     if (s == end || *s != '(') {
    891         PyErr_SetString(PyExc_ValueError,
    892                         "Record must start with a left parenthesis");
    893         return NULL;
    894     }
    895     result = PyList_New(0);
    896     if (!result) return NULL;
    897     i = 0;
    898     /* everything is set up, start parsing the record */
    899     while (++s != end) {
    900         PyObject *element;
    901 
    902         if (*s == ')' || *s == delim) {
    903             Py_INCREF(Py_None); element = Py_None;
    904         }
    905         else {
    906             char *estr;
    907             Py_ssize_t esize;
    908             int quoted = 0, escaped = 0;
    909 
    910             estr = s;
    911             quoted = *s == '"';
    912             if (quoted) ++s;
    913             esize = 0;
    914             while (s != end) {
    915                 if (!quoted && (*s == ')' || *s == delim))
    916                     break;
    917                 if (*s == '"') {
    918                     ++s; if (s == end) break;
    919                     if (!(quoted && *s == '"')) {
    920                         quoted = !quoted; continue;
    921                     }
    922                 }
    923                 if (*s == '\\') {
    924                     ++s; if (s == end) break;
    925                 }
    926                 ++s, ++esize;
    927             }
    928             if (s == end) break; /* error */
    929             if (estr + esize != s) {
    930                 char *r;
    931 
    932                 escaped = 1;
    933                 /* create unescaped string */
    934                 t = estr;
    935                 estr = (char *) PyMem_Malloc(esize);
    936                 if (!estr) {
    937                     Py_DECREF(result); return PyErr_NoMemory();
    938                 }
    939                 quoted = 0;
    940                 r = estr;
    941                 while (t != s) {
    942                     if (*t == '"') {
    943                         ++t;
    944                         if (!(quoted && *t == '"')) {
    945                             quoted = !quoted; continue;
    946                         }
    947                     }
    948                     if (*t == '\\') ++t;
    949                     *r++ = *t++;
    950                 }
    951             }
    952             if (type) { /* internal casting of element type */
    953                 int etype = type[i];
    954 
    955                 if (etype & PYGRES_ARRAY)
    956                     element = cast_array(
    957                         estr, esize, encoding, etype, NULL, 0);
    958                 else if (etype & PYGRES_TEXT)
    959                     element = cast_sized_text(estr, esize, encoding, etype);
    960                 else
    961                     element = cast_sized_simple(estr, esize, etype);
    962             }
    963             else { /* external casting of base type */
    964 #if IS_PY3
    965                 element = encoding == pg_encoding_ascii ? NULL :
    966                     get_decoded_string(estr, esize, encoding);
    967                 if (!element) /* no decoding necessary or possible */
    968 #endif
    969                 element = PyBytes_FromStringAndSize(estr, esize);
    970                 if (element && cast) {
    971                     if (len) {
    972                         PyObject *ecast = PySequence_GetItem(cast, i);
    973 
    974                         if (ecast) {
    975                             if (ecast != Py_None) {
    976                                 PyObject *tmp = element;
    977                                 element = PyObject_CallFunctionObjArgs(
    978                                     ecast, element, NULL);
    979                                 Py_DECREF(tmp);
    980                             }
    981                         }
    982                         else {
    983                             Py_DECREF(element); element = NULL;
    984                         }
    985                     }
    986                     else {
    987                         PyObject *tmp = element;
    988                         element = PyObject_CallFunctionObjArgs(
    989                             cast, element, NULL);
    990                         Py_DECREF(tmp);
    991                     }
    992                 }
    993             }
    994             if (escaped) PyMem_Free(estr);
    995             if (!element) {
    996                 Py_DECREF(result); return NULL;
    997             }
    998         }
    999         if (PyList_Append(result, element)) {
    1000             Py_DECREF(element); Py_DECREF(result); return NULL;
    1001         }
    1002         Py_DECREF(element);
    1003         if (len) ++i;
    1004         if (*s != delim) break; /* no next record */
    1005         if (len && i >= len) {
    1006             PyErr_SetString(PyExc_ValueError, "Too many columns");
    1007             Py_DECREF(result); return NULL;
    1008         }
    1009     }
    1010     if (s == end || *s != ')') {
    1011         PyErr_SetString(PyExc_ValueError, "Unexpected end of record");
    1012         Py_DECREF(result); return NULL;
    1013     }
    1014     do ++s; while (s != end && *s == ' ');
    1015     if (s != end) {
    1016         PyErr_SetString(PyExc_ValueError,
    1017                         "Unexpected characters after end of record");
    1018         Py_DECREF(result); return NULL;
    1019     }
    1020     if (len && i < len) {
    1021         PyErr_SetString(PyExc_ValueError, "Too few columns");
    1022         Py_DECREF(result); return NULL;
    1023     }
    1024 
    1025     ret = PyList_AsTuple(result);
    1026     Py_DECREF(result);
    1027     return ret;
    1028 }
    1029 
    1030 /* Cast string s with size and encoding to a Python dictionary.
    1031    using the input and output syntax for hstore values. */
    1032 
    1033 static PyObject *
    1034 cast_hstore(char *s, Py_ssize_t size, int encoding)
    1035 {
    1036     PyObject *result;
    1037     char *end = s + size;
    1038 
    1039     result = PyDict_New();
    1040 
    1041     /* everything is set up, start parsing the record */
    1042     while (s != end) {
    1043         char *key, *val;
    1044         PyObject *key_obj, *val_obj;
    1045         Py_ssize_t key_esc = 0, val_esc = 0, size;
    1046         int quoted;
    1047 
    1048         while (s != end && *s == ' ') ++s;
    1049         if (s == end) break;
    1050         quoted = *s == '"';
    1051         if (quoted) {
    1052             key = ++s;
    1053             while (s != end) {
    1054                 if (*s == '"') break;
    1055                 if (*s == '\\') {
    1056                     if (++s == end) break;
    1057                     ++key_esc;
    1058                 }
    1059                 ++s;
    1060             }
    1061             if (s == end) {
    1062                 PyErr_SetString(PyExc_ValueError, "Unterminated quote");
    1063                 Py_DECREF(result); return NULL;
    1064             }
    1065         }
    1066         else {
    1067             key = s;
    1068             while (s != end) {
    1069                 if (*s == '=' || *s == ' ') break;
    1070                 if (*s == '\\') {
    1071                     if (++s == end) break;
    1072                     ++key_esc;
    1073                 }
    1074                 ++s;
    1075             }
    1076             if (s == key) {
    1077                 PyErr_SetString(PyExc_ValueError, "Missing key");
    1078                 Py_DECREF(result); return NULL;
    1079             }
    1080         }
    1081         size = s - key - key_esc;
    1082         if (key_esc) {
    1083             char *r = key, *t;
    1084             key = (char *) PyMem_Malloc(size);
    1085             if (!key) {
    1086                 Py_DECREF(result); return PyErr_NoMemory();
    1087             }
    1088             t = key;
    1089             while (r != s) {
    1090                 if (*r == '\\') {
    1091                     ++r; if (r == s) break;
    1092                 }
    1093                 *t++ = *r++;
    1094             }
    1095         }
    1096         key_obj = cast_sized_text(key, size, encoding, PYGRES_TEXT);
    1097         if (key_esc) PyMem_Free(key);
    1098         if (!key_obj) {
    1099             Py_DECREF(result); return NULL;
    1100         }
    1101         if (quoted) ++s;
    1102         while (s != end && *s == ' ') ++s;
    1103         if (s == end || *s++ != '=' || s == end || *s++ != '>') {
    1104             PyErr_SetString(PyExc_ValueError, "Invalid characters after key");
    1105             Py_DECREF(key_obj); Py_DECREF(result); return NULL;
    1106         }
    1107         while (s != end && *s == ' ') ++s;
    1108         quoted = *s == '"';
    1109         if (quoted) {
    1110             val = ++s;
    1111             while (s != end) {
    1112                 if (*s == '"') break;
    1113                 if (*s == '\\') {
    1114                     if (++s == end) break;
    1115                     ++val_esc;
    1116                 }
    1117                 ++s;
    1118             }
    1119             if (s == end) {
    1120                 PyErr_SetString(PyExc_ValueError, "Unterminated quote");
    1121                 Py_DECREF(result); return NULL;
    1122             }
    1123         }
    1124         else {
    1125             val = s;
    1126             while (s != end) {
    1127                 if (*s == ',' || *s == ' ') break;
    1128                 if (*s == '\\') {
    1129                     if (++s == end) break;
    1130                     ++val_esc;
    1131                 }
    1132                 ++s;
    1133             }
    1134             if (s == val) {
    1135                 PyErr_SetString(PyExc_ValueError, "Missing value");
    1136                 Py_DECREF(key_obj); Py_DECREF(result); return NULL;
    1137             }
    1138             if (STR_IS_NULL(val, s - val))
    1139                 val = NULL;
    1140         }
    1141         if (val) {
    1142             size = s - val - val_esc;
    1143             if (val_esc) {
    1144                 char *r = val, *t;
    1145                 val = (char *) PyMem_Malloc(size);
    1146                 if (!val) {
    1147                     Py_DECREF(key_obj); Py_DECREF(result);
    1148                     return PyErr_NoMemory();
    1149                 }
    1150                 t = val;
    1151                 while (r != s) {
    1152                     if (*r == '\\') {
    1153                         ++r; if (r == s) break;
    1154                     }
    1155                     *t++ = *r++;
    1156                 }
    1157             }
    1158             val_obj = cast_sized_text(val, size, encoding, PYGRES_TEXT);
    1159             if (val_esc) PyMem_Free(val);
    1160             if (!val_obj) {
    1161                 Py_DECREF(key_obj); Py_DECREF(result); return NULL;
    1162             }
    1163         }
    1164         else {
    1165             Py_INCREF(Py_None); val_obj = Py_None;
    1166         }
    1167         if (quoted) ++s;
    1168         while (s != end && *s == ' ') ++s;
    1169         if (s != end) {
    1170             if (*s++ != ',') {
    1171                 PyErr_SetString(PyExc_ValueError,
    1172                                 "Invalid characters after val");
    1173                 Py_DECREF(key_obj); Py_DECREF(val_obj);
    1174                 Py_DECREF(result); return NULL;
    1175             }
    1176             while (s != end && *s == ' ') ++s;
    1177             if (s == end) {
    1178                 PyErr_SetString(PyExc_ValueError, "Missing entry");
    1179                 Py_DECREF(key_obj); Py_DECREF(val_obj);
    1180                 Py_DECREF(result); return NULL;
    1181             }
    1182         }
    1183         PyDict_SetItem(result, key_obj, val_obj);
    1184         Py_DECREF(key_obj); Py_DECREF(val_obj);
    1185     }
    1186     return result;
    1187 }
    1188 
    1189 /* internal wrapper for the notice receiver callback */
    1190 static void
    1191 notice_receiver(void *arg, const PGresult *res)
    1192 {
    1193     PyGILState_STATE gstate = PyGILState_Ensure();
    1194     connObject *self = (connObject*) arg;
    1195     PyObject *func = self->notice_receiver;
    1196 
    1197     if (func) {
    1198         noticeObject *notice = PyObject_NEW(noticeObject, &noticeType);
    1199         PyObject *ret;
    1200         if (notice) {
    1201             notice->pgcnx = arg;
    1202             notice->res = res;
    1203         }
    1204         else {
    1205             Py_INCREF(Py_None);
    1206             notice = (noticeObject *)(void *) Py_None;
    1207         }
    1208         ret = PyObject_CallFunction(func, "(O)", notice);
    1209         Py_XDECREF(ret);
    1210     }
    1211     PyGILState_Release(gstate);
    1212 }
    1213 
    1214 /* gets appropriate error type from sqlstate */
    1215 static PyObject *
    1216 get_error_type(const char *sqlstate)
    1217 {
    1218     switch (sqlstate[0]) {
    1219         case '0':
    1220             switch (sqlstate[1]) {
    1221                 case 'A':
    1222                     return NotSupportedError;
    1223             }
    1224             break;
    1225         case '2':
    1226             switch (sqlstate[1]) {
    1227                 case '0':
    1228                 case '1':
    1229                     return ProgrammingError;
    1230                 case '2':
    1231                     return DataError;
    1232                 case '3':
    1233                     return IntegrityError;
    1234                 case '4':
    1235                 case '5':
    1236                     return InternalError;
    1237                 case '6':
    1238                 case '7':
    1239                 case '8':
    1240                     return OperationalError;
    1241                 case 'B':
    1242                 case 'D':
    1243                 case 'F':
    1244                     return InternalError;
    1245             }
    1246             break;
    1247         case '3':
    1248             switch (sqlstate[1]) {
    1249                 case '4':
    1250                     return OperationalError;
    1251                 case '8':
    1252                 case '9':
    1253                 case 'B':
    1254                     return InternalError;
    1255                 case 'D':
    1256                 case 'F':
    1257                     return ProgrammingError;
    1258             }
    1259             break;
    1260         case '4':
    1261             switch (sqlstate[1]) {
    1262                 case '0':
    1263                     return OperationalError;
    1264                 case '2':
    1265                 case '4':
    1266                     return ProgrammingError;
    1267             }
    1268             break;
    1269         case '5':
    1270         case 'H':
    1271             return OperationalError;
    1272         case 'F':
    1273         case 'P':
    1274         case 'X':
    1275             return InternalError;
    1276     }
    1277     return DatabaseError;
    1278 }
    1279 
    1280 /* sets database error message and sqlstate attribute */
    1281 static void
    1282 set_error_msg_and_state(PyObject *type,
    1283     const char *msg, int encoding, const char *sqlstate)
    1284 {
    1285     PyObject *err_obj, *msg_obj, *sql_obj = NULL;
    1286 
    1287 #if IS_PY3
    1288     if (encoding == -1) /* unknown */
    1289         msg_obj = PyUnicode_DecodeLocale(msg, NULL);
    1290     else
    1291         msg_obj = get_decoded_string(msg, strlen(msg), encoding);
    1292     if (!msg_obj) /* cannot decode */
    1293 #endif
    1294     msg_obj = PyBytes_FromString(msg);
    1295 
    1296     if (sqlstate) {
    1297         sql_obj = PyStr_FromStringAndSize(sqlstate, 5);
    1298     }
    1299     else {
    1300         Py_INCREF(Py_None); sql_obj = Py_None;
    1301     }
    1302 
    1303     err_obj = PyObject_CallFunctionObjArgs(type, msg_obj, NULL);
    1304     if (err_obj) {
    1305         Py_DECREF(msg_obj);
    1306         PyObject_SetAttrString(err_obj, "sqlstate", sql_obj);
    1307         Py_DECREF(sql_obj);
    1308         PyErr_SetObject(type, err_obj);
    1309         Py_DECREF(err_obj);
    1310     }
    1311     else {
    1312         PyErr_SetString(type, msg);
    1313     }
    1314 }
    1315 
    1316 /* sets given database error message */
    1317 static void
    1318 set_error_msg(PyObject *type, const char *msg)
    1319 {
    1320     set_error_msg_and_state(type, msg, pg_encoding_ascii, NULL);
    1321 }
    1322 
    1323 /* sets database error from connection and/or result */
    1324 static void
    1325 set_error(PyObject *type, const char * msg, PGconn *cnx, PGresult *result)
    1326 {
    1327     char *sqlstate = NULL;
    1328     int encoding = pg_encoding_ascii;
    1329 
    1330     if (cnx) {
    1331         char *err_msg = PQerrorMessage(cnx);
    1332         if (err_msg) {
    1333             msg = err_msg;
    1334             encoding = PQclientEncoding(cnx);
    1335         }
    1336     }
    1337     if (result) {
    1338         sqlstate = PQresultErrorField(result, PG_DIAG_SQLSTATE);
    1339         if (sqlstate) type = get_error_type(sqlstate);
    1340     }
    1341 
    1342     set_error_msg_and_state(type, msg, encoding, sqlstate);
    1343 }
    1344 
    1345 /* checks connection validity */
    1346 static int
    1347 check_cnx_obj(connObject *self)
    1348 {
    1349     if (!self || !self->valid || !self->cnx) {
    1350         set_error_msg(OperationalError, "Connection has been closed");
    1351         return 0;
    1352     }
    1353     return 1;
    1354 }
    1355 
    1356 /* format result (mostly useful for debugging) */
    1357 /* Note: This is similar to the Postgres function PQprint().
    1358  * PQprint() is not used because handing over a stream from Python to
    1359  * Postgres can be problematic if they use different libs for streams
    1360  * and because using PQprint() and tp_print is not recommended any more.
    1361  */
    1362 static PyObject *
    1363 format_result(const PGresult *res)
    1364 {
    1365     const int n = PQnfields(res);
    1366 
    1367     if (n > 0) {
    1368         char * const aligns = (char *) PyMem_Malloc(n * sizeof(char));
    1369         int * const sizes = (int *) PyMem_Malloc(n * sizeof(int));
    1370 
    1371         if (aligns && sizes) {
    1372             const int m = PQntuples(res);
    1373             int i, j;
    1374             size_t size;
    1375             char *buffer;
    1376 
    1377             /* calculate sizes and alignments */
    1378             for (j = 0; j < n; ++j) {
    1379                 const char * const s = PQfname(res, j);
    1380                 const int format = PQfformat(res, j);
    1381 
    1382                 sizes[j] = s ? (int) strlen(s) : 0;
    1383                 if (format) {
    1384                     aligns[j] = '\0';
    1385                     if (m && sizes[j] < 8)
    1386                         /* "<binary>" must fit */
    1387                         sizes[j] = 8;
    1388                 }
    1389                 else {
    1390                     const Oid ftype = PQftype(res, j);
    1391 
    1392                     switch (ftype) {
    1393                         case INT2OID:
    1394                         case INT4OID:
    1395                         case INT8OID:
    1396                         case FLOAT4OID:
    1397                         case FLOAT8OID:
    1398                         case NUMERICOID:
    1399                         case OIDOID:
    1400                         case XIDOID:
    1401                         case CIDOID:
    1402                         case CASHOID:
    1403                             aligns[j] = 'r';
    1404                             break;
    1405                         default:
    1406                             aligns[j] = 'l';
    1407                     }
    1408                 }
    1409             }
    1410             for (i = 0; i < m; ++i) {
    1411                 for (j = 0; j < n; ++j) {
    1412                     if (aligns[j]) {
    1413                         const int k = PQgetlength(res, i, j);
    1414 
    1415                         if (sizes[j] < k)
    1416                             /* value must fit */
    1417                             sizes[j] = k;
    1418                     }
    1419                 }
    1420             }
    1421             size = 0;
    1422             /* size of one row */
    1423             for (j = 0; j < n; ++j) size += sizes[j] + 1;
    1424             /* times number of rows incl. heading */
    1425             size *= (m + 2);
    1426             /* plus size of footer */
    1427             size += 40;
    1428             /* is the buffer size that needs to be allocated */
    1429             buffer = (char *) PyMem_Malloc(size);
    1430             if (buffer) {
    1431                 char *p = buffer;
    1432                 PyObject *result;
    1433 
    1434                 /* create the header */
    1435                 for (j = 0; j < n; ++j) {
    1436                     const char * const s = PQfname(res, j);
    1437                     const int k = sizes[j];
    1438                     const int h = (k - (int) strlen(s)) / 2;
    1439 
    1440                     sprintf(p, "%*s", h, "");
    1441                     sprintf(p + h, "%-*s", k - h, s);
    1442                     p += k;
    1443                     if (j + 1 < n)
    1444                         *p++ = '|';
    1445                 }
    1446                 *p++ = '\n';
    1447                 for (j = 0; j < n; ++j) {
    1448                     int k = sizes[j];
    1449 
    1450                     while (k--)
    1451                         *p++ = '-';
    1452                     if (j + 1 < n)
    1453                         *p++ = '+';
    1454                 }
    1455                 *p++ = '\n';
    1456                 /* create the body */
    1457                 for (i = 0; i < m; ++i) {
    1458                     for (j = 0; j < n; ++j) {
    1459                         const char align = aligns[j];
    1460                         const int k = sizes[j];
    1461 
    1462                         if (align) {
    1463                             sprintf(p, align == 'r' ? "%*s" : "%-*s", k,
    1464                                     PQgetvalue(res, i, j));
    1465                         }
    1466                         else {
    1467                             sprintf(p, "%-*s", k,
    1468                                     PQgetisnull(res, i, j) ? "" : "<binary>");
    1469                         }
    1470                         p += k;
    1471                         if (j + 1 < n)
    1472                             *p++ = '|';
    1473                     }
    1474                     *p++ = '\n';
    1475                 }
    1476                 /* free memory */
    1477                 PyMem_Free(aligns); PyMem_Free(sizes);
    1478                 /* create the footer */
    1479                 sprintf(p, "(%d row%s)", m, m == 1 ? "" : "s");
    1480                 /* return the result */
    1481                 result = PyStr_FromString(buffer);
    1482                 PyMem_Free(buffer);
    1483                 return result;
    1484             }
    1485             else {
    1486                 PyMem_Free(aligns); PyMem_Free(sizes); return PyErr_NoMemory();
    1487             }
    1488         }
    1489         else {
    1490             PyMem_Free(aligns); PyMem_Free(sizes); return PyErr_NoMemory();
    1491         }
    1492     }
    1493     else
    1494         return PyStr_FromString("(nothing selected)");
    1495 }
    1496 
    1497 /* --------------------------------------------------------------------- */
    1498 /* large objects                                                         */
    1499 /* --------------------------------------------------------------------- */
    1500 #ifdef LARGE_OBJECTS
    1501 
    1502 /* checks large object validity */
    1503 static int
    1504 check_lo_obj(largeObject *self, int level)
    1505 {
    1506     if (!check_cnx_obj(self->pgcnx))
    1507         return 0;
    1508 
    1509     if (!self->lo_oid) {
    1510         set_error_msg(IntegrityError, "Object is not valid (null oid)");
    1511         return 0;
    1512     }
    1513 
    1514     if (level & CHECK_OPEN) {
    1515         if (self->lo_fd < 0) {
    1516             PyErr_SetString(PyExc_IOError, "Object is not opened");
    1517             return 0;
    1518         }
    1519     }
    1520 
    1521     if (level & CHECK_CLOSE) {
    1522         if (self->lo_fd >= 0) {
    1523             PyErr_SetString(PyExc_IOError, "Object is already opened");
    1524             return 0;
    1525         }
    1526     }
    1527 
    1528     return 1;
    1529 }
    1530 
    1531 /* constructor (internal use only) */
    1532 static largeObject *
    1533 large_new(connObject *pgcnx, Oid oid)
    1534 {
    1535     largeObject *large_obj;
    1536 
    1537     if (!(large_obj = PyObject_NEW(largeObject, &largeType))) {
    1538         return NULL;
    1539     }
    1540 
    1541     Py_XINCREF(pgcnx);
    1542     large_obj->pgcnx = pgcnx;
    1543     large_obj->lo_fd = -1;
    1544     large_obj->lo_oid = oid;
    1545 
    1546     return large_obj;
    1547 }
    1548 
    1549 /* destructor */
    1550 static void
    1551 large_dealloc(largeObject *self)
    1552 {
    1553     if (self->lo_fd >= 0 && self->pgcnx->valid)
    1554         lo_close(self->pgcnx->cnx, self->lo_fd);
    1555 
    1556     Py_XDECREF(self->pgcnx);
    1557     PyObject_Del(self);
    1558 }
    1559 
    1560 /* opens large object */
    1561 static char large_open__doc__[] =
    1562 "open(mode) -- open access to large object with specified mode\n\n"
    1563 "The mode must be one of INV_READ, INV_WRITE (module level constants).\n";
    1564 
    1565 static PyObject *
    1566 large_open(largeObject *self, PyObject *args)
    1567 {
    1568     int mode, fd;
    1569 
    1570     /* gets arguments */
    1571     if (!PyArg_ParseTuple(args, "i", &mode)) {
    1572         PyErr_SetString(PyExc_TypeError,
    1573                         "The open() method takes an integer argument");
    1574         return NULL;
    1575     }
    1576 
    1577     /* check validity */
    1578     if (!check_lo_obj(self, CHECK_CLOSE)) {
    1579         return NULL;
    1580     }
    1581 
    1582     /* opens large object */
    1583     if ((fd = lo_open(self->pgcnx->cnx, self->lo_oid, mode)) == -1) {
    1584         PyErr_SetString(PyExc_IOError, "Can't open large object");
    1585         return NULL;
    1586     }
    1587     self->lo_fd = fd;
    1588 
    1589     /* no error : returns Py_None */
    1590     Py_INCREF(Py_None);
    1591     return Py_None;
    1592 }
    1593 
    1594 /* close large object */
    1595 static char large_close__doc__[] =
    1596 "close() -- close access to large object data";
    1597 
    1598 static PyObject *
    1599 large_close(largeObject *self, PyObject *noargs)
    1600 {
    1601     /* checks validity */
    1602     if (!check_lo_obj(self, CHECK_OPEN)) {
    1603         return NULL;
    1604     }
    1605 
    1606     /* closes large object */
    1607     if (lo_close(self->pgcnx->cnx, self->lo_fd)) {
    1608         PyErr_SetString(PyExc_IOError, "Error while closing large object fd");
    1609         return NULL;
    1610     }
    1611     self->lo_fd = -1;
    1612 
    1613     /* no error : returns Py_None */
    1614     Py_INCREF(Py_None);
    1615     return Py_None;
    1616 }
    1617 
    1618 /* reads from large object */
    1619 static char large_read__doc__[] =
    1620 "read(size) -- read from large object to sized string\n\n"
    1621 "Object must be opened in read mode before calling this method.\n";
    1622 
    1623 static PyObject *
    1624 large_read(largeObject *self, PyObject *args)
    1625 {
    1626     int size;
    1627     PyObject *buffer;
    1628 
    1629     /* gets arguments */
    1630     if (!PyArg_ParseTuple(args, "i", &size)) {
    1631         PyErr_SetString(PyExc_TypeError,
    1632                         "Method read() takes an integer argument");
    1633         return NULL;
    1634     }
    1635 
    1636     if (size <= 0) {
    1637         PyErr_SetString(PyExc_ValueError,
    1638                         "Method read() takes a positive integer as argument");
    1639         return NULL;
    1640     }
    1641 
    1642     /* checks validity */
    1643     if (!check_lo_obj(self, CHECK_OPEN)) {
    1644         return NULL;
    1645     }
    1646 
    1647     /* allocate buffer and runs read */
    1648     buffer = PyBytes_FromStringAndSize((char *) NULL, size);
    1649 
    1650     if ((size = lo_read(self->pgcnx->cnx, self->lo_fd,
    1651         PyBytes_AS_STRING((PyBytesObject *) (buffer)), size)) == -1)
    1652     {
    1653         PyErr_SetString(PyExc_IOError, "Error while reading");
    1654         Py_XDECREF(buffer);
    1655         return NULL;
    1656     }
    1657 
    1658     /* resize buffer and returns it */
    1659     _PyBytes_Resize(&buffer, size);
    1660     return buffer;
    1661 }
    1662 
    1663 /* write to large object */
    1664 static char large_write__doc__[] =
    1665 "write(string) -- write sized string to large object\n\n"
    1666 "Object must be opened in read mode before calling this method.\n";
    1667 
    1668 static PyObject *
    1669 large_write(largeObject *self, PyObject *args)
    1670 {
    1671     char *buffer;
    1672     int size, bufsize;
    1673 
    1674     /* gets arguments */
    1675     if (!PyArg_ParseTuple(args, "s#", &buffer, &bufsize)) {
    1676         PyErr_SetString(PyExc_TypeError,
    1677                         "Method write() expects a sized string as argument");
    1678         return NULL;
    1679     }
    1680 
    1681     /* checks validity */
    1682     if (!check_lo_obj(self, CHECK_OPEN)) {
    1683         return NULL;
    1684     }
    1685 
    1686     /* sends query */
    1687     if ((size = lo_write(self->pgcnx->cnx, self->lo_fd, buffer,
    1688                          bufsize)) != bufsize)
    1689     {
    1690         PyErr_SetString(PyExc_IOError, "Buffer truncated during write");
    1691         return NULL;
    1692     }
    1693 
    1694     /* no error : returns Py_None */
    1695     Py_INCREF(Py_None);
    1696     return Py_None;
    1697 }
    1698 
    1699 /* go to position in large object */
    1700 static char large_seek__doc__[] =
    1701 "seek(offset, whence) -- move to specified position\n\n"
    1702 "Object must be opened before calling this method. The whence option\n"
    1703 "can be SEEK_SET, SEEK_CUR or SEEK_END (module level constants).\n";
    1704 
    1705 static PyObject *
    1706 large_seek(largeObject *self, PyObject *args)
    1707 {
    1708     /* offset and whence are initialized to keep compiler happy */
    1709     int ret, offset = 0, whence = 0;
    1710 
    1711     /* gets arguments */
    1712     if (!PyArg_ParseTuple(args, "ii", &offset, &whence)) {
    1713         PyErr_SetString(PyExc_TypeError,
    1714                         "Method lseek() expects two integer arguments");
    1715         return NULL;
    1716     }
    1717 
    1718     /* checks validity */
    1719     if (!check_lo_obj(self, CHECK_OPEN)) {
    1720         return NULL;
    1721     }
    1722 
    1723     /* sends query */
    1724     if ((ret = lo_lseek(
    1725         self->pgcnx->cnx, self->lo_fd, offset, whence)) == -1)
    1726     {
    1727         PyErr_SetString(PyExc_IOError, "Error while moving cursor");
    1728         return NULL;
    1729     }
    1730 
    1731     /* returns position */
    1732     return PyInt_FromLong(ret);
    1733 }
    1734 
    1735 /* gets large object size */
    1736 static char large_size__doc__[] =
    1737 "size() -- return large object size\n\n"
    1738 "The object must be opened before calling this method.\n";
    1739 
    1740 static PyObject *
    1741 large_size(largeObject *self, PyObject *noargs)
    1742 {
    1743     int start, end;
    1744 
    1745     /* checks validity */
    1746     if (!check_lo_obj(self, CHECK_OPEN)) {
    1747         return NULL;
    1748     }
    1749 
    1750     /* gets current position */
    1751     if ((start = lo_tell(self->pgcnx->cnx, self->lo_fd)) == -1) {
    1752         PyErr_SetString(PyExc_IOError, "Error while getting current position");
    1753         return NULL;
    1754     }
    1755 
    1756     /* gets end position */
    1757     if ((end = lo_lseek(self->pgcnx->cnx, self->lo_fd, 0, SEEK_END)) == -1) {
    1758         PyErr_SetString(PyExc_IOError, "Error while getting end position");
    1759         return NULL;
    1760     }
    1761 
    1762     /* move back to start position */
    1763     if ((start = lo_lseek(
    1764         self->pgcnx->cnx, self->lo_fd, start, SEEK_SET)) == -1)
    1765     {
    1766         PyErr_SetString(PyExc_IOError,
    1767                         "Error while moving back to first position");
    1768         return NULL;
    1769     }
    1770 
    1771     /* returns size */
    1772     return PyInt_FromLong(end);
    1773 }
    1774 
    1775 /* gets large object cursor position */
    1776 static char large_tell__doc__[] =
    1777 "tell() -- give current position in large object\n\n"
    1778 "The object must be opened before calling this method.\n";
    1779 
    1780 static PyObject *
    1781 large_tell(largeObject *self, PyObject *noargs)
    1782 {
    1783     int start;
    1784 
    1785     /* checks validity */
    1786     if (!check_lo_obj(self, CHECK_OPEN)) {
    1787         return NULL;
    1788     }
    1789 
    1790     /* gets current position */
    1791     if ((start = lo_tell(self->pgcnx->cnx, self->lo_fd)) == -1) {
    1792         PyErr_SetString(PyExc_IOError, "Error while getting position");
    1793         return NULL;
    1794     }
    1795 
    1796     /* returns size */
    1797     return PyInt_FromLong(start);
    1798 }
    1799 
    1800 /* exports large object as unix file */
    1801 static char large_export__doc__[] =
    1802 "export(filename) -- export large object data to specified file\n\n"
    1803 "The object must be closed when calling this method.\n";
    1804 
    1805 static PyObject *
    1806 large_export(largeObject *self, PyObject *args)
    1807 {
    1808     char *name;
    1809 
    1810     /* checks validity */
    1811     if (!check_lo_obj(self, CHECK_CLOSE)) {
    1812         return NULL;
    1813     }
    1814 
    1815     /* gets arguments */
    1816     if (!PyArg_ParseTuple(args, "s", &name)) {
    1817         PyErr_SetString(PyExc_TypeError,
    1818                         "The method export() takes a filename as argument");
    1819         return NULL;
    1820     }
    1821 
    1822     /* runs command */
    1823     if (lo_export(self->pgcnx->cnx, self->lo_oid, name) != 1) {
    1824         PyErr_SetString(PyExc_IOError, "Error while exporting large object");
    1825         return NULL;
    1826     }
    1827 
    1828     Py_INCREF(Py_None);
    1829     return Py_None;
    1830 }
    1831 
    1832 /* deletes a large object */
    1833 static char large_unlink__doc__[] =
    1834 "unlink() -- destroy large object\n\n"
    1835 "The object must be closed when calling this method.\n";
    1836 
    1837 static PyObject *
    1838 large_unlink(largeObject *self, PyObject *noargs)
    1839 {
    1840     /* checks validity */
    1841     if (!check_lo_obj(self, CHECK_CLOSE)) {
    1842         return NULL;
    1843     }
    1844 
    1845     /* deletes the object, invalidate it on success */
    1846     if (lo_unlink(self->pgcnx->cnx, self->lo_oid) != 1) {
    1847         PyErr_SetString(PyExc_IOError, "Error while unlinking large object");
    1848         return NULL;
    1849     }
    1850     self->lo_oid = 0;
    1851 
    1852     Py_INCREF(Py_None);
    1853     return Py_None;
    1854 }
    1855 
    1856 /* get the list of large object attributes */
    1857 static PyObject *
    1858 large_dir(largeObject *self, PyObject *noargs)
    1859 {
    1860     PyObject *attrs;
    1861 
    1862     attrs = PyObject_Dir(PyObject_Type((PyObject *) self));
    1863     PyObject_CallMethod(
    1864         attrs, "extend", "[sss]", "oid", "pgcnx", "error");
    1865 
    1866     return attrs;
    1867 }
    1868 
    1869 /* large object methods */
    1870 static struct PyMethodDef large_methods[] = {
    1871     {"__dir__", (PyCFunction) large_dir,  METH_NOARGS, NULL},
    1872     {"open", (PyCFunction) large_open, METH_VARARGS, large_open__doc__},
    1873     {"close", (PyCFunction) large_close, METH_NOARGS, large_close__doc__},
    1874     {"read", (PyCFunction) large_read, METH_VARARGS, large_read__doc__},
    1875     {"write", (PyCFunction) large_write, METH_VARARGS, large_write__doc__},
    1876     {"seek", (PyCFunction) large_seek, METH_VARARGS, large_seek__doc__},
    1877     {"size", (PyCFunction) large_size, METH_NOARGS, large_size__doc__},
    1878     {"tell", (PyCFunction) large_tell, METH_NOARGS, large_tell__doc__},
    1879     {"export",(PyCFunction) large_export, METH_VARARGS, large_export__doc__},
    1880     {"unlink",(PyCFunction) large_unlink, METH_NOARGS, large_unlink__doc__},
    1881     {NULL, NULL}
    1882 };
    1883 
    1884 /* gets large object attributes */
    1885 static PyObject *
    1886 large_getattr(largeObject *self, PyObject *nameobj)
    1887 {
    1888     const char *name = PyStr_AsString(nameobj);
    1889 
    1890     /* list postgreSQL large object fields */
    1891 
    1892     /* associated pg connection object */
    1893     if (!strcmp(name, "pgcnx")) {
    1894         if (check_lo_obj(self, 0)) {
    1895             Py_INCREF(self->pgcnx);
    1896             return (PyObject *) (self->pgcnx);
    1897         }
    1898         PyErr_Clear();
    1899         Py_INCREF(Py_None);
    1900         return Py_None;
    1901     }
    1902 
    1903     /* large object oid */
    1904     if (!strcmp(name, "oid")) {
    1905         if (check_lo_obj(self, 0))
    1906             return PyInt_FromLong(self->lo_oid);
    1907         PyErr_Clear();
    1908         Py_INCREF(Py_None);
    1909         return Py_None;
    1910     }
    1911 
    1912     /* error (status) message */
    1913     if (!strcmp(name, "error"))
    1914         return PyStr_FromString(PQerrorMessage(self->pgcnx->cnx));
    1915 
    1916     /* seeks name in methods (fallback) */
    1917     return PyObject_GenericGetAttr((PyObject *) self, nameobj);
    1918 }
    1919 
    1920 /* return large object as string in human readable form */
    1921 static PyObject *
    1922 large_str(largeObject *self)
    1923 {
    1924     char str[80];
    1925     sprintf(str, self->lo_fd >= 0 ?
    1926             "Opened large object, oid %ld" :
    1927             "Closed large object, oid %ld", (long) self->lo_oid);
    1928     return PyStr_FromString(str);
    1929 }
    1930 
    1931 static char large__doc__[] = "PostgreSQL large object";
    1932 
    1933 /* large object type definition */
    1934 static PyTypeObject largeType = {
    1935     PyVarObject_HEAD_INIT(NULL, 0)
    1936     "pg.LargeObject",              /* tp_name */
    1937     sizeof(largeObject),           /* tp_basicsize */
    1938     0,                             /* tp_itemsize */
    1939 
    1940     /* methods */
    1941     (destructor) large_dealloc,    /* tp_dealloc */
    1942     0,                             /* tp_print */
    1943     0,                             /* tp_getattr */
    1944     0,                             /* tp_setattr */
    1945     0,                             /* tp_compare */
    1946     0,                             /* tp_repr */
    1947     0,                             /* tp_as_number */
    1948     0,                             /* tp_as_sequence */
    1949     0,                             /* tp_as_mapping */
    1950     0,                             /* tp_hash */
    1951     0,                             /* tp_call */
    1952     (reprfunc) large_str,          /* tp_str */
    1953     (getattrofunc) large_getattr,  /* tp_getattro */
    1954     0,                             /* tp_setattro */
    1955     0,                             /* tp_as_buffer */
    1956     Py_TPFLAGS_DEFAULT,            /* tp_flags */
    1957     large__doc__,                  /* tp_doc */
    1958     0,                             /* tp_traverse */
    1959     0,                             /* tp_clear */
    1960     0,                             /* tp_richcompare */
    1961     0,                             /* tp_weaklistoffset */
    1962     0,                             /* tp_iter */
    1963     0,                             /* tp_iternext */
    1964     large_methods,                 /* tp_methods */
    1965 };
    1966 #endif /* LARGE_OBJECTS */
    1967 
    1968 /* --------------------------------------------------------------------- */
    1969 /* connection object                                                     */
    1970 /* --------------------------------------------------------------------- */
    1971 static void
    1972 conn_delete(connObject *self)
    1973 {
    1974     if (self->cnx) {
    1975         Py_BEGIN_ALLOW_THREADS
    1976         PQfinish(self->cnx);
    1977         Py_END_ALLOW_THREADS
    1978     }
    1979     Py_XDECREF(self->cast_hook);
    1980     Py_XDECREF(self->notice_receiver);
    1981     PyObject_Del(self);
    1982 }
    1983 
    1984 /* source creation */
    1985 static char conn_source__doc__[] =
    1986 "source() -- create a new source object for this connection";
    1987 
    1988 static PyObject *
    1989 conn_source(connObject *self, PyObject *noargs)
    1990 {
    1991     sourceObject *source_obj;
    1992 
    1993     /* checks validity */
    1994     if (!check_cnx_obj(self)) {
    1995         return NULL;
    1996     }
    1997 
    1998     /* allocates new query object */
    1999     if (!(source_obj = PyObject_NEW(sourceObject, &sourceType))) {
    2000         return NULL;
    2001     }
    2002 
    2003     /* initializes internal parameters */
    2004     Py_XINCREF(self);
    2005     source_obj->pgcnx = self;
    2006     source_obj->result = NULL;
    2007     source_obj->valid = 1;
    2008     source_obj->arraysize = PG_ARRAYSIZE;
    2009 
    2010     return (PyObject *) source_obj;
    2011 }
    2012 
    2013 /* database query */
    2014 
    2015 /* base method for execution of both unprepared and prepared queries */
    2016 static PyObject *
    2017 _conn_query(connObject *self, PyObject *args, int prepared)
    2018 {
    2019     PyObject *query_str_obj, *param_obj = NULL;
    2020     PGresult* result;
    2021     queryObject* query_obj;
    2022     char *query;
    2023     int encoding, status, nparms = 0;
    2024 
    2025     if (!self->cnx) {
    2026         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    2027         return NULL;
    2028     }
    2029 
    2030     /* get query args */
    2031     if (!PyArg_ParseTuple(args, "O|O", &query_str_obj, &param_obj)) {
    2032         return NULL;
    2033     }
    2034 
    2035     encoding = PQclientEncoding(self->cnx);
    2036 
    2037     if (PyBytes_Check(query_str_obj)) {
    2038         query = PyBytes_AsString(query_str_obj);
    2039         query_str_obj = NULL;
    2040     }
    2041     else if (PyUnicode_Check(query_str_obj)) {
    2042         query_str_obj = get_encoded_string(query_str_obj, encoding);
    2043         if (!query_str_obj) return NULL; /* pass the UnicodeEncodeError */
    2044         query = PyBytes_AsString(query_str_obj);
    2045     }
    2046     else {
    2047         PyErr_SetString(PyExc_TypeError,
    2048                         "Method query() expects a string as first argument");
    2049         return NULL;
    2050     }
    2051 
    2052     /* If param_obj is passed, ensure it's a non-empty tuple. We want to treat
    2053      * an empty tuple the same as no argument since we'll get that when the
    2054      * caller passes no arguments to db.query(), and historic behaviour was
    2055      * to call PQexec() in that case, which can execute multiple commands. */
    2056     if (param_obj) {
    2057         param_obj = PySequence_Fast(
    2058             param_obj, "Method query() expects a sequence as second argument");
    2059         if (!param_obj) {
    2060             Py_XDECREF(query_str_obj);
    2061             return NULL;
    2062         }
    2063         nparms = (int) PySequence_Fast_GET_SIZE(param_obj);
    2064 
    2065         /* if there's a single argument and it's a list or tuple, it
    2066          * contains the positional arguments. */
    2067         if (nparms == 1) {
    2068             PyObject *first_obj = PySequence_Fast_GET_ITEM(param_obj, 0);
    2069             if (PyList_Check(first_obj) || PyTuple_Check(first_obj)) {
    2070                 Py_DECREF(param_obj);
    2071                 param_obj = PySequence_Fast(first_obj, NULL);
    2072                 nparms = (int) PySequence_Fast_GET_SIZE(param_obj);
    2073             }
    2074         }
    2075     }
    2076 
    2077     /* gets result */
    2078     if (nparms) {
    2079         /* prepare arguments */
    2080         PyObject **str, **s;
    2081         const char **parms, **p;
    2082         register int i;
    2083 
    2084         str = (PyObject **) PyMem_Malloc(nparms * sizeof(*str));
    2085         parms = (const char **) PyMem_Malloc(nparms * sizeof(*parms));
    2086         if (!str || !parms) {
    2087             PyMem_Free((void *) parms); PyMem_Free(str);
    2088             Py_XDECREF(query_str_obj); Py_XDECREF(param_obj);
    2089             return PyErr_NoMemory();
    2090         }
    2091 
    2092         /* convert optional args to a list of strings -- this allows
    2093          * the caller to pass whatever they like, and prevents us
    2094          * from having to map types to OIDs */
    2095         for (i = 0, s = str, p = parms; i < nparms; ++i, ++p) {
    2096             PyObject *obj = PySequence_Fast_GET_ITEM(param_obj, i);
    2097 
    2098             if (obj == Py_None) {
    2099                 *p = NULL;
    2100             }
    2101             else if (PyBytes_Check(obj)) {
    2102                 *p = PyBytes_AsString(obj);
    2103             }
    2104             else if (PyUnicode_Check(obj)) {
    2105                 PyObject *str_obj = get_encoded_string(obj, encoding);
    2106                 if (!str_obj) {
    2107                     PyMem_Free((void *) parms);
    2108                     while (s != str) { s--; Py_DECREF(*s); }
    2109                     PyMem_Free(str);
    2110                     Py_XDECREF(query_str_obj);
    2111                     Py_XDECREF(param_obj);
    2112                     /* pass the UnicodeEncodeError */
    2113                     return NULL;
    2114                 }
    2115                 *s++ = str_obj;
    2116                 *p = PyBytes_AsString(str_obj);
    2117             }
    2118             else {
    2119                 PyObject *str_obj = PyObject_Str(obj);
    2120                 if (!str_obj) {
    2121                     PyMem_Free((void *) parms);
    2122                     while (s != str) { s--; Py_DECREF(*s); }
    2123                     PyMem_Free(str);
    2124                     Py_XDECREF(query_str_obj);
    2125                     Py_XDECREF(param_obj);
    2126                     PyErr_SetString(
    2127                         PyExc_TypeError,
    2128                         "Query parameter has no string representation");
    2129                     return NULL;
    2130                 }
    2131                 *s++ = str_obj;
    2132                 *p = PyStr_AsString(str_obj);
    2133             }
    2134         }
    2135 
    2136         Py_BEGIN_ALLOW_THREADS
    2137         result = prepared ?
    2138             PQexecPrepared(self->cnx, query, nparms,
    2139                 parms, NULL, NULL, 0) :
    2140             PQexecParams(self->cnx, query, nparms,
    2141                 NULL, parms, NULL, NULL, 0);
    2142         Py_END_ALLOW_THREADS
    2143 
    2144         PyMem_Free((void *) parms);
    2145         while (s != str) { s--; Py_DECREF(*s); }
    2146         PyMem_Free(str);
    2147     }
    2148     else {
    2149         Py_BEGIN_ALLOW_THREADS
    2150         result = prepared ?
    2151             PQexecPrepared(self->cnx, query, 0,
    2152                 NULL, NULL, NULL, 0) :
    2153             PQexec(self->cnx, query);
    2154         Py_END_ALLOW_THREADS
    2155     }
    2156 
    2157     /* we don't need the query and its params any more */
    2158     Py_XDECREF(query_str_obj);
    2159     Py_XDECREF(param_obj);
    2160 
    2161     /* checks result validity */
    2162     if (!result) {
    2163         PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->cnx));
    2164         return NULL;
    2165     }
    2166 
    2167     /* this may have changed the datestyle, so we reset the date format
    2168        in order to force fetching it newly when next time requested */
    2169     self->date_format = date_format; /* this is normally NULL */
    2170 
    2171     /* checks result status */
    2172     if ((status = PQresultStatus(result)) != PGRES_TUPLES_OK) {
    2173         switch (status) {
    2174             case PGRES_EMPTY_QUERY:
    2175                 PyErr_SetString(PyExc_ValueError, "Empty query");
    2176                 break;
    2177             case PGRES_BAD_RESPONSE:
    2178             case PGRES_FATAL_ERROR:
    2179             case PGRES_NONFATAL_ERROR:
    2180                 set_error(ProgrammingError, "Cannot execute query",
    2181                     self->cnx, result);
    2182                 break;
    2183             case PGRES_COMMAND_OK:
    2184                 {   /* INSERT, UPDATE, DELETE */
    2185                     Oid oid = PQoidValue(result);
    2186 
    2187                     if (oid == InvalidOid) {  /* not a single insert */
    2188                         char *ret = PQcmdTuples(result);
    2189 
    2190                         if (ret[0]) {  /* return number of rows affected */
    2191                             PyObject *obj = PyStr_FromString(ret);
    2192                             PQclear(result);
    2193                             return obj;
    2194                         }
    2195                         PQclear(result);
    2196                         Py_INCREF(Py_None);
    2197                         return Py_None;
    2198                     }
    2199                     /* for a single insert, return the oid */
    2200                     PQclear(result);
    2201                     return PyInt_FromLong(oid);
    2202                 }
    2203             case PGRES_COPY_OUT: /* no data will be received */
    2204             case PGRES_COPY_IN:
    2205                 PQclear(result);
    2206                 Py_INCREF(Py_None);
    2207                 return Py_None;
    2208             default:
    2209                 set_error_msg(InternalError, "Unknown result status");
    2210         }
    2211 
    2212         PQclear(result);
    2213         return NULL; /* error detected on query */
    2214     }
    2215 
    2216     if (!(query_obj = PyObject_NEW(queryObject, &queryType)))
    2217         return PyErr_NoMemory();
    2218 
    2219     /* stores result and returns object */
    2220     Py_XINCREF(self);
    2221     query_obj->pgcnx = self;
    2222     query_obj->result = result;
    2223     query_obj->encoding = encoding;
    2224     query_obj->current_row = 0;
    2225     query_obj->max_row = PQntuples(result);
    2226     query_obj->num_fields = PQnfields(result);
    2227     query_obj->col_types = get_col_types(result, query_obj->num_fields);
    2228     if (!query_obj->col_types) {
    2229         Py_DECREF(query_obj);
    2230         Py_DECREF(self);
    2231         return NULL;
    2232     }
    2233 
    2234     return (PyObject *) query_obj;
    2235 }
    2236 
    2237 /* database query */
    2238 static char conn_query__doc__[] =
    2239 "query(sql, [arg]) -- create a new query object for this connection\n\n"
    2240 "You must pass the SQL (string) request and you can optionally pass\n"
    2241 "a tuple with positional parameters.\n";
    2242 
    2243 static PyObject *
    2244 conn_query(connObject *self, PyObject *args)
    2245 {
    2246     return _conn_query(self, args, 0);
    2247 }
    2248 
    2249 /* execute prepared statement */
    2250 static char conn_query_prepared__doc__[] =
    2251 "query_prepared(name, [arg]) -- execute a prepared statement\n\n"
    2252 "You must pass the name (string) of the prepared statement and you can\n"
    2253 "optionally pass a tuple with positional parameters.\n";
    2254 
    2255 static PyObject *
    2256 conn_query_prepared(connObject *self, PyObject *args)
    2257 {
    2258     return _conn_query(self, args, 1);
    2259 }
    2260 
    2261 /* create prepared statement */
    2262 static char conn_prepare__doc__[] =
    2263 "prepare(name, sql) -- create a prepared statement\n\n"
    2264 "You must pass the name (string) of the prepared statement and the\n"
    2265 "SQL (string) request for later execution.\n";
    2266 
    2267 static PyObject *
    2268 conn_prepare(connObject *self, PyObject *args)
    2269 {
    2270     char *name, *query;
    2271     int name_length, query_length;
    2272     PGresult *result;
    2273 
    2274     if (!self->cnx) {
    2275         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    2276         return NULL;
    2277     }
    2278 
    2279     /* reads args */
    2280     if (!PyArg_ParseTuple(args, "s#s#",
    2281         &name, &name_length, &query, &query_length))
    2282     {
    2283         PyErr_SetString(PyExc_TypeError,
    2284                         "Method prepare() takes two string arguments");
    2285         return NULL;
    2286     }
    2287 
    2288     /* create prepared statement */
    2289     Py_BEGIN_ALLOW_THREADS
    2290     result = PQprepare(self->cnx, name, query, 0, NULL);
    2291     Py_END_ALLOW_THREADS
    2292     if (result && PQresultStatus(result) == PGRES_COMMAND_OK) {
    2293         PQclear(result);
    2294         Py_INCREF(Py_None);
    2295         return Py_None; /* success */
    2296     }
    2297     set_error(ProgrammingError, "Cannot create prepared statement",
    2298         self->cnx, result);
    2299     if (result)
    2300         PQclear(result);
    2301     return NULL; /* error */
    2302 }
    2303 
    2304 /* describe prepared statement */
    2305 static char conn_describe_prepared__doc__[] =
    2306 "describe_prepared(name) -- describe a prepared statement\n\n"
    2307 "You must pass the name (string) of the prepared statement.\n";
    2308 
    2309 static PyObject *
    2310 conn_describe_prepared(connObject *self, PyObject *args)
    2311 {
    2312     char *name;
    2313     int name_length;
    2314     PGresult *result;
    2315 
    2316     if (!self->cnx) {
    2317         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    2318         return NULL;
    2319     }
    2320 
    2321     /* reads args */
    2322     if (!PyArg_ParseTuple(args, "s#", &name, &name_length)) {
    2323         PyErr_SetString(PyExc_TypeError,
    2324                         "Method prepare() takes a string argument");
    2325         return NULL;
    2326     }
    2327 
    2328     /* describe prepared statement */
    2329     Py_BEGIN_ALLOW_THREADS
    2330     result = PQdescribePrepared(self->cnx, name);
    2331     Py_END_ALLOW_THREADS
    2332     if (result && PQresultStatus(result) == PGRES_COMMAND_OK) {
    2333         queryObject *query_obj = PyObject_NEW(queryObject, &queryType);
    2334         if (!query_obj)
    2335             return PyErr_NoMemory();
    2336         Py_XINCREF(self);
    2337         query_obj->pgcnx = self;
    2338         query_obj->result = result;
    2339         query_obj->encoding = PQclientEncoding(self->cnx);
    2340         query_obj->current_row = 0;
    2341         query_obj->max_row = PQntuples(result);
    2342         query_obj->num_fields = PQnfields(result);
    2343         query_obj->col_types = get_col_types(result, query_obj->num_fields);
    2344         return (PyObject *) query_obj;
    2345     }
    2346     set_error(ProgrammingError, "Cannot describe prepared statement",
    2347         self->cnx, result);
    2348     if (result)
    2349         PQclear(result);
    2350     return NULL; /* error */
    2351 }
    2352 
    2353 #ifdef DIRECT_ACCESS
    2354 static char conn_putline__doc__[] =
    2355 "putline(line) -- send a line directly to the backend";
    2356 
    2357 /* direct access function: putline */
    2358 static PyObject *
    2359 conn_putline(connObject *self, PyObject *args)
    2360 {
    2361     char *line;
    2362     int line_length;
    2363 
    2364     if (!self->cnx) {
    2365         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    2366         return NULL;
    2367     }
    2368 
    2369     /* reads args */
    2370     if (!PyArg_ParseTuple(args, "s#", &line, &line_length)) {
    2371         PyErr_SetString(PyExc_TypeError,
    2372                         "Method putline() takes a string argument");
    2373         return NULL;
    2374     }
    2375 
    2376     /* sends line to backend */
    2377     if (PQputline(self->cnx, line)) {
    2378         PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
    2379         return NULL;
    2380     }
    2381     Py_INCREF(Py_None);
    2382     return Py_None;
    2383 }
    2384 
    2385 /* direct access function: getline */
    2386 static char conn_getline__doc__[] =
    2387 "getline() -- get a line directly from the backend";
    2388 
    2389 static PyObject *
    2390 conn_getline(connObject *self, PyObject *noargs)
    2391 {
    2392     char line[MAX_BUFFER_SIZE];
    2393     PyObject *str = NULL;     /* GCC */
    2394 
    2395     if (!self->cnx) {
    2396         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    2397         return NULL;
    2398     }
    2399 
    2400     /* gets line */
    2401     switch (PQgetline(self->cnx, line, MAX_BUFFER_SIZE)) {
    2402         case 0:
    2403             str = PyStr_FromString(line);
    2404             break;
    2405         case 1:
    2406             PyErr_SetString(PyExc_MemoryError, "Buffer overflow");
    2407             str = NULL;
    2408             break;
    2409         case EOF:
    2410             Py_INCREF(Py_None);
    2411             str = Py_None;
    2412             break;
    2413     }
    2414 
    2415     return str;
    2416 }
    2417 
    2418 /* direct access function: end copy */
    2419 static char conn_endcopy__doc__[] =
    2420 "endcopy() -- synchronize client and server";
    2421 
    2422 static PyObject *
    2423 conn_endcopy(connObject *self, PyObject *noargs)
    2424 {
    2425     if (!self->cnx) {
    2426         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    2427         return NULL;
    2428     }
    2429 
    2430     /* ends direct copy */
    2431     if (PQendcopy(self->cnx)) {
    2432         PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
    2433         return NULL;
    2434     }
    2435     Py_INCREF(Py_None);
    2436     return Py_None;
    2437 }
    2438 #endif /* DIRECT_ACCESS */
    2439 
    2440 /* return query as string in human readable form */
    2441 static PyObject *
    2442 query_str(queryObject *self)
    2443 {
    2444     return format_result(self->result);
    2445 }
    2446 
    2447 /* insert table */
    2448 static char conn_inserttable__doc__[] =
    2449 "inserttable(table, data) -- insert list into table\n\n"
    2450 "The fields in the list must be in the same order as in the table.\n";
    2451 
    2452 static PyObject *
    2453 conn_inserttable(connObject *self, PyObject *args)
    2454 {
    2455     PGresult *result;
    2456     char *table, *buffer, *bufpt;
    2457     int encoding;
    2458     size_t bufsiz;
    2459     PyObject *list, *sublist, *item;
    2460     PyObject *(*getitem) (PyObject *, Py_ssize_t);
    2461     PyObject *(*getsubitem) (PyObject *, Py_ssize_t);
    2462     Py_ssize_t i, j, m, n;
    2463 
    2464     if (!self->cnx) {
    2465         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    2466         return NULL;
    2467     }
    2468 
    2469     /* gets arguments */
    2470     if (!PyArg_ParseTuple(args, "sO:filter", &table, &list)) {
    2471         PyErr_SetString(
    2472             PyExc_TypeError,
    2473             "Method inserttable() expects a string and a list as arguments");
    2474         return NULL;
    2475     }
    2476 
    2477     /* checks list type */
    2478     if (PyTuple_Check(list)) {
    2479         m = PyTuple_Size(list);
    2480         getitem = PyTuple_GetItem;
    2481     }
    2482     else if (PyList_Check(list)) {
    2483         m = PyList_Size(list);
    2484         getitem = PyList_GetItem;
    2485     }
    2486     else {
    2487         PyErr_SetString(
    2488             PyExc_TypeError,
    2489             "Method inserttable() expects some kind of array"
    2490             " as second argument");
    2491         return NULL;
    2492     }
    2493 
    2494     /* allocate buffer */
    2495     if (!(buffer = PyMem_Malloc(MAX_BUFFER_SIZE)))
    2496         return PyErr_NoMemory();
    2497 
    2498     /* starts query */
    2499     sprintf(buffer, "copy %s from stdin", table);
    2500 
    2501     Py_BEGIN_ALLOW_THREADS
    2502     result = PQexec(self->cnx, buffer);
    2503     Py_END_ALLOW_THREADS
    2504 
    2505     if (!result) {
    2506         PyMem_Free(buffer);
    2507         PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->cnx));
    2508         return NULL;
    2509     }
    2510 
    2511     encoding = PQclientEncoding(self->cnx);
    2512 
    2513     PQclear(result);
    2514 
    2515     n = 0; /* not strictly necessary but avoids warning */
    2516 
    2517     /* feed table */
    2518     for (i = 0; i < m; ++i) {
    2519         sublist = getitem(list, i);
    2520         if (PyTuple_Check(sublist)) {
    2521             j = PyTuple_Size(sublist);
    2522             getsubitem = PyTuple_GetItem;
    2523         }
    2524         else if (PyList_Check(sublist)) {
    2525             j = PyList_Size(sublist);
    2526             getsubitem = PyList_GetItem;
    2527         }
    2528         else {
    2529             PyErr_SetString(
    2530                 PyExc_TypeError,
    2531                 "Second arg must contain some kind of arrays");
    2532             return NULL;
    2533         }
    2534         if (i) {
    2535             if (j != n) {
    2536                 PyMem_Free(buffer);
    2537                 PyErr_SetString(
    2538                     PyExc_TypeError,
    2539                     "Arrays contained in second arg must have same size");
    2540                 return NULL;
    2541             }
    2542         }
    2543         else {
    2544             n = j; /* never used before this assignment */
    2545         }
    2546 
    2547         /* builds insert line */
    2548         bufpt = buffer;
    2549         bufsiz = MAX_BUFFER_SIZE - 1;
    2550 
    2551         for (j = 0; j < n; ++j) {
    2552             if (j) {
    2553                 *bufpt++ = '\t'; --bufsiz;
    2554             }
    2555 
    2556             item = getsubitem(sublist, j);
    2557 
    2558             /* convert item to string and append to buffer */
    2559             if (item == Py_None) {
    2560                 if (bufsiz > 2) {
    2561                     *bufpt++ = '\\'; *bufpt++ = 'N';
    2562                     bufsiz -= 2;
    2563                 }
    2564                 else
    2565                     bufsiz = 0;
    2566             }
    2567             else if (PyBytes_Check(item)) {
    2568                 const char* t = PyBytes_AsString(item);
    2569 
    2570                 while (*t && bufsiz) {
    2571                     if (*t == '\\' || *t == '\t' || *t == '\n') {
    2572                         *bufpt++ = '\\'; --bufsiz;
    2573                         if (!bufsiz) break;
    2574                     }
    2575                     *bufpt++ = *t++; --bufsiz;
    2576                 }
    2577             }
    2578             else if (PyUnicode_Check(item)) {
    2579                 PyObject *s = get_encoded_string(item, encoding);
    2580                 if (!s) {
    2581                     PyMem_Free(buffer);
    2582                     return NULL; /* pass the UnicodeEncodeError */
    2583                 }
    2584                 else {
    2585                     const char* t = PyBytes_AsString(s);
    2586 
    2587                     while (*t && bufsiz) {
    2588                         if (*t == '\\' || *t == '\t' || *t == '\n') {
    2589                             *bufpt++ = '\\'; --bufsiz;
    2590                             if (!bufsiz) break;
    2591                         }
    2592                         *bufpt++ = *t++; --bufsiz;
    2593                     }
    2594                     Py_DECREF(s);
    2595                 }
    2596             }
    2597             else if (PyInt_Check(item) || PyLong_Check(item)) {
    2598                 PyObject* s = PyObject_Str(item);
    2599                 const char* t = PyStr_AsString(s);
    2600 
    2601                 while (*t && bufsiz) {
    2602                     *bufpt++ = *t++; --bufsiz;
    2603                 }
    2604                 Py_DECREF(s);
    2605             }
    2606             else {
    2607                 PyObject* s = PyObject_Repr(item);
    2608                 const char* t = PyStr_AsString(s);
    2609 
    2610                 while (*t && bufsiz) {
    2611                     if (*t == '\\' || *t == '\t' || *t == '\n') {
    2612                         *bufpt++ = '\\'; --bufsiz;
    2613                         if (!bufsiz) break;
    2614                     }
    2615                     *bufpt++ = *t++; --bufsiz;
    2616                 }
    2617                 Py_DECREF(s);
    2618             }
    2619 
    2620             if (bufsiz <= 0) {
    2621                 PyMem_Free(buffer); return PyErr_NoMemory();
    2622             }
    2623 
    2624         }
    2625 
    2626         *bufpt++ = '\n'; *bufpt = '\0';
    2627 
    2628         /* sends data */
    2629         if (PQputline(self->cnx, buffer)) {
    2630             PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
    2631             PQendcopy(self->cnx);
    2632             PyMem_Free(buffer);
    2633             return NULL;
    2634         }
    2635     }
    2636 
    2637     /* ends query */
    2638     if (PQputline(self->cnx, "\\.\n")) {
    2639         PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
    2640         PQendcopy(self->cnx);
    2641         PyMem_Free(buffer);
    2642         return NULL;
    2643     }
    2644 
    2645     if (PQendcopy(self->cnx)) {
    2646         PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
    2647         PyMem_Free(buffer);
    2648         return NULL;
    2649     }
    2650 
    2651     PyMem_Free(buffer);
    2652 
    2653     /* no error : returns nothing */
    2654     Py_INCREF(Py_None);
    2655     return Py_None;
    2656 }
    2657 
    2658 /* get transaction state */
    2659 static char conn_transaction__doc__[] =
    2660 "transaction() -- return the current transaction status";
    2661 
    2662 static PyObject *
    2663 conn_transaction(connObject *self, PyObject *noargs)
    2664 {
    2665     if (!self->cnx) {
    2666         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    2667         return NULL;
    2668     }
    2669 
    2670     return PyInt_FromLong(PQtransactionStatus(self->cnx));
    2671 }
    2672 
    2673 /* get parameter setting */
    2674 static char conn_parameter__doc__[] =
    2675 "parameter(name) -- look up a current parameter setting";
    2676 
    2677 static PyObject *
    2678 conn_parameter(connObject *self, PyObject *args)
    2679 {
    2680     const char *name;
    2681 
    2682     if (!self->cnx) {
    2683         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    2684         return NULL;
    2685     }
    2686 
    2687     /* get query args */
    2688     if (!PyArg_ParseTuple(args, "s", &name)) {
    2689         PyErr_SetString(PyExc_TypeError,
    2690                         "Method parameter() takes a string as argument");
    2691         return NULL;
    2692     }
    2693 
    2694     name = PQparameterStatus(self->cnx, name);
    2695 
    2696     if (name)
    2697         return PyStr_FromString(name);
    2698 
    2699     /* unknown parameter, return None */
    2700     Py_INCREF(Py_None);
    2701     return Py_None;
    2702 }
    2703 
    2704 /* internal function converting a Postgres datestyles to date formats */
    2705 static const char *
    2706 date_style_to_format(const char *s)
    2707 {
    2708     static const char *formats[] =
    2709     {
    2710         "%Y-%m-%d",  /* 0 = ISO */
    2711         "%m-%d-%Y",  /* 1 = Postgres, MDY */
    2712         "%d-%m-%Y",  /* 2 = Postgres, DMY */
    2713         "%m/%d/%Y",  /* 3 = SQL, MDY */
    2714         "%d/%m/%Y",  /* 4 = SQL, DMY */
    2715         "%d.%m.%Y"   /* 5 = German */
    2716     };
    2717 
    2718     switch (s ? *s : 'I') {
    2719         case 'P': /* Postgres */
    2720             s = strchr(s + 1, ',');
    2721             if (s) do ++s; while (*s && *s == ' ');
    2722             return formats[s && *s == 'D' ? 2 : 1];
    2723         case 'S': /* SQL */
    2724             s = strchr(s + 1, ',');
    2725             if (s) do ++s; while (*s && *s == ' ');
    2726             return formats[s && *s == 'D' ? 4 : 3];
    2727         case 'G': /* German */
    2728             return formats[5];
    2729         default: /* ISO */
    2730             return formats[0]; /* ISO is the default */
    2731     }
    2732 }
    2733 
    2734 /* internal function converting a date format to a Postgres datestyle */
    2735 static const char *
    2736 date_format_to_style(const char *s)
    2737 {
    2738     static const char *datestyle[] =
    2739     {
    2740         "ISO, YMD",         /* 0 = %Y-%m-%d */
    2741         "Postgres, MDY",    /* 1 = %m-%d-%Y */
    2742         "Postgres, DMY",    /* 2 = %d-%m-%Y */
    2743         "SQL, MDY",         /* 3 = %m/%d/%Y */
    2744         "SQL, DMY",         /* 4 = %d/%m/%Y */
    2745         "German, DMY"       /* 5 = %d.%m.%Y */
    2746     };
    2747 
    2748     switch (s ? s[1] : 'Y') {
    2749         case 'm':
    2750             switch (s[2]) {
    2751                 case '/':
    2752                     return datestyle[3]; /* SQL, MDY */
    2753                 default:
    2754                     return datestyle[1]; /* Postgres, MDY */
    2755             }
    2756         case 'd':
    2757             switch (s[2]) {
    2758                 case '/':
    2759                     return datestyle[4]; /* SQL, DMY */
    2760                 case '.':
    2761                     return datestyle[5]; /* German */
    2762                 default:
    2763                     return datestyle[2]; /* Postgres, DMY */
    2764             }
    2765         default:
    2766             return datestyle[0]; /* ISO */
    2767     }
    2768 }
    2769 
    2770 /* get current date format */
    2771 static char conn_date_format__doc__[] =
    2772 "date_format() -- return the current date format";
    2773 
    2774 static PyObject *
    2775 conn_date_format(connObject *self, PyObject *noargs)
    2776 {
    2777     const char *fmt;
    2778 
    2779     if (!self->cnx) {
    2780         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    2781         return NULL;
    2782     }
    2783 
    2784     /* check if the date format is cached in the connection */
    2785     fmt = self->date_format;
    2786     if (!fmt) {
    2787         fmt = date_style_to_format(PQparameterStatus(self->cnx, "DateStyle"));
    2788         self->date_format = fmt; /* cache the result */
    2789     }
    2790 
    2791     return PyStr_FromString(fmt);
    2792 }
    2793 
    2794 #ifdef ESCAPING_FUNCS
    2795 
    2796 /* escape literal */
    2797 static char conn_escape_literal__doc__[] =
    2798 "escape_literal(str) -- escape a literal constant for use within SQL";
    2799 
    2800 static PyObject *
    2801 conn_escape_literal(connObject *self, PyObject *string)
    2802 {
    2803     PyObject *tmp_obj = NULL,  /* auxiliary string object */
    2804              *to_obj;          /* string object to return */
    2805     char *from,  /* our string argument as encoded string */
    2806          *to;    /* the result as encoded string */
    2807     Py_ssize_t from_length;    /* length of string */
    2808     size_t to_length;          /* length of result */
    2809     int encoding = -1;         /* client encoding */
    2810 
    2811     if (PyBytes_Check(string)) {
    2812         PyBytes_AsStringAndSize(string, &from, &from_length);
    2813     }
    2814     else if (PyUnicode_Check(string)) {
    2815         encoding = PQclientEncoding(self->cnx);
    2816         tmp_obj = get_encoded_string(string, encoding);
    2817         if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
    2818         PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
    2819     }
    2820     else {
    2821         PyErr_SetString(
    2822             PyExc_TypeError,
    2823             "Method escape_literal() expects a string as argument");
    2824         return NULL;
    2825     }
    2826 
    2827     to = PQescapeLiteral(self->cnx, from, (size_t) from_length);
    2828     to_length = strlen(to);
    2829 
    2830     Py_XDECREF(tmp_obj);
    2831 
    2832     if (encoding == -1)
    2833         to_obj = PyBytes_FromStringAndSize(to, to_length);
    2834     else
    2835         to_obj = get_decoded_string(to, to_length, encoding);
    2836     if (to)
    2837         PQfreemem(to);
    2838     return to_obj;
    2839 }
    2840 
    2841 /* escape identifier */
    2842 static char conn_escape_identifier__doc__[] =
    2843 "escape_identifier(str) -- escape an identifier for use within SQL";
    2844 
    2845 static PyObject *
    2846 conn_escape_identifier(connObject *self, PyObject *string)
    2847 {
    2848     PyObject *tmp_obj = NULL,  /* auxiliary string object */
    2849              *to_obj;          /* string object to return */
    2850     char *from,  /* our string argument as encoded string */
    2851          *to;    /* the result as encoded string */
    2852     Py_ssize_t from_length;    /* length of string */
    2853     size_t to_length;          /* length of result */
    2854     int encoding = -1;         /* client encoding */
    2855 
    2856     if (PyBytes_Check(string)) {
    2857         PyBytes_AsStringAndSize(string, &from, &from_length);
    2858     }
    2859     else if (PyUnicode_Check(string)) {
    2860         encoding = PQclientEncoding(self->cnx);
    2861         tmp_obj = get_encoded_string(string, encoding);
    2862         if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
    2863         PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
    2864     }
    2865     else {
    2866         PyErr_SetString(
    2867             PyExc_TypeError,
    2868             "Method escape_identifier() expects a string as argument");
    2869         return NULL;
    2870     }
    2871 
    2872     to = PQescapeIdentifier(self->cnx, from, (size_t) from_length);
    2873     to_length = strlen(to);
    2874 
    2875     Py_XDECREF(tmp_obj);
    2876 
    2877     if (encoding == -1)
    2878         to_obj = PyBytes_FromStringAndSize(to, to_length);
    2879     else
    2880         to_obj = get_decoded_string(to, to_length, encoding);
    2881     if (to)
    2882         PQfreemem(to);
    2883     return to_obj;
    2884 }
    2885 
    2886 #endif /* ESCAPING_FUNCS */
    2887 
    2888 /* escape string */
    2889 static char conn_escape_string__doc__[] =
    2890 "escape_string(str) -- escape a string for use within SQL";
    2891 
    2892 static PyObject *
    2893 conn_escape_string(connObject *self, PyObject *string)
    2894 {
    2895     PyObject *tmp_obj = NULL,  /* auxiliary string object */
    2896              *to_obj;          /* string object to return */
    2897     char *from,  /* our string argument as encoded string */
    2898          *to;    /* the result as encoded string */
    2899     Py_ssize_t from_length;    /* length of string */
    2900     size_t to_length;          /* length of result */
    2901     int encoding = -1;         /* client encoding */
    2902 
    2903     if (PyBytes_Check(string)) {
    2904         PyBytes_AsStringAndSize(string, &from, &from_length);
    2905     }
    2906     else if (PyUnicode_Check(string)) {
    2907         encoding = PQclientEncoding(self->cnx);
    2908         tmp_obj = get_encoded_string(string, encoding);
    2909         if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
    2910         PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
    2911     }
    2912     else {
    2913         PyErr_SetString(
    2914             PyExc_TypeError,
    2915             "Method escape_string() expects a string as argument");
    2916         return NULL;
    2917     }
    2918 
    2919     to_length = 2*from_length + 1;
    2920     if ((Py_ssize_t) to_length < from_length) { /* overflow */
    2921         to_length = from_length;
    2922         from_length = (from_length - 1)/2;
    2923     }
    2924     to = (char *) PyMem_Malloc(to_length);
    2925     to_length = PQescapeStringConn(self->cnx,
    2926         to, from, (size_t) from_length, NULL);
    2927 
    2928     Py_XDECREF(tmp_obj);
    2929 
    2930     if (encoding == -1)
    2931         to_obj = PyBytes_FromStringAndSize(to, to_length);
    2932     else
    2933         to_obj = get_decoded_string(to, to_length, encoding);
    2934     PyMem_Free(to);
    2935     return to_obj;
    2936 }
    2937 
    2938 /* escape bytea */
    2939 static char conn_escape_bytea__doc__[] =
    2940 "escape_bytea(data) -- escape binary data for use within SQL as type bytea";
    2941 
    2942 static PyObject *
    2943 conn_escape_bytea(connObject *self, PyObject *data)
    2944 {
    2945     PyObject *tmp_obj = NULL,  /* auxiliary string object */
    2946              *to_obj;          /* string object to return */
    2947     char *from,  /* our string argument as encoded string */
    2948          *to;    /* the result as encoded string */
    2949     Py_ssize_t from_length;    /* length of string */
    2950     size_t to_length;          /* length of result */
    2951     int encoding = -1;         /* client encoding */
    2952 
    2953     if (PyBytes_Check(data)) {
    2954         PyBytes_AsStringAndSize(data, &from, &from_length);
    2955     }
    2956     else if (PyUnicode_Check(data)) {
    2957         encoding = PQclientEncoding(self->cnx);
    2958         tmp_obj = get_encoded_string(data, encoding);
    2959         if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
    2960         PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
    2961     }
    2962     else {
    2963         PyErr_SetString(
    2964             PyExc_TypeError,
    2965             "Method escape_bytea() expects a string as argument");
    2966         return NULL;
    2967     }
    2968 
    2969     to = (char *) PQescapeByteaConn(self->cnx,
    2970         (unsigned char *) from, (size_t) from_length, &to_length);
    2971 
    2972     Py_XDECREF(tmp_obj);
    2973 
    2974     if (encoding == -1)
    2975         to_obj = PyBytes_FromStringAndSize(to, to_length - 1);
    2976     else
    2977         to_obj = get_decoded_string(to, to_length - 1, encoding);
    2978     if (to)
    2979         PQfreemem(to);
    2980     return to_obj;
    2981 }
    2982 
    2983 #ifdef LARGE_OBJECTS
    2984 /* creates large object */
    2985 static char conn_locreate__doc__[] =
    2986 "locreate(mode) -- create a new large object in the database";
    2987 
    2988 static PyObject *
    2989 conn_locreate(connObject *self, PyObject *args)
    2990 {
    2991     int mode;
    2992     Oid lo_oid;
    2993 
    2994     /* checks validity */
    2995     if (!check_cnx_obj(self)) {
    2996         return NULL;
    2997     }
    2998 
    2999     /* gets arguments */
    3000     if (!PyArg_ParseTuple(args, "i", &mode)) {
    3001         PyErr_SetString(PyExc_TypeError,
    3002                         "Method locreate() takes an integer argument");
    3003         return NULL;
    3004     }
    3005 
    3006     /* creates large object */
    3007     lo_oid = lo_creat(self->cnx, mode);
    3008     if (lo_oid == 0) {
    3009         set_error_msg(OperationalError, "Can't create large object");
    3010         return NULL;
    3011     }
    3012 
    3013     return (PyObject *) large_new(self, lo_oid);
    3014 }
    3015 
    3016 /* init from already known oid */
    3017 static char conn_getlo__doc__[] =
    3018 "getlo(oid) -- create a large object instance for the specified oid";
    3019 
    3020 static PyObject *
    3021 conn_getlo(connObject *self, PyObject *args)
    3022 {
    3023     int oid;
    3024     Oid lo_oid;
    3025 
    3026     /* checks validity */
    3027     if (!check_cnx_obj(self)) {
    3028         return NULL;
    3029     }
    3030 
    3031     /* gets arguments */
    3032     if (!PyArg_ParseTuple(args, "i", &oid)) {
    3033         PyErr_SetString(PyExc_TypeError,
    3034                         "Method getlo() takes an integer argument");
    3035         return NULL;
    3036     }
    3037 
    3038     lo_oid = (Oid) oid;
    3039     if (lo_oid == 0) {
    3040         PyErr_SetString(PyExc_ValueError, "The object oid can't be null");
    3041         return NULL;
    3042     }
    3043 
    3044     /* creates object */
    3045     return (PyObject *) large_new(self, lo_oid);
    3046 }
    3047 
    3048 /* import unix file */
    3049 static char conn_loimport__doc__[] =
    3050 "loimport(name) -- create a new large object from specified file";
    3051 
    3052 static PyObject *
    3053 conn_loimport(connObject *self, PyObject *args)
    3054 {
    3055     char *name;
    3056     Oid lo_oid;
    3057 
    3058     /* checks validity */
    3059     if (!check_cnx_obj(self)) {
    3060         return NULL;
    3061     }
    3062 
    3063     /* gets arguments */
    3064     if (!PyArg_ParseTuple(args, "s", &name)) {
    3065         PyErr_SetString(PyExc_TypeError,
    3066                         "Method loimport() takes a string argument");
    3067         return NULL;
    3068     }
    3069 
    3070     /* imports file and checks result */
    3071     lo_oid = lo_import(self->cnx, name);
    3072     if (lo_oid == 0) {
    3073         set_error_msg(OperationalError, "Can't create large object");
    3074         return NULL;
    3075     }
    3076 
    3077     return (PyObject *) large_new(self, lo_oid);
    3078 }
    3079 #endif /* LARGE_OBJECTS */
    3080 
    3081 /* resets connection */
    3082 static char conn_reset__doc__[] =
    3083 "reset() -- reset connection with current parameters\n\n"
    3084 "All derived queries and large objects derived from this connection\n"
    3085 "will not be usable after this call.\n";
    3086 
    3087 static PyObject *
    3088 conn_reset(connObject *self, PyObject *noargs)
    3089 {
    3090     if (!self->cnx) {
    3091         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    3092         return NULL;
    3093     }
    3094 
    3095     /* resets the connection */
    3096     PQreset(self->cnx);
    3097     Py_INCREF(Py_None);
    3098     return Py_None;
    3099 }
    3100 
    3101 /* cancels current command */
    3102 static char conn_cancel__doc__[] =
    3103 "cancel() -- abandon processing of the current command";
    3104 
    3105 static PyObject *
    3106 conn_cancel(connObject *self, PyObject *noargs)
    3107 {
    3108     if (!self->cnx) {
    3109         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    3110         return NULL;
    3111     }
    3112 
    3113     /* request that the server abandon processing of the current command */
    3114     return PyInt_FromLong((long) PQrequestCancel(self->cnx));
    3115 }
    3116 
    3117 /* get connection socket */
    3118 static char conn_fileno__doc__[] =
    3119 "fileno() -- return database connection socket file handle";
    3120 
    3121 static PyObject *
    3122 conn_fileno(connObject *self, PyObject *noargs)
    3123 {
    3124     if (!self->cnx) {
    3125         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    3126         return NULL;
    3127     }
    3128 
    3129 #ifdef NO_PQSOCKET
    3130     return PyInt_FromLong((long) self->cnx->sock);
    3131 #else
    3132     return PyInt_FromLong((long) PQsocket(self->cnx));
    3133 #endif
    3134 }
    3135 
    3136 /* set external typecast callback function */
    3137 static char conn_set_cast_hook__doc__[] =
    3138 "set_cast_hook(func) -- set a fallback typecast function";
    3139 
    3140 static PyObject *
    3141 conn_set_cast_hook(connObject *self, PyObject *func)
    3142 {
    3143     PyObject *ret = NULL;
    3144 
    3145     if (func == Py_None) {
    3146         Py_XDECREF(self->cast_hook);
    3147         self->cast_hook = NULL;
    3148         Py_INCREF(Py_None); ret = Py_None;
    3149     }
    3150     else if (PyCallable_Check(func)) {
    3151         Py_XINCREF(func); Py_XDECREF(self->cast_hook);
    3152         self->cast_hook = func;
    3153         Py_INCREF(Py_None); ret = Py_None;
    3154     }
    3155     else {
    3156         PyErr_SetString(PyExc_TypeError,
    3157                         "Method set_cast_hook() expects"
    3158                         " a callable or None as argument");
    3159     }
    3160 
    3161     return ret;
    3162 }
    3163 
    3164 /* get notice receiver callback function */
    3165 static char conn_get_cast_hook__doc__[] =
    3166 "get_cast_hook() -- get the fallback typecast function";
    3167 
    3168 static PyObject *
    3169 conn_get_cast_hook(connObject *self, PyObject *noargs)
    3170 {
    3171     PyObject *ret = self->cast_hook;;
    3172 
    3173     if (!ret)
    3174         ret = Py_None;
    3175     Py_INCREF(ret);
    3176 
    3177     return ret;
    3178 }
    3179 
    3180 /* set notice receiver callback function */
    3181 static char conn_set_notice_receiver__doc__[] =
    3182 "set_notice_receiver(func) -- set the current notice receiver";
    3183 
    3184 static PyObject *
    3185 conn_set_notice_receiver(connObject *self, PyObject *func)
    3186 {
    3187     PyObject *ret = NULL;
    3188 
    3189     if (func == Py_None) {
    3190         Py_XDECREF(self->notice_receiver);
    3191         self->notice_receiver = NULL;
    3192         Py_INCREF(Py_None); ret = Py_None;
    3193     }
    3194     else if (PyCallable_Check(func)) {
    3195         Py_XINCREF(func); Py_XDECREF(self->notice_receiver);
    3196         self->notice_receiver = func;
    3197         PQsetNoticeReceiver(self->cnx, notice_receiver, self);
    3198         Py_INCREF(Py_None); ret = Py_None;
    3199     }
    3200     else {
    3201         PyErr_SetString(PyExc_TypeError,
    3202                         "Method set_notice_receiver() expects"
    3203                         " a callable or None as argument");
    3204     }
    3205 
    3206     return ret;
    3207 }
    3208 
    3209 /* get notice receiver callback function */
    3210 static char conn_get_notice_receiver__doc__[] =
    3211 "get_notice_receiver() -- get the current notice receiver";
    3212 
    3213 static PyObject *
    3214 conn_get_notice_receiver(connObject *self, PyObject *noargs)
    3215 {
    3216     PyObject *ret = self->notice_receiver;
    3217 
    3218     if (!ret)
    3219         ret = Py_None;
    3220     Py_INCREF(ret);
    3221 
    3222     return ret;
    3223 }
    3224 
    3225 /* close without deleting */
    3226 static char conn_close__doc__[] =
    3227 "close() -- close connection\n\n"
    3228 "All instances of the connection object and derived objects\n"
    3229 "(queries and large objects) can no longer be used after this call.\n";
    3230 
    3231 static PyObject *
    3232 conn_close(connObject *self, PyObject *noargs)
    3233 {
    3234     /* connection object cannot already be closed */
    3235     if (!self->cnx) {
    3236         set_error_msg(InternalError, "Connection already closed");
    3237         return NULL;
    3238     }
    3239 
    3240     Py_BEGIN_ALLOW_THREADS
    3241     PQfinish(self->cnx);
    3242     Py_END_ALLOW_THREADS
    3243 
    3244     self->cnx = NULL;
    3245     Py_INCREF(Py_None);
    3246     return Py_None;
    3247 }
    3248 
    3249 /* gets asynchronous notify */
    3250 static char conn_get_notify__doc__[] =
    3251 "getnotify() -- get database notify for this connection";
    3252 
    3253 static PyObject *
    3254 conn_get_notify(connObject *self, PyObject *noargs)
    3255 {
    3256     PGnotify *notify;
    3257 
    3258     if (!self->cnx) {
    3259         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    3260         return NULL;
    3261     }
    3262 
    3263     /* checks for NOTIFY messages */
    3264     PQconsumeInput(self->cnx);
    3265 
    3266     if (!(notify = PQnotifies(self->cnx))) {
    3267         Py_INCREF(Py_None);
    3268         return Py_None;
    3269     }
    3270     else {
    3271         PyObject *notify_result, *tmp;
    3272 
    3273         if (!(tmp = PyStr_FromString(notify->relname))) {
    3274             return NULL;
    3275         }
    3276 
    3277         if (!(notify_result = PyTuple_New(3))) {
    3278             return NULL;
    3279         }
    3280 
    3281         PyTuple_SET_ITEM(notify_result, 0, tmp);
    3282 
    3283         if (!(tmp = PyInt_FromLong(notify->be_pid))) {
    3284             Py_DECREF(notify_result);
    3285             return NULL;
    3286         }
    3287 
    3288         PyTuple_SET_ITEM(notify_result, 1, tmp);
    3289 
    3290         /* extra exists even in old versions that did not support it */
    3291         if (!(tmp = PyStr_FromString(notify->extra))) {
    3292             Py_DECREF(notify_result);
    3293             return NULL;
    3294         }
    3295 
    3296         PyTuple_SET_ITEM(notify_result, 2, tmp);
    3297 
    3298         PQfreemem(notify);
    3299 
    3300         return notify_result;
    3301     }
    3302 }
    3303 
    3304 /* get the list of connection attributes */
    3305 static PyObject *
    3306 conn_dir(connObject *self, PyObject *noargs)
    3307 {
    3308     PyObject *attrs;
    3309 
    3310     attrs = PyObject_Dir(PyObject_Type((PyObject *) self));
    3311     PyObject_CallMethod(
    3312         attrs, "extend", "[sssssssss]",
    3313         "host", "port", "db", "options", "error", "status", "user",
    3314         "protocol_version", "server_version");
    3315 
    3316     return attrs;
    3317 }
    3318 
    3319 /* connection object methods */
    3320 static struct PyMethodDef conn_methods[] = {
    3321     {"__dir__", (PyCFunction) conn_dir,  METH_NOARGS, NULL},
    3322 
    3323     {"source", (PyCFunction) conn_source,
    3324         METH_NOARGS, conn_source__doc__},
    3325     {"query", (PyCFunction) conn_query,
    3326         METH_VARARGS, conn_query__doc__},
    3327     {"query_prepared", (PyCFunction) conn_query_prepared,
    3328         METH_VARARGS, conn_query_prepared__doc__},
    3329     {"prepare", (PyCFunction) conn_prepare,
    3330         METH_VARARGS, conn_prepare__doc__},
    3331     {"describe_prepared", (PyCFunction) conn_describe_prepared,
    3332         METH_VARARGS, conn_describe_prepared__doc__},
    3333     {"reset", (PyCFunction) conn_reset,
    3334         METH_NOARGS, conn_reset__doc__},
    3335     {"cancel", (PyCFunction) conn_cancel,
    3336         METH_NOARGS, conn_cancel__doc__},
    3337     {"close", (PyCFunction) conn_close,
    3338         METH_NOARGS, conn_close__doc__},
    3339     {"fileno", (PyCFunction) conn_fileno,
    3340         METH_NOARGS, conn_fileno__doc__},
    3341     {"get_cast_hook", (PyCFunction) conn_get_cast_hook,
    3342         METH_NOARGS, conn_get_cast_hook__doc__},
    3343     {"set_cast_hook", (PyCFunction) conn_set_cast_hook,
    3344         METH_O, conn_set_cast_hook__doc__},
    3345     {"get_notice_receiver", (PyCFunction) conn_get_notice_receiver,
    3346         METH_NOARGS, conn_get_notice_receiver__doc__},
    3347     {"set_notice_receiver", (PyCFunction) conn_set_notice_receiver,
    3348         METH_O, conn_set_notice_receiver__doc__},
    3349     {"getnotify", (PyCFunction) conn_get_notify,
    3350         METH_NOARGS, conn_get_notify__doc__},
    3351     {"inserttable", (PyCFunction) conn_inserttable,
    3352         METH_VARARGS, conn_inserttable__doc__},
    3353     {"transaction", (PyCFunction) conn_transaction,
    3354         METH_NOARGS, conn_transaction__doc__},
    3355     {"parameter", (PyCFunction) conn_parameter,
    3356         METH_VARARGS, conn_parameter__doc__},
    3357     {"date_format", (PyCFunction) conn_date_format,
    3358         METH_NOARGS, conn_date_format__doc__},
    3359 
    3360 #ifdef ESCAPING_FUNCS
    3361     {"escape_literal", (PyCFunction) conn_escape_literal,
    3362         METH_O, conn_escape_literal__doc__},
    3363     {"escape_identifier", (PyCFunction) conn_escape_identifier,
    3364         METH_O, conn_escape_identifier__doc__},
    3365 #endif /* ESCAPING_FUNCS */
    3366     {"escape_string", (PyCFunction) conn_escape_string,
    3367         METH_O, conn_escape_string__doc__},
    3368     {"escape_bytea", (PyCFunction) conn_escape_bytea,
    3369         METH_O, conn_escape_bytea__doc__},
    3370 
    3371 #ifdef DIRECT_ACCESS
    3372     {"putline", (PyCFunction) conn_putline,
    3373         METH_VARARGS, conn_putline__doc__},
    3374     {"getline", (PyCFunction) conn_getline,
    3375         METH_NOARGS, conn_getline__doc__},
    3376     {"endcopy", (PyCFunction) conn_endcopy,
    3377         METH_NOARGS, conn_endcopy__doc__},
    3378 #endif /* DIRECT_ACCESS */
    3379 
    3380 #ifdef LARGE_OBJECTS
    3381     {"locreate", (PyCFunction) conn_locreate,
    3382         METH_VARARGS, conn_locreate__doc__},
    3383     {"getlo", (PyCFunction) conn_getlo,
    3384         METH_VARARGS, conn_getlo__doc__},
    3385     {"loimport", (PyCFunction) conn_loimport,
    3386         METH_VARARGS, conn_loimport__doc__},
    3387 #endif /* LARGE_OBJECTS */
    3388 
    3389     {NULL, NULL} /* sentinel */
    3390 };
    3391 
    3392 /* gets connection attributes */
    3393 static PyObject *
    3394 conn_getattr(connObject *self, PyObject *nameobj)
    3395 {
    3396     const char *name = PyStr_AsString(nameobj);
    3397 
    3398     /*
    3399      * Although we could check individually, there are only a few
    3400      * attributes that don't require a live connection and unless someone
    3401      * has an urgent need, this will have to do.
    3402      */
    3403 
    3404     /* first exception - close which returns a different error */
    3405     if (strcmp(name, "close") && !self->cnx) {
    3406         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
    3407         return NULL;
    3408     }
    3409 
    3410     /* list PostgreSQL connection fields */
    3411 
    3412     /* postmaster host */
    3413     if (!strcmp(name, "host")) {
    3414         char *r = PQhost(self->cnx);
    3415         if (!r || r[0] == '/') /* Pg >= 9.6 can return a Unix socket path */
    3416             r = "localhost";
    3417         return PyStr_FromString(r);
    3418     }
    3419 
    3420     /* postmaster port */
    3421     if (!strcmp(name, "port"))
    3422         return PyInt_FromLong(atol(PQport(self->cnx)));
    3423 
    3424     /* selected database */
    3425     if (!strcmp(name, "db"))
    3426         return PyStr_FromString(PQdb(self->cnx));
    3427 
    3428     /* selected options */
    3429     if (!strcmp(name, "options"))
    3430         return PyStr_FromString(PQoptions(self->cnx));
    3431 
    3432     /* error (status) message */
    3433     if (!strcmp(name, "error"))
    3434         return PyStr_FromString(PQerrorMessage(self->cnx));
    3435 
    3436     /* connection status : 1 - OK, 0 - BAD */
    3437     if (!strcmp(name, "status"))
    3438         return PyInt_FromLong(PQstatus(self->cnx) == CONNECTION_OK ? 1 : 0);
    3439 
    3440     /* provided user name */
    3441     if (!strcmp(name, "user"))
    3442         return PyStr_FromString(PQuser(self->cnx));
    3443 
    3444     /* protocol version */
    3445     if (!strcmp(name, "protocol_version"))
    3446         return PyInt_FromLong(PQprotocolVersion(self->cnx));
    3447 
    3448     /* backend version */
    3449     if (!strcmp(name, "server_version"))
    3450         return PyInt_FromLong(PQserverVersion(self->cnx));
    3451 
    3452     return PyObject_GenericGetAttr((PyObject *) self, nameobj);
    3453 }
    3454 
    3455 /* connection type definition */
    3456 static PyTypeObject connType = {
    3457     PyVarObject_HEAD_INIT(NULL, 0)
    3458     "pg.Connection",              /* tp_name */
    3459     sizeof(connObject),           /* tp_basicsize */
    3460     0,                            /* tp_itemsize */
    3461     (destructor) conn_delete,     /* tp_dealloc */
    3462     0,                            /* tp_print */
    3463     0,                            /* tp_getattr */
    3464     0,                            /* tp_setattr */
    3465     0,                            /* tp_reserved */
    3466     0,                            /* tp_repr */
    3467     0,                            /* tp_as_number */
    3468     0,                            /* tp_as_sequence */
    3469     0,                            /* tp_as_mapping */
    3470     0,                            /* tp_hash */
    3471     0,                            /* tp_call */
    3472     0,                            /* tp_str */
    3473     (getattrofunc) conn_getattr,  /* tp_getattro */
    3474     0,                            /* tp_setattro */
    3475     0,                            /* tp_as_buffer */
    3476     Py_TPFLAGS_DEFAULT,           /* tp_flags */
    3477     0,                            /* tp_doc */
    3478     0,                            /* tp_traverse */
    3479     0,                            /* tp_clear */
    3480     0,                            /* tp_richcompare */
    3481     0,                            /* tp_weaklistoffset */
    3482     0,                            /* tp_iter */
    3483     0,                            /* tp_iternext */
    3484     conn_methods,                 /* tp_methods */
    3485 };
    3486 
    3487 /* --------------------------------------------------------------------- */
    3488 /* source object                                                         */
    3489 /* --------------------------------------------------------------------- */
    3490 /* checks source object validity */
    3491 static int
    3492 check_source_obj(sourceObject *self, int level)
    3493 {
    3494     if (!self->valid) {
    3495         set_error_msg(OperationalError, "Object has been closed");
    3496         return 0;
    3497     }
    3498 
    3499     if ((level & CHECK_RESULT) && !self->result) {
    3500         set_error_msg(DatabaseError, "No result");
    3501         return 0;
    3502     }
    3503 
    3504     if ((level & CHECK_DQL) && self->result_type != RESULT_DQL) {
    3505         set_error_msg(DatabaseError, "Last query did not return tuples");
    3506         return 0;
    3507     }
    3508 
    3509     if ((level & CHECK_CNX) && !check_cnx_obj(self->pgcnx)) {
    3510         return 0;
    3511     }
    3512 
    3513     return 1;
    3514 }
    3515 
    3516 /* destructor */
    3517 static void
    3518 source_dealloc(sourceObject *self)
    3519 {
    3520     if (self->result)
    3521         PQclear(self->result);
    3522 
    3523     Py_XDECREF(self->pgcnx);
    3524     PyObject_Del(self);
    3525 }
    3526 
    3527 /* closes object */
    3528 static char source_close__doc__[] =
    3529 "close() -- close query object without deleting it\n\n"
    3530 "All instances of the query object can no longer be used after this call.\n";
    3531 
    3532 static PyObject *
    3533 source_close(sourceObject *self, PyObject *noargs)
    3534 {
    3535     /* frees result if necessary and invalidates object */
    3536     if (self->result) {
    3537         PQclear(self->result);
    3538         self->result_type = RESULT_EMPTY;
    3539         self->result = NULL;
    3540     }
    3541 
    3542     self->valid = 0;
    3543 
    3544     /* return None */
    3545     Py_INCREF(Py_None);
    3546     return Py_None;
    3547 }
    3548 
    3549 /* database query */
    3550 static char source_execute__doc__[] =
    3551 "execute(sql) -- execute a SQL statement (string)\n\n"
    3552 "On success, this call returns the number of affected rows, or None\n"
    3553 "for DQL (SELECT, ...) statements.  The fetch (fetch(), fetchone()\n"
    3554 "and fetchall()) methods can be used to get result rows.\n";
    3555 
    3556 static PyObject *
    3557 source_execute(sourceObject *self, PyObject *sql)
    3558 {
    3559     PyObject *tmp_obj = NULL;  /* auxiliary string object */
    3560     char *query;
    3561     int encoding;
    3562 
    3563     /* checks validity */
    3564     if (!check_source_obj(self, CHECK_CNX)) {
    3565         return NULL;
    3566     }
    3567 
    3568     encoding = PQclientEncoding(self->pgcnx->cnx);
    3569 
    3570     if (PyBytes_Check(sql)) {
    3571         query = PyBytes_AsString(sql);
    3572     }
    3573     else if (PyUnicode_Check(sql)) {
    3574         tmp_obj = get_encoded_string(sql, encoding);
    3575         if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
    3576         query = PyBytes_AsString(tmp_obj);
    3577     }
    3578     else {
    3579         PyErr_SetString(PyExc_TypeError,
    3580                         "Method execute() expects a string as argument");
    3581         return NULL;
    3582     }
    3583 
    3584     /* frees previous result */
    3585     if (self->result) {
    3586         PQclear(self->result);
    3587         self->result = NULL;
    3588     }
    3589     self->max_row = 0;
    3590     self->current_row = 0;
    3591     self->num_fields = 0;
    3592     self->encoding = encoding;
    3593 
    3594     /* gets result */
    3595     Py_BEGIN_ALLOW_THREADS
    3596     self->result = PQexec(self->pgcnx->cnx, query);
    3597     Py_END_ALLOW_THREADS
    3598 
    3599     /* we don't need the auxiliary string any more */
    3600     Py_XDECREF(tmp_obj);
    3601 
    3602     /* checks result validity */
    3603     if (!self->result) {
    3604         PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->pgcnx->cnx));
    3605         return NULL;
    3606     }
    3607 
    3608     /* this may have changed the datestyle, so we reset the date format
    3609        in order to force fetching it newly when next time requested */
    3610     self->pgcnx->date_format = date_format; /* this is normally NULL */
    3611 
    3612     /* checks result status */
    3613     switch (PQresultStatus(self->result)) {
    3614         /* query succeeded */
    3615         case PGRES_TUPLES_OK:   /* DQL: returns None (DB-SIG compliant) */
    3616             self->result_type = RESULT_DQL;
    3617             self->max_row = PQntuples(self->result);
    3618             self->num_fields = PQnfields(self->result);
    3619             Py_INCREF(Py_None);
    3620             return Py_None;
    3621         case PGRES_COMMAND_OK:  /* other requests */
    3622         case PGRES_COPY_OUT:
    3623         case PGRES_COPY_IN:
    3624             {
    3625                 long num_rows;
    3626                 char *tmp;
    3627 
    3628                 tmp = PQcmdTuples(self->result);
    3629                 if (tmp[0]) {
    3630                     self->result_type = RESULT_DML;
    3631                     num_rows = atol(tmp);
    3632                 }
    3633                 else {
    3634                     self->result_type = RESULT_DDL;
    3635                     num_rows = -1;
    3636                 }
    3637                 return PyInt_FromLong(num_rows);
    3638             }
    3639 
    3640         /* query failed */
    3641         case PGRES_EMPTY_QUERY:
    3642             PyErr_SetString(PyExc_ValueError, "Empty query");
    3643             break;
    3644         case PGRES_BAD_RESPONSE:
    3645         case PGRES_FATAL_ERROR:
    3646         case PGRES_NONFATAL_ERROR:
    3647             set_error(ProgrammingError, "Cannot execute command",
    3648                 self->pgcnx->cnx, self->result);
    3649             break;
    3650         default:
    3651             set_error_msg(InternalError,
    3652                           "Internal error: unknown result status");
    3653     }
    3654 
    3655     /* frees result and returns error */
    3656     PQclear(self->result);
    3657     self->result = NULL;
    3658     self->result_type = RESULT_EMPTY;
    3659     return NULL;
    3660 }
    3661 
    3662 /* gets oid status for last query (valid for INSERTs, 0 for other) */
    3663 static char source_oidstatus__doc__[] =
    3664 "oidstatus() -- return oid of last inserted row (if available)";
    3665 
    3666 static PyObject *
    3667 source_oidstatus(sourceObject *self, PyObject *noargs)
    3668 {
    3669     Oid oid;
    3670 
    3671     /* checks validity */
    3672     if (!check_source_obj(self, CHECK_RESULT)) {
    3673         return NULL;
    3674     }
    3675 
    3676     /* retrieves oid status */
    3677     if ((oid = PQoidValue(self->result)) == InvalidOid) {
    3678         Py_INCREF(Py_None);
    3679         return Py_None;
    3680     }
    3681 
    3682     return PyInt_FromLong(oid);
    3683 }
    3684 
    3685 /* fetches rows from last result */
    3686 static char source_fetch__doc__[] =
    3687 "fetch(num) -- return the next num rows from the last result in a list\n\n"
    3688 "If num parameter is omitted arraysize attribute value is used.\n"
    3689 "If size equals -1, all rows are fetched.\n";
    3690 
    3691 static PyObject *
    3692 source_fetch(sourceObject *self, PyObject *args)
    3693 {
    3694     PyObject *res_list;
    3695     int i, k;
    3696     long size;
    3697 #if IS_PY3
    3698     int encoding;
    3699 #endif
    3700 
    3701     /* checks validity */
    3702     if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL | CHECK_CNX)) {
    3703         return NULL;
    3704     }
    3705 
    3706     /* checks args */
    3707     size = self->arraysize;
    3708     if (!PyArg_ParseTuple(args, "|l", &size)) {
    3709         PyErr_SetString(PyExc_TypeError,
    3710                         "fetch(num), with num (integer, optional)");
    3711         return NULL;
    3712     }
    3713 
    3714     /* seeks last line */
    3715     /* limit size to be within the amount of data we actually have */
    3716     if (size == -1 || (self->max_row - self->current_row) < size) {
    3717         size = self->max_row - self->current_row;
    3718     }
    3719 
    3720     /* allocate list for result */
    3721     if (!(res_list = PyList_New(0))) return NULL;
    3722 
    3723 #if IS_PY3
    3724     encoding = self->encoding;
    3725 #endif
    3726 
    3727     /* builds result */
    3728     for (i = 0, k = self->current_row; i < size; ++i, ++k) {
    3729         PyObject *rowtuple;
    3730         int j;
    3731 
    3732         if (!(rowtuple = PyTuple_New(self->num_fields))) {
    3733             Py_DECREF(res_list); return NULL;
    3734         }
    3735 
    3736         for (j = 0; j < self->num_fields; ++j) {
    3737             PyObject *str;
    3738 
    3739             if (PQgetisnull(self->result, k, j)) {
    3740                 Py_INCREF(Py_None);
    3741                 str = Py_None;
    3742             }
    3743             else {
    3744                 char *s = PQgetvalue(self->result, k, j);
    3745                 Py_ssize_t size = PQgetlength(self->result, k, j);
    3746 #if IS_PY3
    3747                 if (PQfformat(self->result, j) == 0) { /* textual format */
    3748                     str = get_decoded_string(s, size, encoding);
    3749                     if (!str) /* cannot decode */
    3750                         str = PyBytes_FromStringAndSize(s, size);
    3751                 }
    3752                 else
    3753 #endif
    3754                 str = PyBytes_FromStringAndSize(s, size);
    3755             }
    3756             PyTuple_SET_ITEM(rowtuple, j, str);
    3757         }
    3758 
    3759         if (PyList_Append(res_list, rowtuple)) {
    3760             Py_DECREF(rowtuple); Py_DECREF(res_list); return NULL;
    3761         }
    3762         Py_DECREF(rowtuple);
    3763     }
    3764 
    3765     self->current_row = k;
    3766     return res_list;
    3767 }
    3768 
    3769 /* changes current row (internal wrapper for all "move" methods) */
    3770 static PyObject *
    3771 _source_move(sourceObject *self, int move)
    3772 {
    3773     /* checks validity */
    3774     if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL)) {
    3775         return NULL;
    3776     }
    3777 
    3778     /* changes the current row */
    3779     switch (move) {
    3780         case QUERY_MOVEFIRST:
    3781             self->current_row = 0;
    3782             break;
    3783         case QUERY_MOVELAST:
    3784             self->current_row = self->max_row - 1;
    3785             break;
    3786         case QUERY_MOVENEXT:
    3787             if (self->current_row != self->max_row)
    3788                 ++self->current_row;
    3789             break;
    3790         case QUERY_MOVEPREV:
    3791             if (self->current_row > 0)
    3792                 self->current_row--;
    3793             break;
    3794     }
    3795 
    3796     Py_INCREF(Py_None);
    3797     return Py_None;
    3798 }
    3799 
    3800 /* move to first result row */
    3801 static char source_movefirst__doc__[] =
    3802 "movefirst() -- move to first result row";
    3803 
    3804 static PyObject *
    3805 source_movefirst(sourceObject *self, PyObject *noargs)
    3806 {
    3807     return _source_move(self, QUERY_MOVEFIRST);
    3808 }
    3809 
    3810 /* move to last result row */
    3811 static char source_movelast__doc__[] =
    3812 "movelast() -- move to last valid result row";
    3813 
    3814 static PyObject *
    3815 source_movelast(sourceObject *self, PyObject *noargs)
    3816 {
    3817     return _source_move(self, QUERY_MOVELAST);
    3818 }
    3819 
    3820 /* move to next result row */
    3821 static char source_movenext__doc__[] =
    3822 "movenext() -- move to next result row";
    3823 
    3824 static PyObject *
    3825 source_movenext(sourceObject *self, PyObject *noargs)
    3826 {
    3827     return _source_move(self, QUERY_MOVENEXT);
    3828 }
    3829 
    3830 /* move to previous result row */
    3831 static char source_moveprev__doc__[] =
    3832 "moveprev() -- move to previous result row";
    3833 
    3834 static PyObject *
    3835 source_moveprev(sourceObject *self, PyObject *noargs)
    3836 {
    3837     return _source_move(self, QUERY_MOVEPREV);
    3838 }
    3839 
    3840 /* put copy data */
    3841 static char source_putdata__doc__[] =
    3842 "putdata(buffer) -- send data to server during copy from stdin";
    3843 
    3844 static PyObject *
    3845 source_putdata(sourceObject *self, PyObject *buffer)
    3846 {
    3847     PyObject *tmp_obj = NULL;  /* an auxiliary object */
    3848     char *buf;                 /* the buffer as encoded string */
    3849     Py_ssize_t nbytes;         /* length of string */
    3850     char *errormsg = NULL;     /* error message */
    3851     int res;                   /* direct result of the operation */
    3852     PyObject *ret;             /* return value */
    3853 
    3854     /* checks validity */
    3855     if (!check_source_obj(self, CHECK_CNX)) {
    3856         return NULL;
    3857     }
    3858 
    3859     /* make sure that the connection object is valid */
    3860     if (!self->pgcnx->cnx) {
    3861         return NULL;
    3862     }
    3863 
    3864     if (buffer == Py_None) {
    3865         /* pass None for terminating the operation */
    3866         buf = errormsg = NULL;
    3867     }
    3868     else if (PyBytes_Check(buffer)) {
    3869         /* or pass a byte string */
    3870         PyBytes_AsStringAndSize(buffer, &buf, &nbytes);
    3871     }
    3872     else if (PyUnicode_Check(buffer)) {
    3873         /* or pass a unicode string */
    3874         tmp_obj = get_encoded_string(
    3875             buffer, PQclientEncoding(self->pgcnx->cnx));
    3876         if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
    3877         PyBytes_AsStringAndSize(tmp_obj, &buf, &nbytes);
    3878     }
    3879     else if (PyErr_GivenExceptionMatches(buffer, PyExc_BaseException)) {
    3880         /* or pass a Python exception for sending an error message */
    3881         tmp_obj = PyObject_Str(buffer);
    3882         if (PyUnicode_Check(tmp_obj)) {
    3883             PyObject *obj = tmp_obj;
    3884 
    3885             tmp_obj = get_encoded_string(
    3886                 obj, PQclientEncoding(self->pgcnx->cnx));
    3887             Py_DECREF(obj);
    3888             if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
    3889         }
    3890         errormsg = PyBytes_AsString(tmp_obj);
    3891         buf = NULL;
    3892     }
    3893     else {
    3894         PyErr_SetString(PyExc_TypeError,
    3895                         "Method putdata() expects a buffer, None"
    3896                         " or an exception as argument");
    3897         return NULL;
    3898     }
    3899 
    3900     /* checks validity */
    3901     if (!check_source_obj(self, CHECK_CNX | CHECK_RESULT) ||
    3902         PQresultStatus(self->result) != PGRES_COPY_IN)
    3903     {
    3904         PyErr_SetString(PyExc_IOError,
    3905                         "Connection is invalid or not in copy_in state");
    3906         Py_XDECREF(tmp_obj);
    3907         return NULL;
    3908     }
    3909 
    3910     if (buf) {
    3911         res = nbytes ? PQputCopyData(self->pgcnx->cnx, buf, (int) nbytes) : 1;
    3912     }
    3913     else {
    3914         res = PQputCopyEnd(self->pgcnx->cnx, errormsg);
    3915     }
    3916 
    3917     Py_XDECREF(tmp_obj);
    3918 
    3919     if (res != 1) {
    3920         PyErr_SetString(PyExc_IOError, PQerrorMessage(self->pgcnx->cnx));
    3921         return NULL;
    3922     }
    3923 
    3924     if (buf) { /* buffer has been sent */
    3925         ret = Py_None;
    3926         Py_INCREF(ret);
    3927     }
    3928     else { /* copy is done */
    3929         PGresult *result; /* final result of the operation */
    3930 
    3931         Py_BEGIN_ALLOW_THREADS;
    3932         result = PQgetResult(self->pgcnx->cnx);
    3933         Py_END_ALLOW_THREADS;
    3934 
    3935         if (PQresultStatus(result) == PGRES_COMMAND_OK) {
    3936             char *tmp;
    3937             long num_rows;
    3938 
    3939             tmp = PQcmdTuples(result);
    3940             num_rows = tmp[0] ? atol(tmp) : -1;
    3941             ret = PyInt_FromLong(num_rows);
    3942         }
    3943         else {
    3944             if (!errormsg) errormsg = PQerrorMessage(self->pgcnx->cnx);
    3945             PyErr_SetString(PyExc_IOError, errormsg);
    3946             ret = NULL;
    3947         }
    3948 
    3949         PQclear(self->result);
    3950         self->result = NULL;
    3951         self->result_type = RESULT_EMPTY;
    3952     }
    3953 
    3954     return ret; /* None or number of rows */
    3955 }
    3956 
    3957 /* get copy data */
    3958 static char source_getdata__doc__[] =
    3959 "getdata(decode) -- receive data to server during copy to stdout";
    3960 
    3961 static PyObject *
    3962 source_getdata(sourceObject *self, PyObject *args)
    3963 {
    3964     int *decode = 0;    /* decode flag */
    3965     char *buffer;       /* the copied buffer as encoded byte string */
    3966     Py_ssize_t nbytes;  /* length of the byte string */
    3967     PyObject *ret;      /* return value */
    3968 
    3969     /* checks validity */
    3970     if (!check_source_obj(self, CHECK_CNX)) {
    3971         return NULL;
    3972     }
    3973 
    3974     /* make sure that the connection object is valid */
    3975     if (!self->pgcnx->cnx) {
    3976         return NULL;
    3977     }
    3978 
    3979     if (!PyArg_ParseTuple(args, "|i", &decode)) {
    3980         return NULL;
    3981     }
    3982 
    3983     /* checks validity */
    3984     if (!check_source_obj(self, CHECK_CNX | CHECK_RESULT) ||
    3985         PQresultStatus(self->result) != PGRES_COPY_OUT)
    3986     {
    3987         PyErr_SetString(PyExc_IOError,
    3988                         "Connection is invalid or not in copy_out state");
    3989         return NULL;
    3990     }
    3991 
    3992     nbytes = PQgetCopyData(self->pgcnx->cnx, &buffer, 0);
    3993 
    3994     if (!nbytes || nbytes < -1) { /* an error occurred */
    3995         PyErr_SetString(PyExc_IOError, PQerrorMessage(self->pgcnx->cnx));
    3996         return NULL;
    3997     }
    3998 
    3999     if (nbytes == -1) { /* copy is done */
    4000         PGresult *result; /* final result of the operation */
    4001 
    4002         Py_BEGIN_ALLOW_THREADS;
    4003         result = PQgetResult(self->pgcnx->cnx);
    4004         Py_END_ALLOW_THREADS;
    4005 
    4006         if (PQresultStatus(result) == PGRES_COMMAND_OK) {
    4007             char *tmp;
    4008             long num_rows;
    4009 
    4010             tmp = PQcmdTuples(result);
    4011             num_rows = tmp[0] ? atol(tmp) : -1;
    4012             ret = PyInt_FromLong(num_rows);
    4013         }
    4014         else {
    4015             PyErr_SetString(PyExc_IOError, PQerrorMessage(self->pgcnx->cnx));
    4016             ret = NULL;
    4017         }
    4018 
    4019         PQclear(self->result);
    4020         self->result = NULL;
    4021         self->result_type = RESULT_EMPTY;
    4022     }
    4023     else { /* a row has been returned */
    4024         ret = decode ? get_decoded_string(
    4025                 buffer, nbytes, PQclientEncoding(self->pgcnx->cnx)) :
    4026             PyBytes_FromStringAndSize(buffer, nbytes);
    4027         PQfreemem(buffer);
    4028     }
    4029 
    4030     return ret; /* buffer or number of rows */
    4031 }
    4032 
    4033 /* finds field number from string/integer (internal use only) */
    4034 static int
    4035 _source_fieldindex(sourceObject *self, PyObject *param, const char *usage)
    4036 {
    4037     int num;
    4038 
    4039     /* checks validity */
    4040     if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
    4041         return -1;
    4042 
    4043     /* gets field number */
    4044     if (PyStr_Check(param)) {
    4045         num = PQfnumber(self->result, PyBytes_AsString(param));
    4046     }
    4047     else if (PyInt_Check(param)) {
    4048         num = (int) PyInt_AsLong(param);
    4049     }
    4050     else {
    4051         PyErr_SetString(PyExc_TypeError, usage);
    4052         return -1;
    4053     }
    4054 
    4055     /* checks field validity */
    4056     if (num < 0 || num >= self->num_fields) {
    4057         PyErr_SetString(PyExc_ValueError, "Unknown field");
    4058         return -1;
    4059     }
    4060 
    4061     return num;
    4062 }
    4063 
    4064 /* builds field information from position (internal use only) */
    4065 static PyObject *
    4066 _source_buildinfo(sourceObject *self, int num)
    4067 {
    4068     PyObject *result;
    4069 
    4070     /* allocates tuple */
    4071     result = PyTuple_New(5);
    4072     if (!result) {
    4073         return NULL;
    4074     }
    4075 
    4076     /* affects field information */
    4077     PyTuple_SET_ITEM(result, 0, PyInt_FromLong(num));
    4078     PyTuple_SET_ITEM(result, 1,
    4079         PyStr_FromString(PQfname(self->result, num)));
    4080     PyTuple_SET_ITEM(result, 2,
    4081         PyInt_FromLong(PQftype(self->result, num)));
    4082     PyTuple_SET_ITEM(result, 3,
    4083         PyInt_FromLong(PQfsize(self->result, num)));
    4084     PyTuple_SET_ITEM(result, 4,
    4085         PyInt_FromLong(PQfmod(self->result, num)));
    4086 
    4087     return result;
    4088 }
    4089 
    4090 /* lists fields info */
    4091 static char source_listinfo__doc__[] =
    4092 "listinfo() -- get information for all fields (position, name, type oid)";
    4093 
    4094 static PyObject *
    4095 source_listInfo(sourceObject *self, PyObject *noargs)
    4096 {
    4097     PyObject *result, *info;
    4098     int i;
    4099 
    4100     /* checks validity */
    4101     if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL)) {
    4102         return NULL;
    4103     }
    4104 
    4105     /* builds result */
    4106     if (!(result = PyTuple_New(self->num_fields))) {
    4107         return NULL;
    4108     }
    4109 
    4110     for (i = 0; i < self->num_fields; ++i) {
    4111         info = _source_buildinfo(self, i);
    4112         if (!info) {
    4113             Py_DECREF(result);
    4114             return NULL;
    4115         }
    4116         PyTuple_SET_ITEM(result, i, info);
    4117     }
    4118 
    4119     /* returns result */
    4120     return result;
    4121 };
    4122 
    4123 /* list fields information for last result */
    4124 static char source_fieldinfo__doc__[] =
    4125 "fieldinfo(desc) -- get specified field info (position, name, type oid)";
    4126 
    4127 static PyObject *
    4128 source_fieldinfo(sourceObject *self, PyObject *desc)
    4129 {
    4130     int num;
    4131 
    4132     /* checks args and validity */
    4133     if ((num = _source_fieldindex(
    4134         self, desc,
    4135         "Method fieldinfo() needs a string or integer as argument")) == -1)
    4136     {
    4137         return NULL;
    4138     }
    4139 
    4140     /* returns result */
    4141     return _source_buildinfo(self, num);
    4142 };
    4143 
    4144 /* retrieve field value */
    4145 static char source_field__doc__[] =
    4146 "field(desc) -- return specified field value";
    4147 
    4148 static PyObject *
    4149 source_field(sourceObject *self, PyObject *desc)
    4150 {
    4151     int num;
    4152 
    4153     /* checks args and validity */
    4154     if ((num = _source_fieldindex(
    4155         self, desc,
    4156         "Method field() needs a string or integer as argument")) == -1)
    4157     {
    4158         return NULL;
    4159     }
    4160 
    4161     return PyStr_FromString(
    4162         PQgetvalue(self->result, self->current_row, num));
    4163 }
    4164 
    4165 /* get the list of source object attributes */
    4166 static PyObject *
    4167 source_dir(connObject *self, PyObject *noargs)
    4168 {
    4169     PyObject *attrs;
    4170 
    4171     attrs = PyObject_Dir(PyObject_Type((PyObject *) self));
    4172     PyObject_CallMethod(
    4173         attrs, "extend", "[sssss]",
    4174         "pgcnx", "arraysize", "resulttype", "ntuples", "nfields");
    4175 
    4176     return attrs;
    4177 }
    4178 
    4179 /* source object methods */
    4180 static PyMethodDef source_methods[] = {
    4181     {"__dir__", (PyCFunction) source_dir, METH_NOARGS, NULL},
    4182 
    4183     {"close", (PyCFunction) source_close,
    4184         METH_NOARGS, source_close__doc__},
    4185     {"execute", (PyCFunction) source_execute,
    4186         METH_O, source_execute__doc__},
    4187     {"oidstatus", (PyCFunction) source_oidstatus,
    4188         METH_NOARGS, source_oidstatus__doc__},
    4189     {"fetch", (PyCFunction) source_fetch,
    4190         METH_VARARGS, source_fetch__doc__},
    4191     {"movefirst", (PyCFunction) source_movefirst,
    4192         METH_NOARGS, source_movefirst__doc__},
    4193     {"movelast", (PyCFunction) source_movelast,
    4194         METH_NOARGS, source_movelast__doc__},
    4195     {"movenext", (PyCFunction) source_movenext,
    4196         METH_NOARGS, source_movenext__doc__},
    4197     {"moveprev", (PyCFunction) source_moveprev,
    4198         METH_NOARGS, source_moveprev__doc__},
    4199     {"putdata", (PyCFunction) source_putdata,
    4200         METH_O, source_putdata__doc__},
    4201     {"getdata", (PyCFunction) source_getdata,
    4202         METH_VARARGS, source_getdata__doc__},
    4203     {"field", (PyCFunction) source_field,
    4204         METH_O, source_field__doc__},
    4205     {"fieldinfo", (PyCFunction) source_fieldinfo,
    4206         METH_O, source_fieldinfo__doc__},
    4207     {"listinfo", (PyCFunction) source_listInfo,
    4208         METH_NOARGS, source_listinfo__doc__},
    4209     {NULL, NULL}
    4210 };
    4211 
    4212 /* gets source object attributes */
    4213 static PyObject *
    4214 source_getattr(sourceObject *self, PyObject *nameobj)
    4215 {
    4216     const char *name = PyStr_AsString(nameobj);
    4217 
    4218     /* pg connection object */
    4219     if (!strcmp(name, "pgcnx")) {
    4220         if (check_source_obj(self, 0)) {
    4221             Py_INCREF(self->pgcnx);
    4222             return (PyObject *) (self->pgcnx);
    4223         }
    4224         Py_INCREF(Py_None);
    4225         return Py_None;
    4226     }
    4227 
    4228     /* arraysize */
    4229     if (!strcmp(name, "arraysize"))
    4230         return PyInt_FromLong(self->arraysize);
    4231 
    4232     /* resulttype */
    4233     if (!strcmp(name, "resulttype"))
    4234         return PyInt_FromLong(self->result_type);
    4235 
    4236     /* ntuples */
    4237     if (!strcmp(name, "ntuples"))
    4238         return PyInt_FromLong(self->max_row);
    4239 
    4240     /* nfields */
    4241     if (!strcmp(name, "nfields"))
    4242         return PyInt_FromLong(self->num_fields);
    4243 
    4244     /* seeks name in methods (fallback) */
    4245     return PyObject_GenericGetAttr((PyObject *) self, nameobj);
    4246 }
    4247 
    4248 /* sets query object attributes */
    4249 static int
    4250 source_setattr(sourceObject *self, char *name, PyObject *v)
    4251 {
    4252     /* arraysize */
    4253     if (!strcmp(name, "arraysize")) {
    4254         if (!PyInt_Check(v)) {
    4255             PyErr_SetString(PyExc_TypeError, "arraysize must be integer");
    4256             return -1;
    4257         }
    4258 
    4259         self->arraysize = PyInt_AsLong(v);
    4260         return 0;
    4261     }
    4262 
    4263     /* unknown attribute */
    4264     PyErr_SetString(PyExc_TypeError, "Not a writable attribute");
    4265     return -1;
    4266 }
    4267 
    4268 /* return source object as string in human readable form */
    4269 static PyObject *
    4270 source_str(sourceObject *self)
    4271 {
    4272     switch (self->result_type) {
    4273         case RESULT_DQL:
    4274             return format_result(self->result);
    4275         case RESULT_DDL:
    4276         case RESULT_DML:
    4277             return PyStr_FromString(PQcmdStatus(self->result));
    4278         case RESULT_EMPTY:
    4279         default:
    4280             return PyStr_FromString("(empty PostgreSQL source object)");
    4281     }
    4282 }
    4283 
    4284 static char source__doc__[] = "PyGreSQL source object";
    4285 
    4286 /* source type definition */
    4287 static PyTypeObject sourceType = {
    4288     PyVarObject_HEAD_INIT(NULL, 0)
    4289     "pgdb.Source",                  /* tp_name */
    4290     sizeof(sourceObject),           /* tp_basicsize */
    4291     0,                              /* tp_itemsize */
    4292     /* methods */
    4293     (destructor) source_dealloc,    /* tp_dealloc */
    4294     0,                              /* tp_print */
    4295     0,                              /* tp_getattr */
    4296     (setattrfunc) source_setattr,   /* tp_setattr */
    4297     0,                              /* tp_compare */
    4298     0,                              /* tp_repr */
    4299     0,                              /* tp_as_number */
    4300     0,                              /* tp_as_sequence */
    4301     0,                              /* tp_as_mapping */
    4302     0,                              /* tp_hash */
    4303     0,                              /* tp_call */
    4304     (reprfunc) source_str,          /* tp_str */
    4305     (getattrofunc) source_getattr,  /* tp_getattro */
    4306     0,                              /* tp_setattro */
    4307     0,                              /* tp_as_buffer */
    4308     Py_TPFLAGS_DEFAULT,             /* tp_flags */
    4309     source__doc__,                  /* tp_doc */
    4310     0,                              /* tp_traverse */
    4311     0,                              /* tp_clear */
    4312     0,                              /* tp_richcompare */
    4313     0,                              /* tp_weaklistoffset */
    4314     0,                              /* tp_iter */
    4315     0,                              /* tp_iternext */
    4316     source_methods,                 /* tp_methods */
    4317 };
    4318 
    4319 /* connects to a database */
     217
     218/* MODULE FUNCTIONS */
     219
     220/* connect to a database */
    4320221static char pg_connect__doc__[] =
    4321222"connect(dbname, host, port, opt) -- connect to a PostgreSQL database\n\n"
     
    4401302    return (PyObject *) conn_obj;
    4402303}
    4403 
    4404 static void
    4405 query_dealloc(queryObject *self)
    4406 {
    4407     Py_XDECREF(self->pgcnx);
    4408     if (self->col_types) {
    4409         PyMem_Free(self->col_types);
    4410     }
    4411     if (self->result) {
    4412         PQclear(self->result);
    4413     }
    4414 
    4415     PyObject_Del(self);
    4416 }
    4417 
    4418 /* get number of rows */
    4419 static char query_ntuples__doc__[] =
    4420 "ntuples() -- return number of tuples returned by query";
    4421 
    4422 static PyObject *
    4423 query_ntuples(queryObject *self, PyObject *noargs)
    4424 {
    4425     return PyInt_FromLong(self->max_row);
    4426 }
    4427 
    4428 /* list fields names from query result */
    4429 static char query_listfields__doc__[] =
    4430 "listfields() -- List field names from result";
    4431 
    4432 static PyObject *
    4433 query_listfields(queryObject *self, PyObject *noargs)
    4434 {
    4435     int i;
    4436     char *name;
    4437     PyObject *fieldstuple, *str;
    4438 
    4439     /* builds tuple */
    4440     fieldstuple = PyTuple_New(self->num_fields);
    4441     if (fieldstuple) {
    4442         for (i = 0; i < self->num_fields; ++i) {
    4443             name = PQfname(self->result, i);
    4444             str = PyStr_FromString(name);
    4445             PyTuple_SET_ITEM(fieldstuple, i, str);
    4446         }
    4447     }
    4448     return fieldstuple;
    4449 }
    4450 
    4451 /* get field name from last result */
    4452 static char query_fieldname__doc__[] =
    4453 "fieldname(num) -- return name of field from result from its position";
    4454 
    4455 static PyObject *
    4456 query_fieldname(queryObject *self, PyObject *args)
    4457 {
    4458     int i;
    4459     char *name;
    4460 
    4461     /* gets args */
    4462     if (!PyArg_ParseTuple(args, "i", &i)) {
    4463         PyErr_SetString(PyExc_TypeError,
    4464                         "Method fieldname() takes an integer as argument");
    4465         return NULL;
    4466     }
    4467 
    4468     /* checks number validity */
    4469     if (i >= self->num_fields) {
    4470         PyErr_SetString(PyExc_ValueError, "Invalid field number");
    4471         return NULL;
    4472     }
    4473 
    4474     /* gets fields name and builds object */
    4475     name = PQfname(self->result, i);
    4476     return PyStr_FromString(name);
    4477 }
    4478 
    4479 /* gets fields number from name in last result */
    4480 static char query_fieldnum__doc__[] =
    4481 "fieldnum(name) -- return position in query for field from its name";
    4482 
    4483 static PyObject *
    4484 query_fieldnum(queryObject *self, PyObject *args)
    4485 {
    4486     int num;
    4487     char *name;
    4488 
    4489     /* gets args */
    4490     if (!PyArg_ParseTuple(args, "s", &name)) {
    4491         PyErr_SetString(PyExc_TypeError,
    4492                         "Method fieldnum() takes a string as argument");
    4493         return NULL;
    4494     }
    4495 
    4496     /* gets field number */
    4497     if ((num = PQfnumber(self->result, name)) == -1) {
    4498         PyErr_SetString(PyExc_ValueError, "Unknown field");
    4499         return NULL;
    4500     }
    4501 
    4502     return PyInt_FromLong(num);
    4503 }
    4504 
    4505 /* The __iter__() method of the queryObject.
    4506    This returns the default iterator yielding rows as tuples. */
    4507 static PyObject* query_iter(queryObject *self)
    4508 {
    4509     self->current_row = 0;
    4510     Py_INCREF(self);
    4511     return (PyObject*) self;
    4512 }
    4513 
    4514 /* Return the value in the given column of the current row. */
    4515 static PyObject *
    4516 _query_value_in_column(queryObject *self, int column)
    4517 {
    4518     char *s;
    4519     int type;
    4520 
    4521     if (PQgetisnull(self->result, self->current_row, column)) {
    4522         Py_INCREF(Py_None);
    4523         return Py_None;
    4524     }
    4525 
    4526     /* get the string representation of the value */
    4527     /* note: this is always null-terminated text format */
    4528     s = PQgetvalue(self->result, self->current_row, column);
    4529     /* get the PyGreSQL type of the column */
    4530     type = self->col_types[column];
    4531 
    4532     /* cast the string representation into a Python object */
    4533     if (type & PYGRES_ARRAY)
    4534         return cast_array(s,
    4535             PQgetlength(self->result, self->current_row, column),
    4536             self->encoding, type, NULL, 0);
    4537     if (type == PYGRES_BYTEA)
    4538         return cast_bytea_text(s);
    4539     if (type == PYGRES_OTHER)
    4540         return cast_other(s,
    4541             PQgetlength(self->result, self->current_row, column),
    4542             self->encoding,
    4543             PQftype(self->result, column), self->pgcnx->cast_hook);
    4544     if (type & PYGRES_TEXT)
    4545         return cast_sized_text(s,
    4546             PQgetlength(self->result, self->current_row, column),
    4547             self->encoding, type);
    4548     return cast_unsized_simple(s, type);
    4549 }
    4550 
    4551 /* Return the current row as a tuple. */
    4552 static PyObject *
    4553 _query_row_as_tuple(queryObject *self)
    4554 {
    4555     PyObject *row_tuple = NULL;
    4556     int j;
    4557 
    4558     if (!(row_tuple = PyTuple_New(self->num_fields))) {
    4559         return NULL;
    4560     }
    4561 
    4562     for (j = 0; j < self->num_fields; ++j) {
    4563         PyObject *val = _query_value_in_column(self, j);
    4564         if (!val) {
    4565             Py_DECREF(row_tuple); return NULL;
    4566         }
    4567         PyTuple_SET_ITEM(row_tuple, j, val);
    4568     }
    4569 
    4570     return row_tuple;
    4571 }
    4572 
    4573 /* The __next__() method of the queryObject.
    4574    Returns the current current row as a tuple and moves to the next one. */
    4575 static PyObject *
    4576 query_next(queryObject *self, PyObject *noargs)
    4577 {
    4578     PyObject *row_tuple = NULL;
    4579 
    4580     if (self->current_row >= self->max_row) {
    4581         PyErr_SetNone(PyExc_StopIteration);
    4582         return NULL;
    4583     }
    4584 
    4585     row_tuple = _query_row_as_tuple(self);
    4586     if (row_tuple) ++self->current_row;
    4587     return row_tuple;
    4588 }
    4589 
    4590 /* Retrieves one row from the result as a tuple. */
    4591 static char query_one__doc__[] =
    4592 "one() -- Get one row from the result of a query\n\n"
    4593 "Only one row from the result is returned as a tuple of fields.\n"
    4594 "This method can be called multiple times to return more rows.\n"
    4595 "It returns None if the result does not contain one more row.\n";
    4596 
    4597 static PyObject *
    4598 query_one(queryObject *self, PyObject *noargs)
    4599 {
    4600     PyObject *row_tuple;
    4601 
    4602     if (self->current_row >= self->max_row) {
    4603         Py_INCREF(Py_None); return Py_None;
    4604     }
    4605 
    4606     row_tuple = _query_row_as_tuple(self);
    4607     if (row_tuple) ++self->current_row;
    4608     return row_tuple;
    4609 }
    4610 
    4611 /* Retrieves the single row from the result as a tuple. */
    4612 static char query_single__doc__[] =
    4613 "single() -- Get the result of a query as single row\n\n"
    4614 "The single row from the query result is returned as a tuple of fields.\n"
    4615 "This method returns the same single row when called multiple times.\n"
    4616 "It raises an InvalidResultError if the result doesn't have exactly one row,\n"
    4617 "which will be of type NoResultError or MultipleResultsError specifically.\n";
    4618 
    4619 static PyObject *
    4620 query_single(queryObject *self, PyObject *noargs)
    4621 {
    4622     PyObject *row_tuple;
    4623 
    4624     if (self->max_row != 1) {
    4625         if (self->max_row)
    4626             set_error_msg(MultipleResultsError, "Multiple results found");
    4627         else
    4628             set_error_msg(NoResultError, "No result found");
    4629         return NULL;
    4630     }
    4631 
    4632     self->current_row = 0;
    4633     row_tuple = _query_row_as_tuple(self);
    4634     if (row_tuple) ++self->current_row;
    4635     return row_tuple;
    4636 }
    4637 
    4638 /* Retrieves the last query result as a list of tuples. */
    4639 static char query_getresult__doc__[] =
    4640 "getresult() -- Get the result of a query\n\n"
    4641 "The result is returned as a list of rows, each one a tuple of fields\n"
    4642 "in the order returned by the server.\n";
    4643 
    4644 static PyObject *
    4645 query_getresult(queryObject *self, PyObject *noargs)
    4646 {
    4647     PyObject *result_list;
    4648     int i;
    4649 
    4650     if (!(result_list = PyList_New(self->max_row))) {
    4651         return NULL;
    4652     }
    4653 
    4654     for (i = self->current_row = 0; i < self->max_row; ++i) {
    4655         PyObject *row_tuple = query_next(self, noargs);
    4656 
    4657         if (!row_tuple) {
    4658             Py_DECREF(result_list); return NULL;
    4659         }
    4660         PyList_SET_ITEM(result_list, i, row_tuple);
    4661     }
    4662 
    4663     return result_list;
    4664 }
    4665 
    4666 /* Return the current row as a dict. */
    4667 static PyObject *
    4668 _query_row_as_dict(queryObject *self)
    4669 {
    4670     PyObject *row_dict = NULL;
    4671     int j;
    4672 
    4673     if (!(row_dict = PyDict_New())) {
    4674         return NULL;
    4675     }
    4676 
    4677     for (j = 0; j < self->num_fields; ++j) {
    4678         PyObject *val = _query_value_in_column(self, j);
    4679 
    4680         if (!val) {
    4681             Py_DECREF(row_dict); return NULL;
    4682         }
    4683         PyDict_SetItemString(row_dict, PQfname(self->result, j), val);
    4684         Py_DECREF(val);
    4685     }
    4686 
    4687     return row_dict;
    4688 }
    4689 
    4690 /* Return the current current row as a dict and move to the next one. */
    4691 static PyObject *
    4692 query_next_dict(queryObject *self, PyObject *noargs)
    4693 {
    4694     PyObject *row_dict = NULL;
    4695 
    4696     if (self->current_row >= self->max_row) {
    4697         PyErr_SetNone(PyExc_StopIteration);
    4698         return NULL;
    4699     }
    4700 
    4701     row_dict = _query_row_as_dict(self);
    4702     if (row_dict) ++self->current_row;
    4703     return row_dict;
    4704 }
    4705 
    4706 /* Retrieve one row from the result as a dictionary. */
    4707 static char query_onedict__doc__[] =
    4708 "onedict() -- Get one row from the result of a query\n\n"
    4709 "Only one row from the result is returned as a dictionary with\n"
    4710 "the field names used as the keys.\n"
    4711 "This method can be called multiple times to return more rows.\n"
    4712 "It returns None if the result does not contain one more row.\n";
    4713 
    4714 static PyObject *
    4715 query_onedict(queryObject *self, PyObject *noargs)
    4716 {
    4717     PyObject *row_dict;
    4718 
    4719     if (self->current_row >= self->max_row) {
    4720         Py_INCREF(Py_None); return Py_None;
    4721     }
    4722 
    4723     row_dict = _query_row_as_dict(self);
    4724     if (row_dict) ++self->current_row;
    4725     return row_dict;
    4726 }
    4727 
    4728 /* Retrieve the single row from the result as a dictionary. */
    4729 static char query_singledict__doc__[] =
    4730 "singledict() -- Get the result of a query as single row\n\n"
    4731 "The single row from the query result is returned as a dictionary with\n"
    4732 "the field names used as the keys.\n"
    4733 "This method returns the same single row when called multiple times.\n"
    4734 "It raises an InvalidResultError if the result doesn't have exactly one row,\n"
    4735 "which will be of type NoResultError or MultipleResultsError specifically.\n";
    4736 
    4737 static PyObject *
    4738 query_singledict(queryObject *self, PyObject *noargs)
    4739 {
    4740     PyObject *row_dict;
    4741 
    4742     if (self->max_row != 1) {
    4743         if (self->max_row)
    4744             set_error_msg(MultipleResultsError, "Multiple results found");
    4745         else
    4746             set_error_msg(NoResultError, "No result found");
    4747         return NULL;
    4748     }
    4749 
    4750     self->current_row = 0;
    4751     row_dict = _query_row_as_dict(self);
    4752     if (row_dict) ++self->current_row;
    4753     return row_dict;
    4754 }
    4755 
    4756 /* Retrieve the last query result as a list of dictionaries. */
    4757 static char query_dictresult__doc__[] =
    4758 "dictresult() -- Get the result of a query\n\n"
    4759 "The result is returned as a list of rows, each one a dictionary with\n"
    4760 "the field names used as the keys.\n";
    4761 
    4762 static PyObject *
    4763 query_dictresult(queryObject *self, PyObject *noargs)
    4764 {
    4765     PyObject *result_list;
    4766     int i;
    4767 
    4768     if (!(result_list = PyList_New(self->max_row))) {
    4769         return NULL;
    4770     }
    4771 
    4772     for (i = self->current_row = 0; i < self->max_row; ++i) {
    4773         PyObject *row_dict = query_next_dict(self, noargs);
    4774 
    4775         if (!row_dict) {
    4776             Py_DECREF(result_list); return NULL;
    4777         }
    4778         PyList_SET_ITEM(result_list, i, row_dict);
    4779     }
    4780 
    4781     return result_list;
    4782 }
    4783 
    4784 /* Retrieve last result as iterator of dictionaries. */
    4785 static char query_dictiter__doc__[] =
    4786 "dictiter() -- Get the result of a query\n\n"
    4787 "The result is returned as an iterator of rows, each one a a dictionary\n"
    4788 "with the field names used as the keys.\n";
    4789 
    4790 static PyObject *
    4791 query_dictiter(queryObject *self, PyObject *noargs)
    4792 {
    4793     if (!dictiter) {
    4794         return query_dictresult(self, noargs);
    4795     }
    4796 
    4797     return PyObject_CallFunction(dictiter, "(O)", self);
    4798 }
    4799 
    4800 /* Retrieve one row from the result as a named tuple. */
    4801 static char query_onenamed__doc__[] =
    4802 "onenamed() -- Get one row from the result of a query\n\n"
    4803 "Only one row from the result is returned as a named tuple of fields.\n"
    4804 "This method can be called multiple times to return more rows.\n"
    4805 "It returns None if the result does not contain one more row.\n";
    4806 
    4807 static PyObject *
    4808 query_onenamed(queryObject *self, PyObject *noargs)
    4809 {
    4810     if (!namednext) {
    4811         return query_one(self, noargs);
    4812     }
    4813 
    4814     if (self->current_row >= self->max_row) {
    4815         Py_INCREF(Py_None); return Py_None;
    4816     }
    4817 
    4818     return PyObject_CallFunction(namednext, "(O)", self);
    4819 }
    4820 
    4821 /* Retrieve the single row from the result as a tuple. */
    4822 static char query_singlenamed__doc__[] =
    4823 "singlenamed() -- Get the result of a query as single row\n\n"
    4824 "The single row from the query result is returned as named tuple of fields.\n"
    4825 "This method returns the same single row when called multiple times.\n"
    4826 "It raises an InvalidResultError if the result doesn't have exactly one row,\n"
    4827 "which will be of type NoResultError or MultipleResultsError specifically.\n";
    4828 
    4829 static PyObject *
    4830 query_singlenamed(queryObject *self, PyObject *noargs)
    4831 {
    4832     if (!namednext) {
    4833         return query_single(self, noargs);
    4834     }
    4835 
    4836     if (self->max_row != 1) {
    4837         if (self->max_row)
    4838             set_error_msg(MultipleResultsError, "Multiple results found");
    4839         else
    4840             set_error_msg(NoResultError, "No result found");
    4841         return NULL;
    4842     }
    4843 
    4844     self->current_row = 0;
    4845     return PyObject_CallFunction(namednext, "(O)", self);
    4846 }
    4847 
    4848 /* Retrieve last result as list of named tuples. */
    4849 static char query_namedresult__doc__[] =
    4850 "namedresult() -- Get the result of a query\n\n"
    4851 "The result is returned as a list of rows, each one a named tuple of fields\n"
    4852 "in the order returned by the server.\n";
    4853 
    4854 static PyObject *
    4855 query_namedresult(queryObject *self, PyObject *noargs)
    4856 {
    4857     PyObject *res, *res_list;
    4858 
    4859     if (!namediter) {
    4860         return query_getresult(self, noargs);
    4861     }
    4862 
    4863     res = PyObject_CallFunction(namediter, "(O)", self);
    4864     if (!res) return NULL;
    4865     if (PyList_Check(res)) return res;
    4866     res_list = PySequence_List(res);
    4867     Py_DECREF(res);
    4868     return res_list;
    4869 }
    4870 
    4871 /* Retrieve last result as iterator of named tuples. */
    4872 static char query_namediter__doc__[] =
    4873 "namediter() -- Get the result of a query\n\n"
    4874 "The result is returned as an iterator of rows, each one a named tuple\n"
    4875 "of fields in the order returned by the server.\n";
    4876 
    4877 static PyObject *
    4878 query_namediter(queryObject *self, PyObject *noargs)
    4879 {
    4880     PyObject *res, *res_iter;
    4881 
    4882     if (!namediter) {
    4883         return query_iter(self);
    4884     }
    4885 
    4886     res = PyObject_CallFunction(namediter, "(O)", self);
    4887     if (!res) return NULL;
    4888     if (!PyList_Check(res)) return res;
    4889     res_iter = (Py_TYPE(res)->tp_iter)((PyObject *) self);
    4890     Py_DECREF(res);
    4891     return res_iter;
    4892 }
    4893 
    4894 /* Retrieve the last query result as a list of scalar values. */
    4895 static char query_scalarresult__doc__[] =
    4896 "scalarresult() -- Get query result as scalars\n\n"
    4897 "The result is returned as a list of scalar values where the values\n"
    4898 "are the first fields of the rows in the order returned by the server.\n";
    4899 
    4900 static PyObject *
    4901 query_scalarresult(queryObject *self, PyObject *noargs)
    4902 {
    4903     PyObject *result_list;
    4904 
    4905     if (!self->num_fields) {
    4906         set_error_msg(ProgrammingError, "No fields in result");
    4907         return NULL;
    4908     }
    4909 
    4910     if (!(result_list = PyList_New(self->max_row))) {
    4911         return NULL;
    4912     }
    4913 
    4914     for (self->current_row = 0;
    4915          self->current_row < self->max_row;
    4916          ++self->current_row)
    4917     {
    4918         PyObject *value = _query_value_in_column(self, 0);
    4919 
    4920         if (!value) {
    4921             Py_DECREF(result_list); return NULL;
    4922         }
    4923         PyList_SET_ITEM(result_list, self->current_row, value);
    4924     }
    4925 
    4926     return result_list;
    4927 }
    4928 
    4929 /* Retrieve the last query result as iterator of scalar values. */
    4930 static char query_scalariter__doc__[] =
    4931 "scalariter() -- Get query result as scalars\n\n"
    4932 "The result is returned as an iterator of scalar values where the values\n"
    4933 "are the first fields of the rows in the order returned by the server.\n";
    4934 
    4935 static PyObject *
    4936 query_scalariter(queryObject *self, PyObject *noargs)
    4937 {
    4938     if (!scalariter) {
    4939         return query_scalarresult(self, noargs);
    4940     }
    4941 
    4942     if (!self->num_fields) {
    4943         set_error_msg(ProgrammingError, "No fields in result");
    4944         return NULL;
    4945     }
    4946 
    4947     return PyObject_CallFunction(scalariter, "(O)", self);
    4948 }
    4949 
    4950 /* Retrieve one result as scalar value. */
    4951 static char query_onescalar__doc__[] =
    4952 "onescalar() -- Get one scalar value from the result of a query\n\n"
    4953 "Returns the first field of the next row from the result as a scalar value.\n"
    4954 "This method can be called multiple times to return more rows as scalars.\n"
    4955 "It returns None if the result does not contain one more row.\n";
    4956 
    4957 static PyObject *
    4958 query_onescalar(queryObject *self, PyObject *noargs)
    4959 {
    4960     PyObject *value;
    4961 
    4962     if (!self->num_fields) {
    4963         set_error_msg(ProgrammingError, "No fields in result");
    4964         return NULL;
    4965     }
    4966 
    4967     if (self->current_row >= self->max_row) {
    4968         Py_INCREF(Py_None); return Py_None;
    4969     }
    4970 
    4971     value = _query_value_in_column(self, 0);
    4972     if (value) ++self->current_row;
    4973     return value;
    4974 }
    4975 
    4976 /* Retrieves the single row from the result as a tuple. */
    4977 static char query_singlescalar__doc__[] =
    4978 "singlescalar() -- Get scalar value from single result of a query\n\n"
    4979 "Returns the first field of the next row from the result as a scalar value.\n"
    4980 "This method returns the same single row when called multiple times.\n"
    4981 "It raises an InvalidResultError if the result doesn't have exactly one row,\n"
    4982 "which will be of type NoResultError or MultipleResultsError specifically.\n";
    4983 
    4984 static PyObject *
    4985 query_singlescalar(queryObject *self, PyObject *noargs)
    4986 {
    4987     PyObject *value;
    4988 
    4989     if (!self->num_fields) {
    4990         set_error_msg(ProgrammingError, "No fields in result");
    4991         return NULL;
    4992     }
    4993 
    4994     if (self->max_row != 1) {
    4995         if (self->max_row)
    4996             set_error_msg(MultipleResultsError, "Multiple results found");
    4997         else
    4998             set_error_msg(NoResultError, "No result found");
    4999         return NULL;
    5000     }
    5001 
    5002     self->current_row = 0;
    5003     value = _query_value_in_column(self, 0);
    5004     if (value) ++self->current_row;
    5005     return value;
    5006 }
    5007 
    5008 /* Return length of a query object. */
    5009 static Py_ssize_t
    5010 query_len(PyObject *self)
    5011 {
    5012     PyObject *tmp;
    5013     long len;
    5014 
    5015     tmp = PyLong_FromLong(((queryObject*) self)->max_row);
    5016     len = PyLong_AsSsize_t(tmp);
    5017     Py_DECREF(tmp);
    5018     return len;
    5019 }
    5020 
    5021 /* Return given item from a query object. */
    5022 static PyObject *
    5023 query_getitem(PyObject *self, Py_ssize_t i)
    5024 {
    5025     queryObject *q = (queryObject *) self;
    5026     PyObject *tmp;
    5027     long row;
    5028 
    5029     tmp = PyLong_FromSize_t(i);
    5030     row = PyLong_AsLong(tmp);
    5031     Py_DECREF(tmp);
    5032 
    5033     if (row < 0 || row >= q->max_row) {
    5034         PyErr_SetNone(PyExc_IndexError);
    5035         return NULL;
    5036     }
    5037 
    5038     q->current_row = row;
    5039     return _query_row_as_tuple(q);
    5040 }
    5041 
    5042 /* gets notice object attributes */
    5043 static PyObject *
    5044 notice_getattr(noticeObject *self, PyObject *nameobj)
    5045 {
    5046     PGresult const *res = self->res;
    5047     const char *name = PyStr_AsString(nameobj);
    5048     int fieldcode;
    5049 
    5050     if (!res) {
    5051         PyErr_SetString(PyExc_TypeError, "Cannot get current notice");
    5052         return NULL;
    5053     }
    5054 
    5055     /* pg connection object */
    5056     if (!strcmp(name, "pgcnx")) {
    5057         if (self->pgcnx && check_cnx_obj(self->pgcnx)) {
    5058             Py_INCREF(self->pgcnx);
    5059             return (PyObject *) self->pgcnx;
    5060         }
    5061         else {
    5062             Py_INCREF(Py_None);
    5063             return Py_None;
    5064         }
    5065     }
    5066 
    5067     /* full message */
    5068     if (!strcmp(name, "message")) {
    5069         return PyStr_FromString(PQresultErrorMessage(res));
    5070     }
    5071 
    5072     /* other possible fields */
    5073     fieldcode = 0;
    5074     if (!strcmp(name, "severity"))
    5075         fieldcode = PG_DIAG_SEVERITY;
    5076     else if (!strcmp(name, "primary"))
    5077         fieldcode = PG_DIAG_MESSAGE_PRIMARY;
    5078     else if (!strcmp(name, "detail"))
    5079         fieldcode = PG_DIAG_MESSAGE_DETAIL;
    5080     else if (!strcmp(name, "hint"))
    5081         fieldcode = PG_DIAG_MESSAGE_HINT;
    5082     if (fieldcode) {
    5083         char *s = PQresultErrorField(res, fieldcode);
    5084         if (s) {
    5085             return PyStr_FromString(s);
    5086         }
    5087         else {
    5088             Py_INCREF(Py_None); return Py_None;
    5089         }
    5090     }
    5091 
    5092     return PyObject_GenericGetAttr((PyObject *) self, nameobj);
    5093 }
    5094 
    5095 /* return notice as string in human readable form */
    5096 static PyObject *
    5097 notice_str(noticeObject *self)
    5098 {
    5099     return notice_getattr(self, PyBytes_FromString("message"));
    5100 }
    5101 
    5102 /* get the list of notice attributes */
    5103 static PyObject *
    5104 notice_dir(noticeObject *self, PyObject *noargs)
    5105 {
    5106     PyObject *attrs;
    5107 
    5108     attrs = PyObject_Dir(PyObject_Type((PyObject *) self));
    5109     PyObject_CallMethod(
    5110         attrs, "extend", "[ssssss]",
    5111         "pgcnx", "severity", "message", "primary", "detail", "hint");
    5112 
    5113     return attrs;
    5114 }
    5115 
    5116 /* notice object methods */
    5117 static struct PyMethodDef notice_methods[] = {
    5118     {"__dir__", (PyCFunction) notice_dir,  METH_NOARGS, NULL},
    5119     {NULL, NULL}
    5120 };
    5121 
    5122 /* notice type definition */
    5123 static PyTypeObject noticeType = {
    5124     PyVarObject_HEAD_INIT(NULL, 0)
    5125     "pg.Notice",                    /* tp_name */
    5126     sizeof(noticeObject),           /* tp_basicsize */
    5127     0,                              /* tp_itemsize */
    5128     /* methods */
    5129     0,                              /* tp_dealloc */
    5130     0,                              /* tp_print */
    5131     0,                              /* tp_getattr */
    5132     0,                              /* tp_setattr */
    5133     0,                              /* tp_compare */
    5134     0,                              /* tp_repr */
    5135     0,                              /* tp_as_number */
    5136     0,                              /* tp_as_sequence */
    5137     0,                              /* tp_as_mapping */
    5138     0,                              /* tp_hash */
    5139     0,                              /* tp_call */
    5140     (reprfunc) notice_str,          /* tp_str */
    5141     (getattrofunc) notice_getattr,  /* tp_getattro */
    5142     PyObject_GenericSetAttr,        /* tp_setattro */
    5143     0,                              /* tp_as_buffer */
    5144     Py_TPFLAGS_DEFAULT,             /* tp_flags */
    5145     0,                              /* tp_doc */
    5146     0,                              /* tp_traverse */
    5147     0,                              /* tp_clear */
    5148     0,                              /* tp_richcompare */
    5149     0,                              /* tp_weaklistoffset */
    5150     0,                              /* tp_iter */
    5151     0,                              /* tp_iternext */
    5152     notice_methods,                 /* tp_methods */
    5153 };
    5154 
    5155 /* query object methods */
    5156 static struct PyMethodDef queryMethods[] = {
    5157     {"getresult", (PyCFunction) query_getresult,
    5158         METH_NOARGS, query_getresult__doc__},
    5159     {"dictresult", (PyCFunction) query_dictresult,
    5160         METH_NOARGS, query_dictresult__doc__},
    5161     {"dictiter", (PyCFunction) query_dictiter,
    5162         METH_NOARGS, query_dictiter__doc__},
    5163     {"namedresult", (PyCFunction) query_namedresult,
    5164         METH_NOARGS, query_namedresult__doc__},
    5165     {"namediter", (PyCFunction) query_namediter,
    5166         METH_NOARGS, query_namediter__doc__},
    5167     {"one", (PyCFunction) query_one,
    5168         METH_NOARGS, query_one__doc__},
    5169     {"single", (PyCFunction) query_single,
    5170         METH_NOARGS, query_single__doc__},
    5171     {"onedict", (PyCFunction) query_onedict,
    5172         METH_NOARGS, query_onedict__doc__},
    5173     {"singledict", (PyCFunction) query_singledict,
    5174         METH_NOARGS, query_singledict__doc__},
    5175     {"onenamed", (PyCFunction) query_onenamed,
    5176         METH_NOARGS, query_onenamed__doc__},
    5177     {"singlenamed", (PyCFunction) query_singlenamed,
    5178         METH_NOARGS, query_singlenamed__doc__},
    5179     {"scalarresult", (PyCFunction) query_scalarresult,
    5180         METH_NOARGS, query_scalarresult__doc__},
    5181     {"scalariter", (PyCFunction) query_scalariter,
    5182         METH_NOARGS, query_scalariter__doc__},
    5183     {"onescalar", (PyCFunction) query_onescalar,
    5184         METH_NOARGS, query_onescalar__doc__},
    5185     {"singlescalar", (PyCFunction) query_singlescalar,
    5186         METH_NOARGS, query_singlescalar__doc__},
    5187     {"fieldname", (PyCFunction) query_fieldname,
    5188         METH_VARARGS, query_fieldname__doc__},
    5189     {"fieldnum", (PyCFunction) query_fieldnum,
    5190         METH_VARARGS, query_fieldnum__doc__},
    5191     {"listfields", (PyCFunction) query_listfields,
    5192         METH_NOARGS, query_listfields__doc__},
    5193     {"ntuples", (PyCFunction) query_ntuples,
    5194         METH_NOARGS, query_ntuples__doc__},
    5195     {NULL, NULL}
    5196 };
    5197 
    5198 /* query sequence protocol methods */
    5199 static PySequenceMethods query_sequence_methods = {
    5200     (lenfunc) query_len,           /* sq_length */
    5201     0,                             /* sq_concat */
    5202     0,                             /* sq_repeat */
    5203     (ssizeargfunc) query_getitem,  /* sq_item */
    5204     0,                             /* sq_ass_item */
    5205     0,                             /* sq_contains */
    5206     0,                             /* sq_inplace_concat */
    5207     0,                             /* sq_inplace_repeat */
    5208 };
    5209 
    5210 /* query type definition */
    5211 static PyTypeObject queryType = {
    5212     PyVarObject_HEAD_INIT(NULL, 0)
    5213     "pg.Query",                  /* tp_name */
    5214     sizeof(queryObject),         /* tp_basicsize */
    5215     0,                           /* tp_itemsize */
    5216     /* methods */
    5217     (destructor) query_dealloc,  /* tp_dealloc */
    5218     0,                           /* tp_print */
    5219     0,                           /* tp_getattr */
    5220     0,                           /* tp_setattr */
    5221     0,                           /* tp_compare */
    5222     0,                           /* tp_repr */
    5223     0,                           /* tp_as_number */
    5224     &query_sequence_methods,     /* tp_as_sequence */
    5225     0,                           /* tp_as_mapping */
    5226     0,                           /* tp_hash */
    5227     0,                           /* tp_call */
    5228     (reprfunc) query_str,        /* tp_str */
    5229     PyObject_GenericGetAttr,     /* tp_getattro */
    5230     0,                           /* tp_setattro */
    5231     0,                           /* tp_as_buffer */
    5232     Py_TPFLAGS_DEFAULT
    5233         |Py_TPFLAGS_HAVE_ITER,   /* tp_flags */
    5234     0,                           /* tp_doc */
    5235     0,                           /* tp_traverse */
    5236     0,                           /* tp_clear */
    5237     0,                           /* tp_richcompare */
    5238     0,                           /* tp_weaklistoffset */
    5239     (getiterfunc) query_iter,    /* tp_iter */
    5240     (iternextfunc) query_next,   /* tp_iternext */
    5241     queryMethods,                /* tp_methods */
    5242 };
    5243 
    5244 /* --------------------------------------------------------------------- */
    5245 
    5246 /* MODULE FUNCTIONS */
    5247304
    5248305/* escape string */
Note: See TracChangeset for help on using the changeset viewer.