source: trunk/pgmodule.c

Last change on this file was 932, checked in by cito, 8 months ago

Alternative workaround for Python 3.7 issue

  • Property svn:keywords set to Id
File size: 142.5 KB
Line 
1/*
2 * $Id: pgmodule.c 932 2018-04-22 16:26:15Z darcy $
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).
7 *
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation for any purpose, without fee, and without a written
10 * agreement is hereby granted, provided that the above copyright notice and
11 * this paragraph and the following two paragraphs appear in all copies or in
12 * any new file that contains a substantial portion of this file.
13 *
14 * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
15 * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE
17 * AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18 *
19 * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE
22 * AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
23 * ENHANCEMENTS, OR MODIFICATIONS.
24 *
25 * Further modifications copyright 1997 to 2018 by D'Arcy J.M. Cain
26 * (darcy@PyGreSQL.org) subject to the same terms and conditions as above.
27 *
28 */
29
30/* Note: This should be linked against the same C runtime lib as Python */
31
32#include <Python.h>
33
34#include <libpq-fe.h>
35#include <libpq/libpq-fs.h>
36
37/* the type definitions from <server/catalog/pg_type.h> */
38#include "pgtypes.h"
39
40/* macros for single-source Python 2/3 compatibility */
41#include "py3c.h"
42
43static PyObject *Error, *Warning, *InterfaceError,
44        *DatabaseError, *InternalError, *OperationalError, *ProgrammingError,
45        *IntegrityError, *DataError, *NotSupportedError;
46
47#define _TOSTRING(x) #x
48#define TOSTRING(x) _TOSTRING(x)
49static const char *PyPgVersion = TOSTRING(PYGRESQL_VERSION);
50
51#if SIZEOF_SIZE_T != SIZEOF_INT
52#define Py_InitModule4 Py_InitModule4_64
53#endif
54
55/* default values */
56#define PG_ARRAYSIZE            1
57
58/* flags for object validity checks */
59#define CHECK_OPEN                      1
60#define CHECK_CLOSE                     2
61#define CHECK_CNX                       4
62#define CHECK_RESULT            8
63#define CHECK_DQL                       16
64
65/* query result types */
66#define RESULT_EMPTY            1
67#define RESULT_DML                      2
68#define RESULT_DDL                      3
69#define RESULT_DQL                      4
70
71/* flags for move methods */
72#define QUERY_MOVEFIRST         1
73#define QUERY_MOVELAST          2
74#define QUERY_MOVENEXT          3
75#define QUERY_MOVEPREV          4
76
77#define MAX_BUFFER_SIZE 8192    /* maximum transaction size */
78#define MAX_ARRAY_DEPTH 16              /* maximum allowed depth of an array */
79
80/* MODULE GLOBAL VARIABLES */
81
82#ifdef DEFAULT_VARS
83static PyObject *pg_default_host;       /* default database host */
84static PyObject *pg_default_base;       /* default database name */
85static PyObject *pg_default_opt;        /* default connection options */
86static PyObject *pg_default_port;       /* default connection port */
87static PyObject *pg_default_user;       /* default username */
88static PyObject *pg_default_passwd;     /* default password */
89#endif  /* DEFAULT_VARS */
90
91static PyObject *decimal = NULL, /* decimal type */
92                                *namedresult = NULL, /* function for getting named results */
93                                *jsondecode = NULL; /* function for decoding json strings */
94static const char *date_format = NULL; /* date format that is always assumed */
95static char decimal_point = '.'; /* decimal point used in money values */
96static int bool_as_text = 0; /* whether bool shall be returned as text */
97static int array_as_text = 0; /* whether arrays shall be returned as text */
98static int bytea_escaped = 0; /* whether bytea shall be returned escaped */
99
100static int pg_encoding_utf8 = 0;
101static int pg_encoding_latin1 = 0;
102static int pg_encoding_ascii = 0;
103
104/*
105OBJECTS
106=======
107
108  Each object has a number of elements.  The naming scheme will be based on
109  the object type.  Here are the elements using example object type "foo".
110   - fooObject: A structure to hold local object information.
111   - fooXxx: Object methods such as Delete and Getattr.
112   - fooMethods: Methods declaration.
113   - fooType: Type definition for object.
114
115  This is followed by the object methods.
116
117  The objects that we need to create:
118   - pg: The module itself.
119   - conn: Connection object returned from pg.connect().
120   - notice: Notice object returned from pg.notice().
121   - large: Large object returned by pg.conn.locreate() and Pg.Conn.loimport().
122   - query: Query object returned by pg.conn.Conn.query().
123   - source: Source object returned by pg.conn.source().
124*/
125
126/* forward declarations for types */
127static PyTypeObject noticeType;
128static PyTypeObject queryType;
129static PyTypeObject sourceType;
130static PyTypeObject largeType;
131static PyTypeObject connType;
132
133/* forward static declarations */
134static void notice_receiver(void *, const PGresult *);
135
136/* --------------------------------------------------------------------- */
137/* Object declarations                                                                                                   */
138/* --------------------------------------------------------------------- */
139typedef struct
140{
141        PyObject_HEAD
142        int                     valid;                          /* validity flag */
143        PGconn     *cnx;                                /* Postgres connection handle */
144        const char *date_format;                /* date format derived from datestyle */
145        PyObject   *cast_hook;                  /* external typecast method */
146        PyObject   *notice_receiver;    /* current notice receiver */
147}       connObject;
148#define is_connObject(v) (PyType(v) == &connType)
149
150typedef struct
151{
152        PyObject_HEAD
153        int                     valid;                  /* validity flag */
154        connObject *pgcnx;                      /* parent connection object */
155        PGresult        *result;                /* result content */
156        int                     encoding;               /* client encoding */
157        int                     result_type;    /* result type (DDL/DML/DQL) */
158        long            arraysize;              /* array size for fetch method */
159        int                     current_row;    /* current selected row */
160        int                     max_row;                /* number of rows in the result */
161        int                     num_fields;             /* number of fields in each row */
162}       sourceObject;
163#define is_sourceObject(v) (PyType(v) == &sourceType)
164
165typedef struct
166{
167        PyObject_HEAD
168        connObject *pgcnx;                      /* parent connection object */
169        PGresult        const *res;             /* an error or warning */
170}       noticeObject;
171#define is_noticeObject(v) (PyType(v) == &noticeType)
172
173typedef struct
174{
175        PyObject_HEAD
176        connObject *pgcnx;                      /* parent connection object */
177        PGresult   *result;                     /* result content */
178        int                     encoding;               /* client encoding */
179}       queryObject;
180#define is_queryObject(v) (PyType(v) == &queryType)
181
182#ifdef LARGE_OBJECTS
183typedef struct
184{
185        PyObject_HEAD
186        connObject *pgcnx;                      /* parent connection object */
187        Oid                     lo_oid;                 /* large object oid */
188        int                     lo_fd;                  /* large object fd */
189}       largeObject;
190#define is_largeObject(v) (PyType(v) == &largeType)
191#endif /* LARGE_OBJECTS */
192
193/* PyGreSQL internal types */
194
195/* simple types */
196#define PYGRES_INT 1
197#define PYGRES_LONG 2
198#define PYGRES_FLOAT 3
199#define PYGRES_DECIMAL 4
200#define PYGRES_MONEY 5
201#define PYGRES_BOOL 6
202/* text based types */
203#define PYGRES_TEXT 8
204#define PYGRES_BYTEA 9
205#define PYGRES_JSON 10
206#define PYGRES_OTHER 11
207/* array types */
208#define PYGRES_ARRAY 16
209
210/* --------------------------------------------------------------------- */
211/* Internal Functions                                                                                                    */
212/* --------------------------------------------------------------------- */
213
214/* shared function for encoding and decoding strings */
215
216static PyObject *
217get_decoded_string(const char *str, Py_ssize_t size, int encoding)
218{
219        if (encoding == pg_encoding_utf8)
220                return PyUnicode_DecodeUTF8(str, size, "strict");
221        if (encoding == pg_encoding_latin1)
222                return PyUnicode_DecodeLatin1(str, size, "strict");
223        if (encoding == pg_encoding_ascii)
224                return PyUnicode_DecodeASCII(str, size, "strict");
225        /* encoding name should be properly translated to Python here */
226        return PyUnicode_Decode(str, size,
227                pg_encoding_to_char(encoding), "strict");
228}
229
230static PyObject *
231get_encoded_string(PyObject *unicode_obj, int encoding)
232{
233        if (encoding == pg_encoding_utf8)
234                return PyUnicode_AsUTF8String(unicode_obj);
235        if (encoding == pg_encoding_latin1)
236                return PyUnicode_AsLatin1String(unicode_obj);
237        if (encoding == pg_encoding_ascii)
238                return PyUnicode_AsASCIIString(unicode_obj);
239        /* encoding name should be properly translated to Python here */
240        return PyUnicode_AsEncodedString(unicode_obj,
241                pg_encoding_to_char(encoding), "strict");
242}
243
244/* helper functions */
245
246/* get PyGreSQL internal types for a PostgreSQL type */
247static int
248get_type(Oid pgtype)
249{
250        int t;
251
252        switch (pgtype)
253        {
254                /* simple types */
255
256                case INT2OID:
257                case INT4OID:
258                case CIDOID:
259                case OIDOID:
260                case XIDOID:
261                        t = PYGRES_INT;
262                        break;
263
264                case INT8OID:
265                        t = PYGRES_LONG;
266                        break;
267
268                case FLOAT4OID:
269                case FLOAT8OID:
270                        t = PYGRES_FLOAT;
271                        break;
272
273                case NUMERICOID:
274                        t = PYGRES_DECIMAL;
275                        break;
276
277                case CASHOID:
278                        t = decimal_point ? PYGRES_MONEY : PYGRES_TEXT;
279                        break;
280
281                case BOOLOID:
282                        t = PYGRES_BOOL;
283                        break;
284
285                case BYTEAOID:
286                        t = bytea_escaped ? PYGRES_TEXT : PYGRES_BYTEA;
287                        break;
288
289                case JSONOID:
290                case JSONBOID:
291                        t = jsondecode ? PYGRES_JSON : PYGRES_TEXT;
292                        break;
293
294                case BPCHAROID:
295                case CHAROID:
296                case TEXTOID:
297                case VARCHAROID:
298                case NAMEOID:
299                case REGTYPEOID:
300                        t = PYGRES_TEXT;
301                        break;
302
303                /* array types */
304
305                case INT2ARRAYOID:
306                case INT4ARRAYOID:
307                case CIDARRAYOID:
308                case OIDARRAYOID:
309                case XIDARRAYOID:
310                        t = array_as_text ? PYGRES_TEXT : (PYGRES_INT | PYGRES_ARRAY);
311                        break;
312
313                case INT8ARRAYOID:
314                        t = array_as_text ? PYGRES_TEXT : (PYGRES_LONG | PYGRES_ARRAY);
315                        break;
316
317                case FLOAT4ARRAYOID:
318                case FLOAT8ARRAYOID:
319                        t = array_as_text ? PYGRES_TEXT : (PYGRES_FLOAT | PYGRES_ARRAY);
320                        break;
321
322                case NUMERICARRAYOID:
323                        t = array_as_text ? PYGRES_TEXT : (PYGRES_DECIMAL | PYGRES_ARRAY);
324                        break;
325
326                case CASHARRAYOID:
327                        t = array_as_text ? PYGRES_TEXT : ((decimal_point ?
328                                PYGRES_MONEY : PYGRES_TEXT) | PYGRES_ARRAY);
329                        break;
330
331                case BOOLARRAYOID:
332                        t = array_as_text ? PYGRES_TEXT : (PYGRES_BOOL | PYGRES_ARRAY);
333                        break;
334
335                case BYTEAARRAYOID:
336                        t = array_as_text ? PYGRES_TEXT : ((bytea_escaped ?
337                            PYGRES_TEXT : PYGRES_BYTEA) | PYGRES_ARRAY);
338                        break;
339
340                case JSONARRAYOID:
341                case JSONBARRAYOID:
342                        t = array_as_text ? PYGRES_TEXT : ((jsondecode ?
343                            PYGRES_JSON : PYGRES_TEXT) | PYGRES_ARRAY);
344                        break;
345
346                case BPCHARARRAYOID:
347                case CHARARRAYOID:
348                case TEXTARRAYOID:
349                case VARCHARARRAYOID:
350                case NAMEARRAYOID:
351                case REGTYPEARRAYOID:
352                        t = array_as_text ? PYGRES_TEXT : (PYGRES_TEXT | PYGRES_ARRAY);
353                        break;
354
355                default:
356                        t = PYGRES_OTHER;
357        }
358
359        return t;
360}
361
362/* get PyGreSQL column types for all result columns */
363static int *
364get_col_types(PGresult *result, int nfields)
365{
366        int *types, *t, j;
367
368        if (!(types = PyMem_Malloc(sizeof(int) * nfields)))
369                return (int *)PyErr_NoMemory();
370
371        for (j = 0, t=types; j < nfields; ++j)
372                *t++ = get_type(PQftype(result, j));
373
374        return types;
375}
376
377/* Cast a bytea encoded text based type to a Python object.
378   This assumes the text is null-terminated character string. */
379static PyObject *
380cast_bytea_text(char *s)
381{
382        PyObject   *obj;
383        char       *tmp_str;
384        size_t          str_len;
385
386    /* this function should not be called when bytea_escaped is set */
387        tmp_str = (char *)PQunescapeBytea((unsigned char*)s, &str_len);
388        obj = PyBytes_FromStringAndSize(tmp_str, str_len);
389        if (tmp_str)
390                PQfreemem(tmp_str);
391        return obj;
392}
393
394/* Cast a text based type to a Python object.
395   This needs the character string, size and encoding. */
396static PyObject *
397cast_sized_text(char *s, Py_ssize_t size, int encoding, int type)
398{
399        PyObject   *obj, *tmp_obj;
400        char       *tmp_str;
401        size_t          str_len;
402
403        switch (type) /* this must be the PyGreSQL internal type */
404        {
405                case PYGRES_BYTEA:
406                    /* this type should not be passed when bytea_escaped is set */
407                        /* we need to add a null byte */
408                        tmp_str = (char *) PyMem_Malloc(size + 1);
409                        if (!tmp_str) return PyErr_NoMemory();
410                        memcpy(tmp_str, s, size);
411                        s = tmp_str; *(s + size) = '\0';
412                        tmp_str = (char *)PQunescapeBytea((unsigned char*)s, &str_len);
413                        PyMem_Free(s);
414                        if (!tmp_str) return PyErr_NoMemory();
415                        obj = PyBytes_FromStringAndSize(tmp_str, str_len);
416                        if (tmp_str)
417                                PQfreemem(tmp_str);
418                        break;
419
420                case PYGRES_JSON:
421                        /* this type should only be passed when jsondecode is set */
422                        obj = get_decoded_string(s, size, encoding);
423                        if (obj && jsondecode) /* was able to decode */
424                        {
425                                tmp_obj = Py_BuildValue("(O)", obj);
426                                obj = PyObject_CallObject(jsondecode, tmp_obj);
427                                Py_DECREF(tmp_obj);
428                        }
429                        break;
430
431                default:  /* PYGRES_TEXT */
432#if IS_PY3
433                        obj = get_decoded_string(s, size, encoding);
434                        if (!obj) /* cannot decode */
435#endif
436                        obj = PyBytes_FromStringAndSize(s, size);
437        }
438
439        return obj;
440}
441
442/* Cast an arbitrary type to a Python object using a callback function.
443   This needs the character string, size, encoding, the Postgres type
444   and the external typecast function to be called. */
445static PyObject *
446cast_other(char *s, Py_ssize_t size, int encoding, Oid pgtype,
447        PyObject *cast_hook)
448{
449        PyObject *obj;
450
451        obj = cast_sized_text(s, size, encoding, PYGRES_TEXT);
452
453        if (cast_hook)
454        {
455                PyObject *tmp_obj = obj;
456                obj = PyObject_CallFunction(cast_hook, "(OI)", obj, pgtype);
457                Py_DECREF(tmp_obj);
458        }
459        return obj;
460}
461
462/* Cast a simple type to a Python object.
463   This needs a character string representation with a given size. */
464static PyObject *
465cast_sized_simple(char *s, Py_ssize_t size, int type)
466{
467        PyObject   *obj, *tmp_obj;
468        char            buf[64], *t;
469        int                     i, j, n;
470
471        switch (type) /* this must be the PyGreSQL internal type */
472        {
473                case PYGRES_INT:
474                        n = sizeof(buf)/sizeof(buf[0]) - 1;
475                        if ((int)size < n) n = (int)size;
476                        for (i = 0, t = buf; i < n; ++i) *t++ = *s++;
477                        *t = '\0';
478                        obj = PyInt_FromString(buf, NULL, 10);
479                        break;
480
481                case PYGRES_LONG:
482                        n = sizeof(buf)/sizeof(buf[0]) - 1;
483                        if ((int)size < n) n = (int)size;
484                        for (i = 0, t = buf; i < n; ++i) *t++ = *s++;
485                        *t = '\0';
486                        obj = PyLong_FromString(buf, NULL, 10);
487                        break;
488
489                case PYGRES_FLOAT:
490                        tmp_obj = PyStr_FromStringAndSize(s, size);
491                        obj = PyFloat_FromString(tmp_obj);
492                        Py_DECREF(tmp_obj);
493                        break;
494
495                case PYGRES_MONEY:
496                        /* this type should only be passed when decimal_point is set */
497                        n = sizeof(buf)/sizeof(buf[0]) - 1;
498                        for (i = 0, j = 0; i < size && j < n; ++i, ++s)
499                        {
500                                if (*s >= '0' && *s <= '9')
501                                        buf[j++] = *s;
502                                else if (*s == decimal_point)
503                                        buf[j++] = '.';
504                                else if (*s == '(' || *s == '-')
505                                        buf[j++] = '-';
506                        }
507                        if (decimal)
508                        {
509                                buf[j] = '\0';
510                                obj = PyObject_CallFunction(decimal, "(s)", buf);
511                        }
512                        else
513                        {
514                                tmp_obj = PyStr_FromString(buf);
515                                obj = PyFloat_FromString(tmp_obj);
516                                Py_DECREF(tmp_obj);
517
518                        }
519                        break;
520
521                case PYGRES_DECIMAL:
522                        tmp_obj = PyStr_FromStringAndSize(s, size);
523                        obj = decimal ? PyObject_CallFunctionObjArgs(
524                                decimal, tmp_obj, NULL) : PyFloat_FromString(tmp_obj);
525                        Py_DECREF(tmp_obj);
526                        break;
527
528                case PYGRES_BOOL:
529                        /* convert to bool only if bool_as_text is not set */
530                        if (bool_as_text)
531                        {
532                                obj = PyStr_FromString(*s == 't' ? "t" : "f");
533                        }
534                        else
535                        {
536                                obj = *s == 't' ? Py_True : Py_False;
537                                Py_INCREF(obj);
538                        }
539                        break;
540
541                default:
542                        /* other types should never be passed, use cast_sized_text */
543                        obj = PyStr_FromStringAndSize(s, size);
544        }
545
546        return obj;
547}
548
549/* Cast a simple type to a Python object.
550   This needs a null-terminated character string representation. */
551static PyObject *
552cast_unsized_simple(char *s, int type)
553{
554        PyObject   *obj, *tmp_obj;
555        char            buf[64];
556        int                     j, n;
557
558        switch (type) /* this must be the PyGreSQL internal type */
559        {
560                case PYGRES_INT:
561                        obj = PyInt_FromString(s, NULL, 10);
562                        break;
563
564                case PYGRES_LONG:
565                        obj = PyLong_FromString(s, NULL, 10);
566                        break;
567
568                case PYGRES_FLOAT:
569                        tmp_obj = PyStr_FromString(s);
570                        obj = PyFloat_FromString(tmp_obj);
571                        Py_DECREF(tmp_obj);
572                        break;
573
574                case PYGRES_MONEY:
575                        /* this type should only be passed when decimal_point is set */
576                        n = sizeof(buf)/sizeof(buf[0]) - 1;
577                        for (j = 0; *s && j < n; ++s)
578                        {
579                                if (*s >= '0' && *s <= '9')
580                                        buf[j++] = *s;
581                                else if (*s == decimal_point)
582                                        buf[j++] = '.';
583                                else if (*s == '(' || *s == '-')
584                                        buf[j++] = '-';
585                        }
586                        buf[j] = '\0'; s = buf;
587                        /* FALLTHROUGH */ /* no break here */
588
589                case PYGRES_DECIMAL:
590                        if (decimal)
591                        {
592                                obj = PyObject_CallFunction(decimal, "(s)", s);
593                        }
594                        else
595                        {
596                                tmp_obj = PyStr_FromString(s);
597                                obj = PyFloat_FromString(tmp_obj);
598                                Py_DECREF(tmp_obj);
599                        }
600                        break;
601
602                case PYGRES_BOOL:
603                        /* convert to bool only if bool_as_text is not set */
604                        if (bool_as_text)
605                        {
606                                obj = PyStr_FromString(*s == 't' ? "t" : "f");
607                        }
608                        else
609                        {
610                                obj = *s == 't' ? Py_True : Py_False;
611                                Py_INCREF(obj);
612                        }
613                        break;
614
615                default:
616                        /* other types should never be passed, use cast_sized_text */
617                        obj = PyStr_FromString(s);
618        }
619
620        return obj;
621}
622
623/* quick case insensitive check if given sized string is null */
624#define STR_IS_NULL(s, n) (n == 4 \
625        && (s[0] == 'n' || s[0] == 'N') \
626        && (s[1] == 'u' || s[1] == 'U') \
627        && (s[2] == 'l' || s[2] == 'L') \
628        && (s[3] == 'l' || s[3] == 'L'))
629
630/* Cast string s with size and encoding to a Python list,
631   using the input and output syntax for arrays.
632   Use internal type or cast function to cast elements.
633   The parameter delim specifies the delimiter for the elements,
634   since some types do not use the default delimiter of a comma. */
635static PyObject *
636cast_array(char *s, Py_ssize_t size, int encoding,
637         int type, PyObject *cast, char delim)
638{
639        PyObject   *result, *stack[MAX_ARRAY_DEPTH];
640        char       *end = s + size, *t;
641        int                     depth, ranges = 0, level = 0;
642
643        if (type)
644        {
645                type &= ~PYGRES_ARRAY; /* get the base type */
646                if (!type) type = PYGRES_TEXT;
647        }
648        if (!delim)
649                delim = ',';
650        else if (delim == '{' || delim =='}' || delim=='\\')
651        {
652                PyErr_SetString(PyExc_ValueError, "Invalid array delimiter");
653                return NULL;
654        }
655
656        /* strip blanks at the beginning */
657        while (s != end && *s == ' ') ++s;
658        if (*s == '[') /* dimension ranges */
659        {
660                int valid;
661
662                for (valid = 0; !valid;)
663                {
664                        if (s == end || *s++ != '[') break;
665                        while (s != end && *s == ' ') ++s;
666                        if (s != end && (*s == '+' || *s == '-')) ++s;
667                        if (s == end || *s <= '0' || *s >= '9') break;
668                        while (s != end && *s >= '0' && *s <= '9') ++s;
669                        if (s == end || *s++ != ':') break;
670                        if (s != end && (*s == '+' || *s == '-')) ++s;
671                        if (s == end || *s <= '0' || *s >= '9') break;
672                        while (s != end && *s >= '0' && *s <= '9') ++s;
673                        if (s == end || *s++ != ']') break;
674                        while (s != end && *s == ' ') ++s;
675                        ++ranges;
676                        if (s != end && *s == '=')
677                        {
678                                do ++s; while (s != end && *s == ' ');
679                                valid = 1;
680                        }
681                }
682                if (!valid)
683                {
684                        PyErr_SetString(PyExc_ValueError, "Invalid array dimensions");
685                        return NULL;
686                }
687        }
688        for (t = s, depth = 0; t != end && (*t == '{' || *t == ' '); ++t)
689                if (*t == '{') ++depth;
690        if (!depth)
691        {
692                PyErr_SetString(PyExc_ValueError,
693                        "Array must start with a left brace");
694                return NULL;
695        }
696        if (ranges && depth != ranges)
697        {
698                PyErr_SetString(PyExc_ValueError,
699                        "Array dimensions do not match content");
700                return NULL;
701        }
702        if (depth > MAX_ARRAY_DEPTH)
703        {
704                PyErr_SetString(PyExc_ValueError, "Array is too deeply nested");
705                return NULL;
706        }
707        depth--; /* next level of parsing */
708        result = PyList_New(0);
709        if (!result) return NULL;
710        do ++s; while (s != end && *s == ' ');
711        /* everything is set up, start parsing the array */
712        while (s != end)
713        {
714                if (*s == '}')
715                {
716                        PyObject *subresult;
717
718                        if (!level) break; /* top level array ended */
719                        do ++s; while (s != end && *s == ' ');
720                        if (s == end) break; /* error */
721                        if (*s == delim)
722                        {
723                                do ++s; while (s != end && *s == ' ');
724                                if (s == end) break; /* error */
725                                if (*s != '{')
726                                {
727                                        PyErr_SetString(PyExc_ValueError,
728                                                "Subarray expected but not found");
729                                        Py_DECREF(result); return NULL;
730                                }
731                        }
732                        else if (*s != '}') break; /* error */
733                        subresult = result;
734                        result = stack[--level];
735                        if (PyList_Append(result, subresult))
736                        {
737                                Py_DECREF(result); return NULL;
738                        }
739                }
740                else if (level == depth) /* we expect elements at this level */
741                {
742                        PyObject   *element;
743                        char       *estr;
744                        Py_ssize_t      esize;
745                        int escaped = 0;
746
747                        if (*s == '{')
748                        {
749                                PyErr_SetString(PyExc_ValueError,
750                                        "Subarray found where not expected");
751                                Py_DECREF(result); return NULL;
752                        }
753                        if (*s == '"') /* quoted element */
754                        {
755                                estr = ++s;
756                                while (s != end && *s != '"')
757                                {
758                                        if (*s == '\\')
759                                        {
760                                                ++s; if (s == end) break;
761                                                escaped = 1;
762                                        }
763                                        ++s;
764                                }
765                                esize = s - estr;
766                                do ++s; while (s != end && *s == ' ');
767                        }
768                        else /* unquoted element */
769                        {
770                                estr = s;
771                                /* can contain blanks inside */
772                                while (s != end && *s != '"' &&
773                                        *s != '{' && *s != '}' && *s != delim)
774                                {
775                                        if (*s == '\\')
776                                        {
777                                                ++s; if (s == end) break;
778                                                escaped = 1;
779                                        }
780                                        ++s;
781                                }
782                                t = s; while (t > estr && *(t - 1) == ' ') --t;
783                                if (!(esize = t - estr))
784                                {
785                                        s = end; break; /* error */
786                                }
787                                if (STR_IS_NULL(estr, esize)) /* NULL gives None */
788                                        estr = NULL;
789                        }
790                        if (s == end) break; /* error */
791                        if (estr)
792                        {
793                                if (escaped)
794                                {
795                                        char       *r;
796                                        Py_ssize_t      i;
797
798                                        /* create unescaped string */
799                                        t = estr;
800                                        estr = (char *) PyMem_Malloc(esize);
801                                        if (!estr)
802                                        {
803                                                Py_DECREF(result); return PyErr_NoMemory();
804                                        }
805                                        for (i = 0, r = estr; i < esize; ++i)
806                                        {
807                                                if (*t == '\\') ++t, ++i;
808                                                *r++ = *t++;
809                                        }
810                                        esize = r - estr;
811                                }
812                                if (type) /* internal casting of base type */
813                                {
814                                        if (type & PYGRES_TEXT)
815                                                element = cast_sized_text(estr, esize, encoding, type);
816                                        else
817                                                element = cast_sized_simple(estr, esize, type);
818                                }
819                                else /* external casting of base type */
820                                {
821#if IS_PY3
822                                        element = encoding == pg_encoding_ascii ? NULL :
823                                                get_decoded_string(estr, esize, encoding);
824                                        if (!element) /* no decoding necessary or possible */
825#endif
826                                        element = PyBytes_FromStringAndSize(estr, esize);
827                                        if (element && cast)
828                                        {
829                                                PyObject *tmp = element;
830                                                element = PyObject_CallFunctionObjArgs(
831                                                        cast, element, NULL);
832                                                Py_DECREF(tmp);
833                                        }
834                                }
835                                if (escaped) PyMem_Free(estr);
836                                if (!element)
837                                {
838                                        Py_DECREF(result); return NULL;
839                                }
840                        }
841                        else
842                        {
843                                Py_INCREF(Py_None); element = Py_None;
844                        }
845                        if (PyList_Append(result, element))
846                        {
847                                Py_DECREF(element); Py_DECREF(result); return NULL;
848                        }
849                        Py_DECREF(element);
850                        if (*s == delim)
851                        {
852                                do ++s; while (s != end && *s == ' ');
853                                if (s == end) break; /* error */
854                        }
855                        else if (*s != '}') break; /* error */
856                }
857                else /* we expect arrays at this level */
858                {
859                        if (*s != '{')
860                        {
861                                PyErr_SetString(PyExc_ValueError,
862                                        "Subarray must start with a left brace");
863                                Py_DECREF(result); return NULL;
864                        }
865                        do ++s; while (s != end && *s == ' ');
866                        if (s == end) break; /* error */
867                        stack[level++] = result;
868                        if (!(result = PyList_New(0))) return NULL;
869                }
870        }
871        if (s == end || *s != '}')
872        {
873                PyErr_SetString(PyExc_ValueError,
874                        "Unexpected end of array");
875                Py_DECREF(result); return NULL;
876        }
877        do ++s; while (s != end && *s == ' ');
878        if (s != end)
879        {
880                PyErr_SetString(PyExc_ValueError,
881                        "Unexpected characters after end of array");
882                Py_DECREF(result); return NULL;
883        }
884        return result;
885}
886
887/* Cast string s with size and encoding to a Python tuple.
888   using the input and output syntax for composite types.
889   Use array of internal types or cast function or sequence of cast
890   functions to cast elements. The parameter len is the record size.
891   The parameter delim can specify a delimiter for the elements,
892   although composite types always use a comma as delimiter. */
893
894static PyObject *
895cast_record(char *s, Py_ssize_t size, int encoding,
896         int *type, PyObject *cast, Py_ssize_t len, char delim)
897{
898        PyObject   *result, *ret;
899        char       *end = s + size, *t;
900        Py_ssize_t      i;
901
902        if (!delim)
903                delim = ',';
904        else if (delim == '(' || delim ==')' || delim=='\\')
905        {
906                PyErr_SetString(PyExc_ValueError, "Invalid record delimiter");
907                return NULL;
908        }
909
910        /* strip blanks at the beginning */
911        while (s != end && *s == ' ') ++s;
912        if (s == end || *s != '(')
913        {
914                PyErr_SetString(PyExc_ValueError,
915                        "Record must start with a left parenthesis");
916                return NULL;
917        }
918        result = PyList_New(0);
919        if (!result) return NULL;
920        i = 0;
921        /* everything is set up, start parsing the record */
922        while (++s != end)
923        {
924                PyObject   *element;
925
926                if (*s == ')' || *s == delim)
927                {
928                        Py_INCREF(Py_None); element = Py_None;
929                }
930                else
931                {
932                        char       *estr;
933                        Py_ssize_t      esize;
934                        int quoted = 0, escaped =0;
935
936                        estr = s;
937                        quoted = *s == '"';
938                        if (quoted) ++s;
939                        esize = 0;
940                        while (s != end)
941                        {
942                                if (!quoted && (*s == ')' || *s == delim))
943                                        break;
944                                if (*s == '"')
945                                {
946                                        ++s; if (s == end) break;
947                                        if (!(quoted && *s == '"'))
948                                        {
949                                                quoted = !quoted; continue;
950                                        }
951                                }
952                                if (*s == '\\')
953                                {
954                                        ++s; if (s == end) break;
955                                }
956                                ++s, ++esize;
957                        }
958                        if (s == end) break; /* error */
959                        if (estr + esize != s)
960                        {
961                                char       *r;
962
963                                escaped = 1;
964                                /* create unescaped string */
965                                t = estr;
966                                estr = (char *) PyMem_Malloc(esize);
967                                if (!estr)
968                                {
969                                        Py_DECREF(result); return PyErr_NoMemory();
970                                }
971                                quoted = 0;
972                                r = estr;
973                                while (t != s)
974                                {
975                                        if (*t == '"')
976                                        {
977                                                ++t;
978                                                if (!(quoted && *t == '"'))
979                                                {
980                                                        quoted = !quoted; continue;
981                                                }
982                                        }
983                                        if (*t == '\\') ++t;
984                                        *r++ = *t++;
985                                }
986                        }
987                        if (type) /* internal casting of element type */
988                        {
989                                int etype = type[i];
990
991                                if (etype & PYGRES_ARRAY)
992                                        element = cast_array(
993                                                estr, esize, encoding, etype, NULL, 0);
994                                else if (etype & PYGRES_TEXT)
995                                        element = cast_sized_text(estr, esize, encoding, etype);
996                                else
997                                        element = cast_sized_simple(estr, esize, etype);
998                        }
999                        else /* external casting of base type */
1000                        {
1001#if IS_PY3
1002                                element = encoding == pg_encoding_ascii ? NULL :
1003                                        get_decoded_string(estr, esize, encoding);
1004                                if (!element) /* no decoding necessary or possible */
1005#endif
1006                                element = PyBytes_FromStringAndSize(estr, esize);
1007                                if (element && cast)
1008                                {
1009                                        if (len)
1010                                        {
1011                                                PyObject *ecast = PySequence_GetItem(cast, i);
1012
1013                                                if (ecast)
1014                                                {
1015                                                        if (ecast != Py_None)
1016                                                        {
1017                                                                PyObject *tmp = element;
1018                                                                element = PyObject_CallFunctionObjArgs(
1019                                                                        ecast, element, NULL);
1020                                                                Py_DECREF(tmp);
1021                                                        }
1022                                                }
1023                                                else
1024                                                {
1025                                                        Py_DECREF(element); element = NULL;
1026                                                }
1027                                        }
1028                                        else
1029                                        {
1030                                                PyObject *tmp = element;
1031                                                element = PyObject_CallFunctionObjArgs(
1032                                                        cast, element, NULL);
1033                                                Py_DECREF(tmp);
1034                                        }
1035                                }
1036                        }
1037                        if (escaped) PyMem_Free(estr);
1038                        if (!element)
1039                        {
1040                                Py_DECREF(result); return NULL;
1041                        }
1042                }
1043                if (PyList_Append(result, element))
1044                {
1045                        Py_DECREF(element); Py_DECREF(result); return NULL;
1046                }
1047                Py_DECREF(element);
1048                if (len) ++i;
1049                if (*s != delim) break; /* no next record */
1050                if (len && i >= len)
1051                {
1052                        PyErr_SetString(PyExc_ValueError, "Too many columns");
1053                        Py_DECREF(result); return NULL;
1054                }
1055        }
1056        if (s == end || *s != ')')
1057        {
1058                PyErr_SetString(PyExc_ValueError, "Unexpected end of record");
1059                Py_DECREF(result); return NULL;
1060        }
1061        do ++s; while (s != end && *s == ' ');
1062        if (s != end)
1063        {
1064                PyErr_SetString(PyExc_ValueError,
1065                        "Unexpected characters after end of record");
1066                Py_DECREF(result); return NULL;
1067        }
1068        if (len && i < len)
1069        {
1070                PyErr_SetString(PyExc_ValueError, "Too few columns");
1071                Py_DECREF(result); return NULL;
1072        }
1073
1074        ret = PyList_AsTuple(result);
1075        Py_DECREF(result);
1076        return ret;
1077}
1078
1079/* Cast string s with size and encoding to a Python dictionary.
1080   using the input and output syntax for hstore values. */
1081
1082static PyObject *
1083cast_hstore(char *s, Py_ssize_t size, int encoding)
1084{
1085        PyObject   *result;
1086        char       *end = s + size;
1087
1088    result = PyDict_New();
1089
1090        /* everything is set up, start parsing the record */
1091        while (s != end)
1092        {
1093                char       *key, *val;
1094                PyObject   *key_obj, *val_obj;
1095                Py_ssize_t      key_esc = 0, val_esc = 0, size;
1096                int                     quoted;
1097
1098                while (s != end && *s == ' ') ++s;
1099                if (s == end) break;
1100                quoted = *s == '"';
1101                if (quoted)
1102                {
1103                        key = ++s;
1104                        while (s != end)
1105                        {
1106                                if (*s == '"') break;
1107                                if (*s == '\\')
1108                                {
1109                                        if (++s == end) break;
1110                                        ++key_esc;
1111                                }
1112                                ++s;
1113                        }
1114                        if (s == end)
1115                        {
1116                                PyErr_SetString(PyExc_ValueError, "Unterminated quote");
1117                                Py_DECREF(result); return NULL;
1118                        }
1119                }
1120                else
1121                {
1122                        key = s;
1123                        while (s != end)
1124                        {
1125                                if (*s == '=' || *s == ' ') break;
1126                                if (*s == '\\')
1127                                {
1128                                        if (++s == end) break;
1129                                        ++key_esc;
1130                                }
1131                                ++s;
1132                        }
1133                        if (s == key)
1134                        {
1135                                PyErr_SetString(PyExc_ValueError, "Missing key");
1136                                Py_DECREF(result); return NULL;
1137                        }
1138                }
1139                size = s - key - key_esc;
1140                if (key_esc)
1141                {
1142                        char *r = key, *t;
1143                        key = (char *) PyMem_Malloc(size);
1144                        if (!key)
1145                        {
1146                                Py_DECREF(result); return PyErr_NoMemory();
1147                        }
1148                        t = key;
1149                        while (r != s)
1150                        {
1151                                if (*r == '\\')
1152                                {
1153                                        ++r; if (r == s) break;
1154                                }
1155                                *t++ = *r++;
1156                        }
1157                }
1158                key_obj = cast_sized_text(key, size, encoding, PYGRES_TEXT);
1159                if (key_esc) PyMem_Free(key);
1160                if (!key_obj)
1161                {
1162                        Py_DECREF(result); return NULL;
1163                }
1164                if (quoted) ++s;
1165                while (s != end && *s == ' ') ++s;
1166                if (s == end || *s++ != '=' || s == end || *s++ != '>')
1167                {
1168                        PyErr_SetString(PyExc_ValueError, "Invalid characters after key");
1169                        Py_DECREF(key_obj); Py_DECREF(result); return NULL;
1170                }
1171                while (s != end && *s == ' ') ++s;
1172                quoted = *s == '"';
1173                if (quoted)
1174                {
1175                        val = ++s;
1176                        while (s != end)
1177                        {
1178                                if (*s == '"') break;
1179                                if (*s == '\\')
1180                                {
1181                                        if (++s == end) break;
1182                                        ++val_esc;
1183                                }
1184                                ++s;
1185                        }
1186                        if (s == end)
1187                        {
1188                                PyErr_SetString(PyExc_ValueError, "Unterminated quote");
1189                                Py_DECREF(result); return NULL;
1190                        }
1191                }
1192                else
1193                {
1194                        val = s;
1195                        while (s != end)
1196                        {
1197                                if (*s == ',' || *s == ' ') break;
1198                                if (*s == '\\')
1199                                {
1200                                        if (++s == end) break;
1201                                        ++val_esc;
1202                                }
1203                                ++s;
1204                        }
1205                        if (s == val)
1206                        {
1207                                PyErr_SetString(PyExc_ValueError, "Missing value");
1208                                Py_DECREF(key_obj); Py_DECREF(result); return NULL;
1209                        }
1210                        if (STR_IS_NULL(val, s - val))
1211                                val = NULL;
1212                }
1213                if (val)
1214                {
1215                        size = s - val - val_esc;
1216                        if (val_esc)
1217                        {
1218                                char *r = val, *t;
1219                                val = (char *) PyMem_Malloc(size);
1220                                if (!val)
1221                                {
1222                                        Py_DECREF(key_obj); Py_DECREF(result);
1223                                        return PyErr_NoMemory();
1224                                }
1225                                t = val;
1226                                while (r != s)
1227                                {
1228                                        if (*r == '\\')
1229                                        {
1230                                                ++r; if (r == s) break;
1231                                        }
1232                                        *t++ = *r++;
1233                                }
1234                        }
1235                        val_obj = cast_sized_text(val, size, encoding, PYGRES_TEXT);
1236                        if (val_esc) PyMem_Free(val);
1237                        if (!val_obj)
1238                        {
1239                                Py_DECREF(key_obj); Py_DECREF(result); return NULL;
1240                        }
1241                }
1242                else
1243                {
1244                        Py_INCREF(Py_None); val_obj = Py_None;
1245                }
1246                if (quoted) ++s;
1247                while (s != end && *s == ' ') ++s;
1248                if (s != end)
1249                {
1250                        if (*s++ != ',')
1251                        {
1252                                PyErr_SetString(PyExc_ValueError,
1253                                        "Invalid characters after val");
1254                                Py_DECREF(key_obj); Py_DECREF(val_obj);
1255                                Py_DECREF(result); return NULL;
1256                        }
1257                        while (s != end && *s == ' ') ++s;
1258                        if (s == end)
1259                        {
1260                                PyErr_SetString(PyExc_ValueError, "Missing entry");
1261                                Py_DECREF(key_obj); Py_DECREF(val_obj);
1262                                Py_DECREF(result); return NULL;
1263                        }
1264                }
1265                PyDict_SetItem(result, key_obj, val_obj);
1266                Py_DECREF(key_obj); Py_DECREF(val_obj);
1267        }
1268        return result;
1269}
1270
1271/* internal wrapper for the notice receiver callback */
1272static void
1273notice_receiver(void *arg, const PGresult *res)
1274{
1275        PyGILState_STATE gstate = PyGILState_Ensure();
1276        connObject *self = (connObject*) arg;
1277        PyObject *func = self->notice_receiver;
1278
1279        if (func)
1280        {
1281                noticeObject *notice = PyObject_NEW(noticeObject, &noticeType);
1282                PyObject *ret;
1283                if (notice)
1284                {
1285                        notice->pgcnx = arg;
1286                        notice->res = res;
1287                }
1288                else
1289                {
1290                        Py_INCREF(Py_None);
1291                        notice = (noticeObject *)(void *)Py_None;
1292                }
1293                ret = PyObject_CallFunction(func, "(O)", notice);
1294                Py_XDECREF(ret);
1295        }
1296        PyGILState_Release(gstate);
1297}
1298
1299/* gets appropriate error type from sqlstate */
1300static PyObject *
1301get_error_type(const char *sqlstate)
1302{
1303        switch (sqlstate[0]) {
1304                case '0':
1305                        switch (sqlstate[1])
1306                        {
1307                                case 'A':
1308                                        return NotSupportedError;
1309                        }
1310                        break;
1311                case '2':
1312                        switch (sqlstate[1])
1313                        {
1314                                case '0':
1315                                case '1':
1316                                        return ProgrammingError;
1317                                case '2':
1318                                        return DataError;
1319                                case '3':
1320                                        return IntegrityError;
1321                                case '4':
1322                                case '5':
1323                                        return InternalError;
1324                                case '6':
1325                                case '7':
1326                                case '8':
1327                                        return OperationalError;
1328                                case 'B':
1329                                case 'D':
1330                                case 'F':
1331                                        return InternalError;
1332                        }
1333                        break;
1334                case '3':
1335                        switch (sqlstate[1])
1336                        {
1337                                case '4':
1338                                        return OperationalError;
1339                                case '8':
1340                                case '9':
1341                                case 'B':
1342                                        return InternalError;
1343                                case 'D':
1344                                case 'F':
1345                                        return ProgrammingError;
1346                        }
1347                        break;
1348                case '4':
1349                        switch (sqlstate[1])
1350                        {
1351                                case '0':
1352                                        return OperationalError;
1353                                case '2':
1354                                case '4':
1355                                        return ProgrammingError;
1356                        }
1357                        break;
1358                case '5':
1359                case 'H':
1360                        return OperationalError;
1361                case 'F':
1362                case 'P':
1363                case 'X':
1364                        return InternalError;
1365        }
1366        return DatabaseError;
1367}
1368
1369/* sets database error message and sqlstate attribute */
1370static void
1371set_error_msg_and_state(PyObject *type,
1372        const char *msg, int encoding, const char *sqlstate)
1373{
1374        PyObject   *err_obj, *msg_obj, *sql_obj = NULL;
1375
1376#if IS_PY3
1377        if (encoding == -1) /* unknown */
1378        {
1379                msg_obj = PyUnicode_DecodeLocale(msg, NULL);
1380        }
1381        else
1382                msg_obj = get_decoded_string(msg, strlen(msg), encoding);
1383        if (!msg_obj) /* cannot decode */
1384#endif
1385        msg_obj = PyBytes_FromString(msg);
1386
1387        if (sqlstate)
1388                sql_obj = PyStr_FromStringAndSize(sqlstate, 5);
1389        else
1390        {
1391                Py_INCREF(Py_None); sql_obj = Py_None;
1392        }
1393
1394        err_obj = PyObject_CallFunctionObjArgs(type, msg_obj, NULL);
1395        if (err_obj)
1396        {
1397                Py_DECREF(msg_obj);
1398                PyObject_SetAttrString(err_obj, "sqlstate", sql_obj);
1399                Py_DECREF(sql_obj);
1400                PyErr_SetObject(type, err_obj);
1401                Py_DECREF(err_obj);
1402        }
1403        else
1404        {
1405                PyErr_SetString(type, msg);
1406        }
1407}
1408
1409/* sets given database error message */
1410static void
1411set_error_msg(PyObject *type, const char *msg)
1412{
1413        set_error_msg_and_state(type, msg, pg_encoding_ascii, NULL);
1414}
1415
1416/* sets database error from connection and/or result */
1417static void
1418set_error(PyObject *type, const char * msg, PGconn *cnx, PGresult *result)
1419{
1420        char *sqlstate = NULL; int encoding = pg_encoding_ascii;
1421
1422        if (cnx)
1423        {
1424                char *err_msg = PQerrorMessage(cnx);
1425                if (err_msg)
1426                {
1427                        msg = err_msg;
1428                        encoding = PQclientEncoding(cnx);
1429                }
1430        }
1431        if (result)
1432        {
1433                sqlstate = PQresultErrorField(result, PG_DIAG_SQLSTATE);
1434                if (sqlstate) type = get_error_type(sqlstate);
1435        }
1436
1437        set_error_msg_and_state(type, msg, encoding, sqlstate);
1438}
1439
1440/* checks connection validity */
1441static int
1442check_cnx_obj(connObject *self)
1443{
1444        if (!self || !self->valid || !self->cnx)
1445        {
1446                set_error_msg(OperationalError, "Connection has been closed");
1447                return 0;
1448        }
1449        return 1;
1450}
1451
1452/* format result (mostly useful for debugging) */
1453/* Note: This is similar to the Postgres function PQprint().
1454 * PQprint() is not used because handing over a stream from Python to
1455 * Postgres can be problematic if they use different libs for streams
1456 * and because using PQprint() and tp_print is not recommended any more.
1457 */
1458static PyObject *
1459format_result(const PGresult *res)
1460{
1461        const int n = PQnfields(res);
1462
1463        if (n > 0)
1464        {
1465                char * const aligns = (char *) PyMem_Malloc(n * sizeof(char));
1466                int * const sizes = (int *) PyMem_Malloc(n * sizeof(int));
1467
1468                if (aligns && sizes)
1469                {
1470                        const int m = PQntuples(res);
1471                        int i, j;
1472                        size_t size;
1473                        char *buffer;
1474
1475                        /* calculate sizes and alignments */
1476                        for (j = 0; j < n; ++j)
1477                        {
1478                                const char * const s = PQfname(res, j);
1479                                const int format = PQfformat(res, j);
1480
1481                                sizes[j] = s ? (int)strlen(s) : 0;
1482                                if (format)
1483                                {
1484                                        aligns[j] = '\0';
1485                                        if (m && sizes[j] < 8)
1486                                                /* "<binary>" must fit */
1487                                                sizes[j] = 8;
1488                                }
1489                                else
1490                                {
1491                                        const Oid ftype = PQftype(res, j);
1492
1493                                        switch (ftype)
1494                                        {
1495                                                case INT2OID:
1496                                                case INT4OID:
1497                                                case INT8OID:
1498                                                case FLOAT4OID:
1499                                                case FLOAT8OID:
1500                                                case NUMERICOID:
1501                                                case OIDOID:
1502                                                case XIDOID:
1503                                                case CIDOID:
1504                                                case CASHOID:
1505                                                        aligns[j] = 'r';
1506                                                        break;
1507                                                default:
1508                                                        aligns[j] = 'l';
1509                                        }
1510                                }
1511                        }
1512                        for (i = 0; i < m; ++i)
1513                        {
1514                                for (j = 0; j < n; ++j)
1515                                {
1516                                        if (aligns[j])
1517                                        {
1518                                                const int k = PQgetlength(res, i, j);
1519
1520                                                if (sizes[j] < k)
1521                                                        /* value must fit */
1522                                                        sizes[j] = k;
1523                                        }
1524                                }
1525                        }
1526                        size = 0;
1527                        /* size of one row */
1528                        for (j = 0; j < n; ++j) size += sizes[j] + 1;
1529                        /* times number of rows incl. heading */
1530                        size *= (m + 2);
1531                        /* plus size of footer */
1532                        size += 40;
1533                        /* is the buffer size that needs to be allocated */
1534                        buffer = (char *) PyMem_Malloc(size);
1535                        if (buffer)
1536                        {
1537                                char *p = buffer;
1538                                PyObject *result;
1539
1540                                /* create the header */
1541                                for (j = 0; j < n; ++j)
1542                                {
1543                                        const char * const s = PQfname(res, j);
1544                                        const int k = sizes[j];
1545                                        const int h = (k - (int)strlen(s)) / 2;
1546
1547                                        sprintf(p, "%*s", h, "");
1548                                        sprintf(p + h, "%-*s", k - h, s);
1549                                        p += k;
1550                                        if (j + 1 < n)
1551                                                *p++ = '|';
1552                                }
1553                                *p++ = '\n';
1554                                for (j = 0; j < n; ++j)
1555                                {
1556                                        int k = sizes[j];
1557
1558                                        while (k--)
1559                                                *p++ = '-';
1560                                        if (j + 1 < n)
1561                                                *p++ = '+';
1562                                }
1563                                *p++ = '\n';
1564                                /* create the body */
1565                                for (i = 0; i < m; ++i)
1566                                {
1567                                        for (j = 0; j < n; ++j)
1568                                        {
1569                                                const char align = aligns[j];
1570                                                const int k = sizes[j];
1571
1572                                                if (align)
1573                                                {
1574                                                        sprintf(p, align == 'r' ?
1575                                                                "%*s" : "%-*s", k,
1576                                                                PQgetvalue(res, i, j));
1577                                                }
1578                                                else
1579                                                {
1580                                                        sprintf(p, "%-*s", k,
1581                                                                PQgetisnull(res, i, j) ?
1582                                                                "" : "<binary>");
1583                                                }
1584                                                p += k;
1585                                                if (j + 1 < n)
1586                                                        *p++ = '|';
1587                                        }
1588                                        *p++ = '\n';
1589                                }
1590                                /* free memory */
1591                                PyMem_Free(aligns); PyMem_Free(sizes);
1592                                /* create the footer */
1593                                sprintf(p, "(%d row%s)", m, m == 1 ? "" : "s");
1594                                /* return the result */
1595                                result = PyStr_FromString(buffer);
1596                                PyMem_Free(buffer);
1597                                return result;
1598                        }
1599                        else
1600                        {
1601                                PyMem_Free(aligns); PyMem_Free(sizes); return PyErr_NoMemory();
1602                        }
1603                }
1604                else
1605                {
1606                        PyMem_Free(aligns); PyMem_Free(sizes); return PyErr_NoMemory();
1607                }
1608        }
1609        else
1610                return PyStr_FromString("(nothing selected)");
1611}
1612
1613/* --------------------------------------------------------------------- */
1614/* large objects                                                                                                                 */
1615/* --------------------------------------------------------------------- */
1616#ifdef LARGE_OBJECTS
1617
1618/* checks large object validity */
1619static int
1620check_lo_obj(largeObject *self, int level)
1621{
1622        if (!check_cnx_obj(self->pgcnx))
1623                return 0;
1624
1625        if (!self->lo_oid)
1626        {
1627                set_error_msg(IntegrityError, "Object is not valid (null oid)");
1628                return 0;
1629        }
1630
1631        if (level & CHECK_OPEN)
1632        {
1633                if (self->lo_fd < 0)
1634                {
1635                        PyErr_SetString(PyExc_IOError, "Object is not opened");
1636                        return 0;
1637                }
1638        }
1639
1640        if (level & CHECK_CLOSE)
1641        {
1642                if (self->lo_fd >= 0)
1643                {
1644                        PyErr_SetString(PyExc_IOError, "Object is already opened");
1645                        return 0;
1646                }
1647        }
1648
1649        return 1;
1650}
1651
1652/* constructor (internal use only) */
1653static largeObject *
1654largeNew(connObject *pgcnx, Oid oid)
1655{
1656        largeObject *npglo;
1657
1658        if (!(npglo = PyObject_NEW(largeObject, &largeType)))
1659                return NULL;
1660
1661        Py_XINCREF(pgcnx);
1662        npglo->pgcnx = pgcnx;
1663        npglo->lo_fd = -1;
1664        npglo->lo_oid = oid;
1665
1666        return npglo;
1667}
1668
1669/* destructor */
1670static void
1671largeDealloc(largeObject *self)
1672{
1673        if (self->lo_fd >= 0 && self->pgcnx->valid)
1674                lo_close(self->pgcnx->cnx, self->lo_fd);
1675
1676        Py_XDECREF(self->pgcnx);
1677        PyObject_Del(self);
1678}
1679
1680/* opens large object */
1681static char largeOpen__doc__[] =
1682"open(mode) -- open access to large object with specified mode\n\n"
1683"The mode must be one of INV_READ, INV_WRITE (module level constants).\n";
1684
1685static PyObject *
1686largeOpen(largeObject *self, PyObject *args)
1687{
1688        int                     mode,
1689                                fd;
1690
1691        /* gets arguments */
1692        if (!PyArg_ParseTuple(args, "i", &mode))
1693        {
1694                PyErr_SetString(PyExc_TypeError,
1695                        "The open() method takes an integer argument");
1696                return NULL;
1697        }
1698
1699        /* check validity */
1700        if (!check_lo_obj(self, CHECK_CLOSE))
1701                return NULL;
1702
1703        /* opens large object */
1704        if ((fd = lo_open(self->pgcnx->cnx, self->lo_oid, mode)) == -1)
1705        {
1706                PyErr_SetString(PyExc_IOError, "Can't open large object");
1707                return NULL;
1708        }
1709        self->lo_fd = fd;
1710
1711        /* no error : returns Py_None */
1712        Py_INCREF(Py_None);
1713        return Py_None;
1714}
1715
1716/* close large object */
1717static char largeClose__doc__[] =
1718"close() -- close access to large object data";
1719
1720static PyObject *
1721largeClose(largeObject *self, PyObject *noargs)
1722{
1723        /* checks validity */
1724        if (!check_lo_obj(self, CHECK_OPEN))
1725                return NULL;
1726
1727        /* closes large object */
1728        if (lo_close(self->pgcnx->cnx, self->lo_fd))
1729        {
1730                PyErr_SetString(PyExc_IOError, "Error while closing large object fd");
1731                return NULL;
1732        }
1733        self->lo_fd = -1;
1734
1735        /* no error : returns Py_None */
1736        Py_INCREF(Py_None);
1737        return Py_None;
1738}
1739
1740/* reads from large object */
1741static char largeRead__doc__[] =
1742"read(size) -- read from large object to sized string\n\n"
1743"Object must be opened in read mode before calling this method.\n";
1744
1745static PyObject *
1746largeRead(largeObject *self, PyObject *args)
1747{
1748        int                     size;
1749        PyObject   *buffer;
1750
1751        /* gets arguments */
1752        if (!PyArg_ParseTuple(args, "i", &size))
1753        {
1754                PyErr_SetString(PyExc_TypeError,
1755                        "Method read() takes an integer argument");
1756                return NULL;
1757        }
1758
1759        if (size <= 0)
1760        {
1761                PyErr_SetString(PyExc_ValueError,
1762                        "Method read() takes a positive integer as argument");
1763                return NULL;
1764        }
1765
1766        /* checks validity */
1767        if (!check_lo_obj(self, CHECK_OPEN))
1768                return NULL;
1769
1770        /* allocate buffer and runs read */
1771        buffer = PyBytes_FromStringAndSize((char *) NULL, size);
1772
1773        if ((size = lo_read(self->pgcnx->cnx, self->lo_fd,
1774                PyBytes_AS_STRING((PyBytesObject *)(buffer)), size)) == -1)
1775        {
1776                PyErr_SetString(PyExc_IOError, "Error while reading");
1777                Py_XDECREF(buffer);
1778                return NULL;
1779        }
1780
1781        /* resize buffer and returns it */
1782        _PyBytes_Resize(&buffer, size);
1783        return buffer;
1784}
1785
1786/* write to large object */
1787static char largeWrite__doc__[] =
1788"write(string) -- write sized string to large object\n\n"
1789"Object must be opened in read mode before calling this method.\n";
1790
1791static PyObject *
1792largeWrite(largeObject *self, PyObject *args)
1793{
1794        char       *buffer;
1795        int                     size,
1796                                bufsize;
1797
1798        /* gets arguments */
1799        if (!PyArg_ParseTuple(args, "s#", &buffer, &bufsize))
1800        {
1801                PyErr_SetString(PyExc_TypeError,
1802                        "Method write() expects a sized string as argument");
1803                return NULL;
1804        }
1805
1806        /* checks validity */
1807        if (!check_lo_obj(self, CHECK_OPEN))
1808                return NULL;
1809
1810        /* sends query */
1811        if ((size = lo_write(self->pgcnx->cnx, self->lo_fd, buffer,
1812                                                 bufsize)) != bufsize)
1813        {
1814                PyErr_SetString(PyExc_IOError, "Buffer truncated during write");
1815                return NULL;
1816        }
1817
1818        /* no error : returns Py_None */
1819        Py_INCREF(Py_None);
1820        return Py_None;
1821}
1822
1823/* go to position in large object */
1824static char largeSeek__doc__[] =
1825"seek(offset, whence) -- move to specified position\n\n"
1826"Object must be opened before calling this method. The whence option\n"
1827"can be SEEK_SET, SEEK_CUR or SEEK_END (module level constants).\n";
1828
1829static PyObject *
1830largeSeek(largeObject *self, PyObject *args)
1831{
1832        /* offset and whence are initialized to keep compiler happy */
1833        int                     ret,
1834                                offset = 0,
1835                                whence = 0;
1836
1837        /* gets arguments */
1838        if (!PyArg_ParseTuple(args, "ii", &offset, &whence))
1839        {
1840                PyErr_SetString(PyExc_TypeError,
1841                        "Method lseek() expects two integer arguments");
1842                return NULL;
1843        }
1844
1845        /* checks validity */
1846        if (!check_lo_obj(self, CHECK_OPEN))
1847                return NULL;
1848
1849        /* sends query */
1850        if ((ret = lo_lseek(self->pgcnx->cnx, self->lo_fd, offset, whence)) == -1)
1851        {
1852                PyErr_SetString(PyExc_IOError, "Error while moving cursor");
1853                return NULL;
1854        }
1855
1856        /* returns position */
1857        return PyInt_FromLong(ret);
1858}
1859
1860/* gets large object size */
1861static char largeSize__doc__[] =
1862"size() -- return large object size\n\n"
1863"The object must be opened before calling this method.\n";
1864
1865static PyObject *
1866largeSize(largeObject *self, PyObject *noargs)
1867{
1868        int                     start,
1869                                end;
1870
1871        /* checks validity */
1872        if (!check_lo_obj(self, CHECK_OPEN))
1873                return NULL;
1874
1875        /* gets current position */
1876        if ((start = lo_tell(self->pgcnx->cnx, self->lo_fd)) == -1)
1877        {
1878                PyErr_SetString(PyExc_IOError, "Error while getting current position");
1879                return NULL;
1880        }
1881
1882        /* gets end position */
1883        if ((end = lo_lseek(self->pgcnx->cnx, self->lo_fd, 0, SEEK_END)) == -1)
1884        {
1885                PyErr_SetString(PyExc_IOError, "Error while getting end position");
1886                return NULL;
1887        }
1888
1889        /* move back to start position */
1890        if ((start = lo_lseek(
1891                self->pgcnx->cnx, self->lo_fd, start, SEEK_SET)) == -1)
1892        {
1893                PyErr_SetString(PyExc_IOError,
1894                        "Error while moving back to first position");
1895                return NULL;
1896        }
1897
1898        /* returns size */
1899        return PyInt_FromLong(end);
1900}
1901
1902/* gets large object cursor position */
1903static char largeTell__doc__[] =
1904"tell() -- give current position in large object\n\n"
1905"The object must be opened before calling this method.\n";
1906
1907static PyObject *
1908largeTell(largeObject *self, PyObject *noargs)
1909{
1910        int                     start;
1911
1912        /* checks validity */
1913        if (!check_lo_obj(self, CHECK_OPEN))
1914                return NULL;
1915
1916        /* gets current position */
1917        if ((start = lo_tell(self->pgcnx->cnx, self->lo_fd)) == -1)
1918        {
1919                PyErr_SetString(PyExc_IOError, "Error while getting position");
1920                return NULL;
1921        }
1922
1923        /* returns size */
1924        return PyInt_FromLong(start);
1925}
1926
1927/* exports large object as unix file */
1928static char largeExport__doc__[] =
1929"export(filename) -- export large object data to specified file\n\n"
1930"The object must be closed when calling this method.\n";
1931
1932static PyObject *
1933largeExport(largeObject *self, PyObject *args)
1934{
1935        char *name;
1936
1937        /* checks validity */
1938        if (!check_lo_obj(self, CHECK_CLOSE))
1939                return NULL;
1940
1941        /* gets arguments */
1942        if (!PyArg_ParseTuple(args, "s", &name))
1943        {
1944                PyErr_SetString(PyExc_TypeError,
1945                        "The method export() takes a filename as argument");
1946                return NULL;
1947        }
1948
1949        /* runs command */
1950        if (lo_export(self->pgcnx->cnx, self->lo_oid, name) != 1)
1951        {
1952                PyErr_SetString(PyExc_IOError, "Error while exporting large object");
1953                return NULL;
1954        }
1955
1956        Py_INCREF(Py_None);
1957        return Py_None;
1958}
1959
1960/* deletes a large object */
1961static char largeUnlink__doc__[] =
1962"unlink() -- destroy large object\n\n"
1963"The object must be closed when calling this method.\n";
1964
1965static PyObject *
1966largeUnlink(largeObject *self, PyObject *noargs)
1967{
1968        /* checks validity */
1969        if (!check_lo_obj(self, CHECK_CLOSE))
1970                return NULL;
1971
1972        /* deletes the object, invalidate it on success */
1973        if (lo_unlink(self->pgcnx->cnx, self->lo_oid) != 1)
1974        {
1975                PyErr_SetString(PyExc_IOError, "Error while unlinking large object");
1976                return NULL;
1977        }
1978        self->lo_oid = 0;
1979
1980        Py_INCREF(Py_None);
1981        return Py_None;
1982}
1983
1984/* get the list of large object attributes */
1985static PyObject *
1986largeDir(largeObject *self, PyObject *noargs)
1987{
1988        PyObject *attrs;
1989
1990        attrs = PyObject_Dir(PyObject_Type((PyObject *)self));
1991        PyObject_CallMethod(attrs, "extend", "[sss]",
1992                "oid", "pgcnx", "error");
1993
1994        return attrs;
1995}
1996
1997/* large object methods */
1998static struct PyMethodDef largeMethods[] = {
1999        {"__dir__", (PyCFunction) largeDir,  METH_NOARGS, NULL},
2000        {"open", (PyCFunction) largeOpen, METH_VARARGS, largeOpen__doc__},
2001        {"close", (PyCFunction) largeClose, METH_NOARGS, largeClose__doc__},
2002        {"read", (PyCFunction) largeRead, METH_VARARGS, largeRead__doc__},
2003        {"write", (PyCFunction) largeWrite, METH_VARARGS, largeWrite__doc__},
2004        {"seek", (PyCFunction) largeSeek, METH_VARARGS, largeSeek__doc__},
2005        {"size", (PyCFunction) largeSize, METH_NOARGS, largeSize__doc__},
2006        {"tell", (PyCFunction) largeTell, METH_NOARGS, largeTell__doc__},
2007        {"export",(PyCFunction) largeExport, METH_VARARGS, largeExport__doc__},
2008        {"unlink",(PyCFunction) largeUnlink, METH_NOARGS, largeUnlink__doc__},
2009        {NULL, NULL}
2010};
2011
2012/* gets large object attributes */
2013static PyObject *
2014largeGetAttr(largeObject *self, PyObject *nameobj)
2015{
2016        const char *name = PyStr_AsString(nameobj);
2017
2018        /* list postgreSQL large object fields */
2019
2020        /* associated pg connection object */
2021        if (!strcmp(name, "pgcnx"))
2022        {
2023                if (check_lo_obj(self, 0))
2024                {
2025                        Py_INCREF(self->pgcnx);
2026                        return (PyObject *) (self->pgcnx);
2027                }
2028                PyErr_Clear();
2029                Py_INCREF(Py_None);
2030                return Py_None;
2031        }
2032
2033        /* large object oid */
2034        if (!strcmp(name, "oid"))
2035        {
2036                if (check_lo_obj(self, 0))
2037                        return PyInt_FromLong(self->lo_oid);
2038                PyErr_Clear();
2039                Py_INCREF(Py_None);
2040                return Py_None;
2041        }
2042
2043        /* error (status) message */
2044        if (!strcmp(name, "error"))
2045                return PyStr_FromString(PQerrorMessage(self->pgcnx->cnx));
2046
2047        /* seeks name in methods (fallback) */
2048        return PyObject_GenericGetAttr((PyObject *) self, nameobj);
2049}
2050
2051/* return large object as string in human readable form */
2052static PyObject *
2053largeStr(largeObject *self)
2054{
2055        char            str[80];
2056        sprintf(str, self->lo_fd >= 0 ?
2057                        "Opened large object, oid %ld" :
2058                        "Closed large object, oid %ld", (long) self->lo_oid);
2059        return PyStr_FromString(str);
2060}
2061
2062static char large__doc__[] = "PostgreSQL large object";
2063
2064/* large object type definition */
2065static PyTypeObject largeType = {
2066        PyVarObject_HEAD_INIT(NULL, 0)
2067        "pg.LargeObject",                               /* tp_name */
2068        sizeof(largeObject),                    /* tp_basicsize */
2069        0,                                                              /* tp_itemsize */
2070
2071        /* methods */
2072        (destructor) largeDealloc,              /* tp_dealloc */
2073        0,                                                              /* tp_print */
2074        0,                                                              /* tp_getattr */
2075        0,                                                              /* tp_setattr */
2076        0,                                                              /* tp_compare */
2077        0,                                                              /* tp_repr */
2078        0,                                                              /* tp_as_number */
2079        0,                                                              /* tp_as_sequence */
2080        0,                                                              /* tp_as_mapping */
2081        0,                                                              /* tp_hash */
2082        0,                                                              /* tp_call */
2083        (reprfunc) largeStr,                    /* tp_str */
2084        (getattrofunc) largeGetAttr,    /* tp_getattro */
2085        0,                                                              /* tp_setattro */
2086        0,                                                              /* tp_as_buffer */
2087        Py_TPFLAGS_DEFAULT,                             /* tp_flags */
2088        large__doc__,                                   /* tp_doc */
2089        0,                                                              /* tp_traverse */
2090        0,                                                              /* tp_clear */
2091        0,                                                              /* tp_richcompare */
2092        0,                                                              /* tp_weaklistoffset */
2093        0,                                                              /* tp_iter */
2094        0,                                                              /* tp_iternext */
2095        largeMethods,                                   /* tp_methods */
2096};
2097#endif /* LARGE_OBJECTS */
2098
2099/* --------------------------------------------------------------------- */
2100/* connection object                                                                                                     */
2101/* --------------------------------------------------------------------- */
2102static void
2103connDelete(connObject *self)
2104{
2105        if (self->cnx)
2106        {
2107                Py_BEGIN_ALLOW_THREADS
2108                PQfinish(self->cnx);
2109                Py_END_ALLOW_THREADS
2110        }
2111        Py_XDECREF(self->cast_hook);
2112        Py_XDECREF(self->notice_receiver);
2113        PyObject_Del(self);
2114}
2115
2116/* source creation */
2117static char connSource__doc__[] =
2118"source() -- create a new source object for this connection";
2119
2120static PyObject *
2121connSource(connObject *self, PyObject *noargs)
2122{
2123        sourceObject *npgobj;
2124
2125        /* checks validity */
2126        if (!check_cnx_obj(self))
2127                return NULL;
2128
2129        /* allocates new query object */
2130        if (!(npgobj = PyObject_NEW(sourceObject, &sourceType)))
2131                return NULL;
2132
2133        /* initializes internal parameters */
2134        Py_XINCREF(self);
2135        npgobj->pgcnx = self;
2136        npgobj->result = NULL;
2137        npgobj->valid = 1;
2138        npgobj->arraysize = PG_ARRAYSIZE;
2139
2140        return (PyObject *) npgobj;
2141}
2142
2143/* database query */
2144static char connQuery__doc__[] =
2145"query(sql, [arg]) -- create a new query object for this connection\n\n"
2146"You must pass the SQL (string) request and you can optionally pass\n"
2147"a tuple with positional parameters.\n";
2148
2149static PyObject *
2150connQuery(connObject *self, PyObject *args)
2151{
2152        PyObject        *query_obj;
2153        PyObject        *param_obj = NULL;
2154        char            *query;
2155        PGresult        *result;
2156        queryObject *npgobj;
2157        int                     encoding,
2158                                status,
2159                                nparms = 0;
2160
2161        if (!self->cnx)
2162        {
2163                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2164                return NULL;
2165        }
2166
2167        /* get query args */
2168        if (!PyArg_ParseTuple(args, "O|O", &query_obj, &param_obj))
2169        {
2170                return NULL;
2171        }
2172
2173        encoding = PQclientEncoding(self->cnx);
2174
2175        if (PyBytes_Check(query_obj))
2176        {
2177                query = PyBytes_AsString(query_obj);
2178                query_obj = NULL;
2179        }
2180        else if (PyUnicode_Check(query_obj))
2181        {
2182                query_obj = get_encoded_string(query_obj, encoding);
2183                if (!query_obj) return NULL; /* pass the UnicodeEncodeError */
2184                query = PyBytes_AsString(query_obj);
2185        }
2186        else
2187        {
2188                PyErr_SetString(PyExc_TypeError,
2189                        "Method query() expects a string as first argument");
2190                return NULL;
2191        }
2192
2193        /* If param_obj is passed, ensure it's a non-empty tuple. We want to treat
2194         * an empty tuple the same as no argument since we'll get that when the
2195         * caller passes no arguments to db.query(), and historic behaviour was
2196         * to call PQexec() in that case, which can execute multiple commands. */
2197        if (param_obj)
2198        {
2199                param_obj = PySequence_Fast(param_obj,
2200                        "Method query() expects a sequence as second argument");
2201                if (!param_obj)
2202                {
2203                        Py_XDECREF(query_obj);
2204                        return NULL;
2205                }
2206                nparms = (int)PySequence_Fast_GET_SIZE(param_obj);
2207
2208                /* if there's a single argument and it's a list or tuple, it
2209                 * contains the positional arguments. */
2210                if (nparms == 1)
2211                {
2212                        PyObject *first_obj = PySequence_Fast_GET_ITEM(param_obj, 0);
2213                        if (PyList_Check(first_obj) || PyTuple_Check(first_obj))
2214                        {
2215                                Py_DECREF(param_obj);
2216                                param_obj = PySequence_Fast(first_obj, NULL);
2217                                nparms = (int)PySequence_Fast_GET_SIZE(param_obj);
2218                        }
2219                }
2220        }
2221
2222        /* gets result */
2223        if (nparms)
2224        {
2225                /* prepare arguments */
2226                PyObject        **str, **s;
2227                const char      **parms, **p;
2228                register int i;
2229
2230                str = (PyObject **)PyMem_Malloc(nparms * sizeof(*str));
2231                parms = (const char **)PyMem_Malloc(nparms * sizeof(*parms));
2232                if (!str || !parms)
2233                {
2234                        PyMem_Free((void *)parms); PyMem_Free(str);
2235                        Py_XDECREF(query_obj); Py_XDECREF(param_obj);
2236                        return PyErr_NoMemory();
2237                }
2238
2239                /* convert optional args to a list of strings -- this allows
2240                 * the caller to pass whatever they like, and prevents us
2241                 * from having to map types to OIDs */
2242                for (i = 0, s=str, p=parms; i < nparms; ++i, ++p)
2243                {
2244                        PyObject *obj = PySequence_Fast_GET_ITEM(param_obj, i);
2245
2246                        if (obj == Py_None)
2247                        {
2248                                *p = NULL;
2249                        }
2250                        else if (PyBytes_Check(obj))
2251                        {
2252                                *p = PyBytes_AsString(obj);
2253                        }
2254                        else if (PyUnicode_Check(obj))
2255                        {
2256                                PyObject *str_obj = get_encoded_string(obj, encoding);
2257                                if (!str_obj)
2258                                {
2259                                        PyMem_Free((void *)parms);
2260                                        while (s != str) { s--; Py_DECREF(*s); }
2261                                        PyMem_Free(str);
2262                                        Py_XDECREF(query_obj);
2263                                        Py_XDECREF(param_obj);
2264                                        /* pass the UnicodeEncodeError */
2265                                        return NULL;
2266                                }
2267                                *s++ = str_obj;
2268                                *p = PyBytes_AsString(str_obj);
2269                        }
2270                        else
2271                        {
2272                                PyObject *str_obj = PyObject_Str(obj);
2273                                if (!str_obj)
2274                                {
2275                                        PyMem_Free((void *)parms);
2276                                        while (s != str) { s--; Py_DECREF(*s); }
2277                                        PyMem_Free(str);
2278                                        Py_XDECREF(query_obj);
2279                                        Py_XDECREF(param_obj);
2280                                        PyErr_SetString(PyExc_TypeError,
2281                                                "Query parameter has no string representation");
2282                                        return NULL;
2283                                }
2284                                *s++ = str_obj;
2285                                *p = PyStr_AsString(str_obj);
2286                        }
2287                }
2288
2289                Py_BEGIN_ALLOW_THREADS
2290                result = PQexecParams(self->cnx, query, nparms,
2291                        NULL, parms, NULL, NULL, 0);
2292                Py_END_ALLOW_THREADS
2293
2294                PyMem_Free((void *)parms);
2295                while (s != str) { s--; Py_DECREF(*s); }
2296                PyMem_Free(str);
2297        }
2298        else
2299        {
2300                Py_BEGIN_ALLOW_THREADS
2301                result = PQexec(self->cnx, query);
2302                Py_END_ALLOW_THREADS
2303        }
2304
2305        /* we don't need the query and its params any more */
2306        Py_XDECREF(query_obj);
2307        Py_XDECREF(param_obj);
2308
2309        /* checks result validity */
2310        if (!result)
2311        {
2312                PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->cnx));
2313                return NULL;
2314        }
2315
2316        /* this may have changed the datestyle, so we reset the date format
2317           in order to force fetching it newly when next time requested */
2318        self->date_format = date_format; /* this is normally NULL */
2319
2320        /* checks result status */
2321        if ((status = PQresultStatus(result)) != PGRES_TUPLES_OK)
2322        {
2323                switch (status)
2324                {
2325                        case PGRES_EMPTY_QUERY:
2326                                PyErr_SetString(PyExc_ValueError, "Empty query");
2327                                break;
2328                        case PGRES_BAD_RESPONSE:
2329                        case PGRES_FATAL_ERROR:
2330                        case PGRES_NONFATAL_ERROR:
2331                                set_error(ProgrammingError, "Cannot execute query",
2332                                        self->cnx, result);
2333                                break;
2334                        case PGRES_COMMAND_OK:
2335                                {                                               /* INSERT, UPDATE, DELETE */
2336                                        Oid             oid = PQoidValue(result);
2337                                        if (oid == InvalidOid)  /* not a single insert */
2338                                        {
2339                                                char    *ret = PQcmdTuples(result);
2340
2341                                                if (ret[0])             /* return number of rows affected */
2342                                                {
2343                                                        PyObject *obj = PyStr_FromString(ret);
2344                                                        PQclear(result);
2345                                                        return obj;
2346                                                }
2347                                                PQclear(result);
2348                                                Py_INCREF(Py_None);
2349                                                return Py_None;
2350                                        }
2351                                        /* for a single insert, return the oid */
2352                                        PQclear(result);
2353                                        return PyInt_FromLong(oid);
2354                                }
2355                        case PGRES_COPY_OUT:            /* no data will be received */
2356                        case PGRES_COPY_IN:
2357                                PQclear(result);
2358                                Py_INCREF(Py_None);
2359                                return Py_None;
2360                        default:
2361                                set_error_msg(InternalError, "Unknown result status");
2362                }
2363
2364                PQclear(result);
2365                return NULL;                    /* error detected on query */
2366        }
2367
2368        if (!(npgobj = PyObject_NEW(queryObject, &queryType)))
2369                return PyErr_NoMemory();
2370
2371        /* stores result and returns object */
2372        Py_XINCREF(self);
2373        npgobj->pgcnx = self;
2374        npgobj->result = result;
2375        npgobj->encoding = encoding;
2376        return (PyObject *) npgobj;
2377}
2378
2379#ifdef DIRECT_ACCESS
2380static char connPutLine__doc__[] =
2381"putline(line) -- send a line directly to the backend";
2382
2383/* direct access function: putline */
2384static PyObject *
2385connPutLine(connObject *self, PyObject *args)
2386{
2387        char *line;
2388        int line_length;
2389
2390        if (!self->cnx)
2391        {
2392                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2393                return NULL;
2394        }
2395
2396        /* reads args */
2397        if (!PyArg_ParseTuple(args, "s#", &line, &line_length))
2398        {
2399                PyErr_SetString(PyExc_TypeError,
2400                        "Method putline() takes a string argument");
2401                return NULL;
2402        }
2403
2404        /* sends line to backend */
2405        if (PQputline(self->cnx, line))
2406        {
2407                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
2408                return NULL;
2409        }
2410        Py_INCREF(Py_None);
2411        return Py_None;
2412}
2413
2414/* direct access function: getline */
2415static char connGetLine__doc__[] =
2416"getline() -- get a line directly from the backend";
2417
2418static PyObject *
2419connGetLine(connObject *self, PyObject *noargs)
2420{
2421        char            line[MAX_BUFFER_SIZE];
2422        PyObject   *str = NULL;         /* GCC */
2423
2424        if (!self->cnx)
2425        {
2426                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2427                return NULL;
2428        }
2429
2430        /* gets line */
2431        switch (PQgetline(self->cnx, line, MAX_BUFFER_SIZE))
2432        {
2433                case 0:
2434                        str = PyStr_FromString(line);
2435                        break;
2436                case 1:
2437                        PyErr_SetString(PyExc_MemoryError, "Buffer overflow");
2438                        str = NULL;
2439                        break;
2440                case EOF:
2441                        Py_INCREF(Py_None);
2442                        str = Py_None;
2443                        break;
2444        }
2445
2446        return str;
2447}
2448
2449/* direct access function: end copy */
2450static char connEndCopy__doc__[] =
2451"endcopy() -- synchronize client and server";
2452
2453static PyObject *
2454connEndCopy(connObject *self, PyObject *noargs)
2455{
2456        if (!self->cnx)
2457        {
2458                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2459                return NULL;
2460        }
2461
2462        /* ends direct copy */
2463        if (PQendcopy(self->cnx))
2464        {
2465                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
2466                return NULL;
2467        }
2468        Py_INCREF(Py_None);
2469        return Py_None;
2470}
2471#endif /* DIRECT_ACCESS */
2472
2473/* return query as string in human readable form */
2474static PyObject *
2475queryStr(queryObject *self)
2476{
2477        return format_result(self->result);
2478}
2479
2480/* insert table */
2481static char connInsertTable__doc__[] =
2482"inserttable(table, data) -- insert list into table\n\n"
2483"The fields in the list must be in the same order as in the table.\n";
2484
2485static PyObject *
2486connInsertTable(connObject *self, PyObject *args)
2487{
2488        PGresult        *result;
2489        char            *table,
2490                                *buffer,
2491                                *bufpt;
2492        int                     encoding;
2493        size_t          bufsiz;
2494        PyObject        *list,
2495                                *sublist,
2496                                *item;
2497        PyObject        *(*getitem) (PyObject *, Py_ssize_t);
2498        PyObject        *(*getsubitem) (PyObject *, Py_ssize_t);
2499        Py_ssize_t      i,
2500                                j,
2501                                m,
2502                                n;
2503
2504        if (!self->cnx)
2505        {
2506                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2507                return NULL;
2508        }
2509
2510        /* gets arguments */
2511        if (!PyArg_ParseTuple(args, "sO:filter", &table, &list))
2512        {
2513                PyErr_SetString(PyExc_TypeError,
2514                        "Method inserttable() expects a string and a list as arguments");
2515                return NULL;
2516        }
2517
2518        /* checks list type */
2519        if (PyTuple_Check(list))
2520        {
2521                m = PyTuple_Size(list);
2522                getitem = PyTuple_GetItem;
2523        }
2524        else if (PyList_Check(list))
2525        {
2526                m = PyList_Size(list);
2527                getitem = PyList_GetItem;
2528        }
2529        else
2530        {
2531                PyErr_SetString(PyExc_TypeError,
2532                        "Method inserttable() expects some kind of array"
2533                        " as second argument");
2534                return NULL;
2535        }
2536
2537        /* allocate buffer */
2538        if (!(buffer = PyMem_Malloc(MAX_BUFFER_SIZE)))
2539                return PyErr_NoMemory();
2540
2541        /* starts query */
2542        sprintf(buffer, "copy %s from stdin", table);
2543
2544        Py_BEGIN_ALLOW_THREADS
2545        result = PQexec(self->cnx, buffer);
2546        Py_END_ALLOW_THREADS
2547
2548        if (!result)
2549        {
2550                PyMem_Free(buffer);
2551                PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->cnx));
2552                return NULL;
2553        }
2554
2555        encoding = PQclientEncoding(self->cnx);
2556
2557        PQclear(result);
2558
2559        n = 0; /* not strictly necessary but avoids warning */
2560
2561        /* feed table */
2562        for (i = 0; i < m; ++i)
2563        {
2564                sublist = getitem(list, i);
2565                if (PyTuple_Check(sublist))
2566                {
2567                        j = PyTuple_Size(sublist);
2568                        getsubitem = PyTuple_GetItem;
2569                }
2570                else if (PyList_Check(sublist))
2571                {
2572                        j = PyList_Size(sublist);
2573                        getsubitem = PyList_GetItem;
2574                }
2575                else
2576                {
2577                        PyErr_SetString(PyExc_TypeError,
2578                                "Second arg must contain some kind of arrays");
2579                        return NULL;
2580                }
2581                if (i)
2582                {
2583                        if (j != n)
2584                        {
2585                                PyMem_Free(buffer);
2586                                PyErr_SetString(PyExc_TypeError,
2587                                        "Arrays contained in second arg must have same size");
2588                                return NULL;
2589                        }
2590                }
2591                else
2592                {
2593                        n = j; /* never used before this assignment */
2594                }
2595
2596                /* builds insert line */
2597                bufpt = buffer;
2598                bufsiz = MAX_BUFFER_SIZE - 1;
2599
2600                for (j = 0; j < n; ++j)
2601                {
2602                        if (j)
2603                        {
2604                                *bufpt++ = '\t'; --bufsiz;
2605                        }
2606
2607                        item = getsubitem(sublist, j);
2608
2609                        /* convert item to string and append to buffer */
2610                        if (item == Py_None)
2611                        {
2612                                if (bufsiz > 2)
2613                                {
2614                                        *bufpt++ = '\\'; *bufpt++ = 'N';
2615                                        bufsiz -= 2;
2616                                }
2617                                else
2618                                        bufsiz = 0;
2619                        }
2620                        else if (PyBytes_Check(item))
2621                        {
2622                                const char* t = PyBytes_AsString(item);
2623                                while (*t && bufsiz)
2624                                {
2625                                        if (*t == '\\' || *t == '\t' || *t == '\n')
2626                                        {
2627                                                *bufpt++ = '\\'; --bufsiz;
2628                                                if (!bufsiz) break;
2629                                        }
2630                                        *bufpt++ = *t++; --bufsiz;
2631                                }
2632                        }
2633                        else if (PyUnicode_Check(item))
2634                        {
2635                                PyObject *s = get_encoded_string(item, encoding);
2636                                if (!s)
2637                                {
2638                                        PyMem_Free(buffer);
2639                                        return NULL; /* pass the UnicodeEncodeError */
2640                                }
2641                                else
2642                                {
2643                                        const char* t = PyBytes_AsString(s);
2644                                        while (*t && bufsiz)
2645                                        {
2646                                                if (*t == '\\' || *t == '\t' || *t == '\n')
2647                                                {
2648                                                        *bufpt++ = '\\'; --bufsiz;
2649                                                        if (!bufsiz) break;
2650                                                }
2651                                                *bufpt++ = *t++; --bufsiz;
2652                                        }
2653                                        Py_DECREF(s);
2654                                }
2655                        }
2656                        else if (PyInt_Check(item) || PyLong_Check(item))
2657                        {
2658                                PyObject* s = PyObject_Str(item);
2659                                const char* t = PyStr_AsString(s);
2660                                while (*t && bufsiz)
2661                                {
2662                                        *bufpt++ = *t++; --bufsiz;
2663                                }
2664                                Py_DECREF(s);
2665                        }
2666                        else
2667                        {
2668                                PyObject* s = PyObject_Repr(item);
2669                                const char* t = PyStr_AsString(s);
2670                                while (*t && bufsiz)
2671                                {
2672                                        if (*t == '\\' || *t == '\t' || *t == '\n')
2673                                        {
2674                                                *bufpt++ = '\\'; --bufsiz;
2675                                                if (!bufsiz) break;
2676                                        }
2677                                        *bufpt++ = *t++; --bufsiz;
2678                                }
2679                                Py_DECREF(s);
2680                        }
2681
2682                        if (bufsiz <= 0)
2683                        {
2684                                PyMem_Free(buffer); return PyErr_NoMemory();
2685                        }
2686
2687                }
2688
2689                *bufpt++ = '\n'; *bufpt = '\0';
2690
2691                /* sends data */
2692                if (PQputline(self->cnx, buffer))
2693                {
2694                        PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
2695                        PQendcopy(self->cnx);
2696                        PyMem_Free(buffer);
2697                        return NULL;
2698                }
2699        }
2700
2701        /* ends query */
2702        if (PQputline(self->cnx, "\\.\n"))
2703        {
2704                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
2705                PQendcopy(self->cnx);
2706                PyMem_Free(buffer);
2707                return NULL;
2708        }
2709
2710        if (PQendcopy(self->cnx))
2711        {
2712                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
2713                PyMem_Free(buffer);
2714                return NULL;
2715        }
2716
2717        PyMem_Free(buffer);
2718
2719        /* no error : returns nothing */
2720        Py_INCREF(Py_None);
2721        return Py_None;
2722}
2723
2724/* get transaction state */
2725static char connTransaction__doc__[] =
2726"transaction() -- return the current transaction status";
2727
2728static PyObject *
2729connTransaction(connObject *self, PyObject *noargs)
2730{
2731        if (!self->cnx)
2732        {
2733                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2734                return NULL;
2735        }
2736
2737        return PyInt_FromLong(PQtransactionStatus(self->cnx));
2738}
2739
2740/* get parameter setting */
2741static char connParameter__doc__[] =
2742"parameter(name) -- look up a current parameter setting";
2743
2744static PyObject *
2745connParameter(connObject *self, PyObject *args)
2746{
2747        const char *name;
2748
2749        if (!self->cnx)
2750        {
2751                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2752                return NULL;
2753        }
2754
2755        /* get query args */
2756        if (!PyArg_ParseTuple(args, "s", &name))
2757        {
2758                PyErr_SetString(PyExc_TypeError,
2759                        "Method parameter() takes a string as argument");
2760                return NULL;
2761        }
2762
2763        name = PQparameterStatus(self->cnx, name);
2764
2765        if (name)
2766                return PyStr_FromString(name);
2767
2768        /* unknown parameter, return None */
2769        Py_INCREF(Py_None);
2770        return Py_None;
2771}
2772
2773/* internal function converting a Postgres datestyles to date formats */
2774static const char *
2775date_style_to_format(const char *s)
2776{
2777        static const char *formats[] = {
2778                "%Y-%m-%d",             /* 0 = ISO */
2779                "%m-%d-%Y",             /* 1 = Postgres, MDY */
2780                "%d-%m-%Y",             /* 2 = Postgres, DMY */
2781                "%m/%d/%Y",             /* 3 = SQL, MDY */
2782                "%d/%m/%Y",             /* 4 = SQL, DMY */
2783                "%d.%m.%Y"};    /* 5 = German */
2784
2785        switch (s ? *s : 'I')
2786        {
2787                case 'P': /* Postgres */
2788                        s = strchr(s + 1, ',');
2789                        if (s) do ++s; while (*s && *s == ' ');
2790                        return formats[s && *s == 'D' ? 2 : 1];
2791                case 'S': /* SQL */
2792                        s = strchr(s + 1, ',');
2793                        if (s) do ++s; while (*s && *s == ' ');
2794                        return formats[s && *s == 'D' ? 4 : 3];
2795                case 'G': /* German */
2796                        return formats[5];
2797                default: /* ISO */
2798                        return formats[0]; /* ISO is the default */
2799        }
2800}
2801
2802/* internal function converting a date format to a Postgres datestyle */
2803static const char *
2804date_format_to_style(const char *s)
2805{
2806        static const char *datestyle[] = {
2807                "ISO, YMD",                     /* 0 = %Y-%m-%d */
2808                "Postgres, MDY",        /* 1 = %m-%d-%Y */
2809                "Postgres, DMY",        /* 2 = %d-%m-%Y */
2810                "SQL, MDY",             /* 3 = %m/%d/%Y */
2811                "SQL, DMY",             /* 4 = %d/%m/%Y */
2812                "German, DMY"};         /* 5 = %d.%m.%Y */
2813
2814        switch (s ? s[1] : 'Y')
2815        {
2816                case 'm':
2817                        switch (s[2])
2818                        {
2819                                case '/':
2820                                        return datestyle[3]; /* SQL, MDY */
2821                                default:
2822                                        return datestyle[1]; /* Postgres, MDY */
2823                        }
2824                case 'd':
2825                        switch (s[2])
2826                        {
2827                                case '/':
2828                                        return datestyle[4]; /* SQL, DMY */
2829                                case '.':
2830                                        return datestyle[5]; /* German */
2831                                default:
2832                                        return datestyle[2]; /* Postgres, DMY */
2833                        }
2834                default:
2835                        return datestyle[0]; /* ISO */
2836        }
2837}
2838
2839/* get current date format */
2840static char connDateFormat__doc__[] =
2841"date_format() -- return the current date format";
2842
2843static PyObject *
2844connDateFormat(connObject *self, PyObject *noargs)
2845{
2846        const char *fmt;
2847
2848        if (!self->cnx)
2849        {
2850                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2851                return NULL;
2852        }
2853
2854        /* check if the date format is cached in the connection */
2855        fmt = self->date_format;
2856        if (!fmt)
2857        {
2858                fmt = date_style_to_format(PQparameterStatus(self->cnx, "DateStyle"));
2859                self->date_format = fmt; /* cache the result */
2860        }
2861
2862        return PyStr_FromString(fmt);
2863}
2864
2865#ifdef ESCAPING_FUNCS
2866
2867/* escape literal */
2868static char connEscapeLiteral__doc__[] =
2869"escape_literal(str) -- escape a literal constant for use within SQL";
2870
2871static PyObject *
2872connEscapeLiteral(connObject *self, PyObject *string)
2873{
2874        PyObject   *tmp_obj = NULL, /* auxiliary string object */
2875                           *to_obj; /* string object to return */
2876        char       *from, /* our string argument as encoded string */
2877                           *to; /* the result as encoded string */
2878        Py_ssize_t      from_length; /* length of string */
2879        size_t          to_length; /* length of result */
2880        int                     encoding = -1; /* client encoding */
2881
2882        if (PyBytes_Check(string))
2883        {
2884                PyBytes_AsStringAndSize(string, &from, &from_length);
2885        }
2886        else if (PyUnicode_Check(string))
2887        {
2888                encoding = PQclientEncoding(self->cnx);
2889                tmp_obj = get_encoded_string(string, encoding);
2890                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
2891                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
2892        }
2893        else
2894        {
2895                PyErr_SetString(PyExc_TypeError,
2896                        "Method escape_literal() expects a string as argument");
2897                return NULL;
2898        }
2899
2900        to = PQescapeLiteral(self->cnx, from, (size_t)from_length);
2901        to_length = strlen(to);
2902
2903        Py_XDECREF(tmp_obj);
2904
2905        if (encoding == -1)
2906                to_obj = PyBytes_FromStringAndSize(to, to_length);
2907        else
2908                to_obj = get_decoded_string(to, to_length, encoding);
2909        if (to)
2910                PQfreemem(to);
2911        return to_obj;
2912}
2913
2914/* escape identifier */
2915static char connEscapeIdentifier__doc__[] =
2916"escape_identifier(str) -- escape an identifier for use within SQL";
2917
2918static PyObject *
2919connEscapeIdentifier(connObject *self, PyObject *string)
2920{
2921        PyObject   *tmp_obj = NULL, /* auxiliary string object */
2922                           *to_obj; /* string object to return */
2923        char       *from, /* our string argument as encoded string */
2924                           *to; /* the result as encoded string */
2925        Py_ssize_t      from_length; /* length of string */
2926        size_t          to_length; /* length of result */
2927        int                     encoding = -1; /* client encoding */
2928
2929        if (PyBytes_Check(string))
2930        {
2931                PyBytes_AsStringAndSize(string, &from, &from_length);
2932        }
2933        else if (PyUnicode_Check(string))
2934        {
2935                encoding = PQclientEncoding(self->cnx);
2936                tmp_obj = get_encoded_string(string, encoding);
2937                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
2938                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
2939        }
2940        else
2941        {
2942                PyErr_SetString(PyExc_TypeError,
2943                        "Method escape_identifier() expects a string as argument");
2944                return NULL;
2945        }
2946
2947        to = PQescapeIdentifier(self->cnx, from, (size_t)from_length);
2948        to_length = strlen(to);
2949
2950        Py_XDECREF(tmp_obj);
2951
2952        if (encoding == -1)
2953                to_obj = PyBytes_FromStringAndSize(to, to_length);
2954        else
2955                to_obj = get_decoded_string(to, to_length, encoding);
2956        if (to)
2957                PQfreemem(to);
2958        return to_obj;
2959}
2960
2961#endif  /* ESCAPING_FUNCS */
2962
2963/* escape string */
2964static char connEscapeString__doc__[] =
2965"escape_string(str) -- escape a string for use within SQL";
2966
2967static PyObject *
2968connEscapeString(connObject *self, PyObject *string)
2969{
2970        PyObject   *tmp_obj = NULL, /* auxiliary string object */
2971                           *to_obj; /* string object to return */
2972        char       *from, /* our string argument as encoded string */
2973                           *to; /* the result as encoded string */
2974        Py_ssize_t      from_length; /* length of string */
2975        size_t          to_length; /* length of result */
2976        int                     encoding = -1; /* client encoding */
2977
2978        if (PyBytes_Check(string))
2979        {
2980                PyBytes_AsStringAndSize(string, &from, &from_length);
2981        }
2982        else if (PyUnicode_Check(string))
2983        {
2984                encoding = PQclientEncoding(self->cnx);
2985                tmp_obj = get_encoded_string(string, encoding);
2986                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
2987                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
2988        }
2989        else
2990        {
2991                PyErr_SetString(PyExc_TypeError,
2992                        "Method escape_string() expects a string as argument");
2993                return NULL;
2994        }
2995
2996        to_length = 2*from_length + 1;
2997        if ((Py_ssize_t)to_length < from_length) /* overflow */
2998        {
2999                to_length = from_length;
3000                from_length = (from_length - 1)/2;
3001        }
3002        to = (char *)PyMem_Malloc(to_length);
3003        to_length = PQescapeStringConn(self->cnx,
3004                to, from, (size_t)from_length, NULL);
3005
3006        Py_XDECREF(tmp_obj);
3007
3008        if (encoding == -1)
3009                to_obj = PyBytes_FromStringAndSize(to, to_length);
3010        else
3011                to_obj = get_decoded_string(to, to_length, encoding);
3012        PyMem_Free(to);
3013        return to_obj;
3014}
3015
3016/* escape bytea */
3017static char connEscapeBytea__doc__[] =
3018"escape_bytea(data) -- escape binary data for use within SQL as type bytea";
3019
3020static PyObject *
3021connEscapeBytea(connObject *self, PyObject *data)
3022{
3023        PyObject   *tmp_obj = NULL, /* auxiliary string object */
3024                           *to_obj; /* string object to return */
3025        char       *from, /* our string argument as encoded string */
3026                           *to; /* the result as encoded string */
3027        Py_ssize_t      from_length; /* length of string */
3028        size_t          to_length; /* length of result */
3029        int                     encoding = -1; /* client encoding */
3030
3031        if (PyBytes_Check(data))
3032        {
3033                PyBytes_AsStringAndSize(data, &from, &from_length);
3034        }
3035        else if (PyUnicode_Check(data))
3036        {
3037                encoding = PQclientEncoding(self->cnx);
3038                tmp_obj = get_encoded_string(data, encoding);
3039                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
3040                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
3041        }
3042        else
3043        {
3044                PyErr_SetString(PyExc_TypeError,
3045                        "Method escape_bytea() expects a string as argument");
3046                return NULL;
3047        }
3048
3049        to = (char *)PQescapeByteaConn(self->cnx,
3050                (unsigned char *)from, (size_t)from_length, &to_length);
3051
3052        Py_XDECREF(tmp_obj);
3053
3054        if (encoding == -1)
3055                to_obj = PyBytes_FromStringAndSize(to, to_length - 1);
3056        else
3057                to_obj = get_decoded_string(to, to_length - 1, encoding);
3058        if (to)
3059                PQfreemem(to);
3060        return to_obj;
3061}
3062
3063#ifdef LARGE_OBJECTS
3064/* creates large object */
3065static char connCreateLO__doc__[] =
3066"locreate(mode) -- create a new large object in the database";
3067
3068static PyObject *
3069connCreateLO(connObject *self, PyObject *args)
3070{
3071        int                     mode;
3072        Oid                     lo_oid;
3073
3074        /* checks validity */
3075        if (!check_cnx_obj(self))
3076                return NULL;
3077
3078        /* gets arguments */
3079        if (!PyArg_ParseTuple(args, "i", &mode))
3080        {
3081                PyErr_SetString(PyExc_TypeError,
3082                        "Method locreate() takes an integer argument");
3083                return NULL;
3084        }
3085
3086        /* creates large object */
3087        lo_oid = lo_creat(self->cnx, mode);
3088        if (lo_oid == 0)
3089        {
3090                set_error_msg(OperationalError, "Can't create large object");
3091                return NULL;
3092        }
3093
3094        return (PyObject *) largeNew(self, lo_oid);
3095}
3096
3097/* init from already known oid */
3098static char connGetLO__doc__[] =
3099"getlo(oid) -- create a large object instance for the specified oid";
3100
3101static PyObject *
3102connGetLO(connObject *self, PyObject *args)
3103{
3104        int                     oid;
3105        Oid                     lo_oid;
3106
3107        /* checks validity */
3108        if (!check_cnx_obj(self))
3109                return NULL;
3110
3111        /* gets arguments */
3112        if (!PyArg_ParseTuple(args, "i", &oid))
3113        {
3114                PyErr_SetString(PyExc_TypeError,
3115                        "Method getlo() takes an integer argument");
3116                return NULL;
3117        }
3118
3119        lo_oid = (Oid)oid;
3120        if (lo_oid == 0)
3121        {
3122                PyErr_SetString(PyExc_ValueError, "The object oid can't be null");
3123                return NULL;
3124        }
3125
3126        /* creates object */
3127        return (PyObject *) largeNew(self, lo_oid);
3128}
3129
3130/* import unix file */
3131static char connImportLO__doc__[] =
3132"loimport(name) -- create a new large object from specified file";
3133
3134static PyObject *
3135connImportLO(connObject *self, PyObject *args)
3136{
3137        char   *name;
3138        Oid             lo_oid;
3139
3140        /* checks validity */
3141        if (!check_cnx_obj(self))
3142                return NULL;
3143
3144        /* gets arguments */
3145        if (!PyArg_ParseTuple(args, "s", &name))
3146        {
3147                PyErr_SetString(PyExc_TypeError,
3148                        "Method loimport() takes a string argument");
3149                return NULL;
3150        }
3151
3152        /* imports file and checks result */
3153        lo_oid = lo_import(self->cnx, name);
3154        if (lo_oid == 0)
3155        {
3156                set_error_msg(OperationalError, "Can't create large object");
3157                return NULL;
3158        }
3159
3160        return (PyObject *) largeNew(self, lo_oid);
3161}
3162#endif /* LARGE_OBJECTS */
3163
3164/* resets connection */
3165static char connReset__doc__[] =
3166"reset() -- reset connection with current parameters\n\n"
3167"All derived queries and large objects derived from this connection\n"
3168"will not be usable after this call.\n";
3169
3170static PyObject *
3171connReset(connObject *self, PyObject *noargs)
3172{
3173        if (!self->cnx)
3174        {
3175                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
3176                return NULL;
3177        }
3178
3179        /* resets the connection */
3180        PQreset(self->cnx);
3181        Py_INCREF(Py_None);
3182        return Py_None;
3183}
3184
3185/* cancels current command */
3186static char connCancel__doc__[] =
3187"cancel() -- abandon processing of the current command";
3188
3189static PyObject *
3190connCancel(connObject *self, PyObject *noargs)
3191{
3192        if (!self->cnx)
3193        {
3194                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
3195                return NULL;
3196        }
3197
3198        /* request that the server abandon processing of the current command */
3199        return PyInt_FromLong((long) PQrequestCancel(self->cnx));
3200}
3201
3202/* get connection socket */
3203static char connFileno__doc__[] =
3204"fileno() -- return database connection socket file handle";
3205
3206static PyObject *
3207connFileno(connObject *self, PyObject *noargs)
3208{
3209        if (!self->cnx)
3210        {
3211                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
3212                return NULL;
3213        }
3214
3215#ifdef NO_PQSOCKET
3216        return PyInt_FromLong((long) self->cnx->sock);
3217#else
3218        return PyInt_FromLong((long) PQsocket(self->cnx));
3219#endif
3220}
3221
3222/* set external typecast callback function */
3223static char connSetCastHook__doc__[] =
3224"set_cast_hook(func) -- set a fallback typecast function";
3225
3226static PyObject *
3227connSetCastHook(connObject *self, PyObject *func)
3228{
3229        PyObject *ret = NULL;
3230
3231        if (func == Py_None)
3232        {
3233                Py_XDECREF(self->cast_hook);
3234                self->cast_hook = NULL;
3235                Py_INCREF(Py_None); ret = Py_None;
3236        }
3237        else if (PyCallable_Check(func))
3238        {
3239                Py_XINCREF(func); Py_XDECREF(self->cast_hook);
3240                self->cast_hook = func;
3241                Py_INCREF(Py_None); ret = Py_None;
3242        }
3243        else
3244                PyErr_SetString(PyExc_TypeError,
3245                        "Method set_cast_hook() expects"
3246                         " a callable or None as argument");
3247
3248        return ret;
3249}
3250
3251/* get notice receiver callback function */
3252static char connGetCastHook__doc__[] =
3253"get_cast_hook() -- get the fallback typecast function";
3254
3255static PyObject *
3256connGetCastHook(connObject *self, PyObject *noargs)
3257{
3258        PyObject *ret = self->cast_hook;;
3259
3260        if (!ret)
3261                ret = Py_None;
3262        Py_INCREF(ret);
3263
3264        return ret;
3265}
3266
3267/* set notice receiver callback function */
3268static char connSetNoticeReceiver__doc__[] =
3269"set_notice_receiver(func) -- set the current notice receiver";
3270
3271static PyObject *
3272connSetNoticeReceiver(connObject *self, PyObject *func)
3273{
3274        PyObject *ret = NULL;
3275
3276        if (func == Py_None)
3277        {
3278                Py_XDECREF(self->notice_receiver);
3279                self->notice_receiver = NULL;
3280                Py_INCREF(Py_None); ret = Py_None;
3281        }
3282        else if (PyCallable_Check(func))
3283        {
3284                Py_XINCREF(func); Py_XDECREF(self->notice_receiver);
3285                self->notice_receiver = func;
3286                PQsetNoticeReceiver(self->cnx, notice_receiver, self);
3287                Py_INCREF(Py_None); ret = Py_None;
3288        }
3289        else
3290                PyErr_SetString(PyExc_TypeError,
3291                        "Method set_notice_receiver() expects"
3292                         " a callable or None as argument");
3293
3294        return ret;
3295}
3296
3297/* get notice receiver callback function */
3298static char connGetNoticeReceiver__doc__[] =
3299"get_notice_receiver() -- get the current notice receiver";
3300
3301static PyObject *
3302connGetNoticeReceiver(connObject *self, PyObject *noargs)
3303{
3304        PyObject *ret = self->notice_receiver;
3305
3306        if (!ret)
3307                ret = Py_None;
3308        Py_INCREF(ret);
3309
3310        return ret;
3311}
3312
3313/* close without deleting */
3314static char connClose__doc__[] =
3315"close() -- close connection\n\n"
3316"All instances of the connection object and derived objects\n"
3317"(queries and large objects) can no longer be used after this call.\n";
3318
3319static PyObject *
3320connClose(connObject *self, PyObject *noargs)
3321{
3322        /* connection object cannot already be closed */
3323        if (!self->cnx)
3324        {
3325                set_error_msg(InternalError, "Connection already closed");
3326                return NULL;
3327        }
3328
3329        Py_BEGIN_ALLOW_THREADS
3330        PQfinish(self->cnx);
3331        Py_END_ALLOW_THREADS
3332
3333        self->cnx = NULL;
3334        Py_INCREF(Py_None);
3335        return Py_None;
3336}
3337
3338/* gets asynchronous notify */
3339static char connGetNotify__doc__[] =
3340"getnotify() -- get database notify for this connection";
3341
3342static PyObject *
3343connGetNotify(connObject *self, PyObject *noargs)
3344{
3345        PGnotify   *notify;
3346
3347        if (!self->cnx)
3348        {
3349                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
3350                return NULL;
3351        }
3352
3353        /* checks for NOTIFY messages */
3354        PQconsumeInput(self->cnx);
3355
3356        if (!(notify = PQnotifies(self->cnx)))
3357        {
3358                Py_INCREF(Py_None);
3359                return Py_None;
3360        }
3361        else
3362        {
3363                PyObject   *notify_result,
3364                                   *temp;
3365
3366                if (!(temp = PyStr_FromString(notify->relname)))
3367                        return NULL;
3368
3369                if (!(notify_result = PyTuple_New(3)))
3370                        return NULL;
3371
3372                PyTuple_SET_ITEM(notify_result, 0, temp);
3373
3374                if (!(temp = PyInt_FromLong(notify->be_pid)))
3375                {
3376                        Py_DECREF(notify_result);
3377                        return NULL;
3378                }
3379
3380                PyTuple_SET_ITEM(notify_result, 1, temp);
3381
3382                /* extra exists even in old versions that did not support it */
3383                if (!(temp = PyStr_FromString(notify->extra)))
3384                {
3385                        Py_DECREF(notify_result);
3386                        return NULL;
3387                }
3388
3389                PyTuple_SET_ITEM(notify_result, 2, temp);
3390
3391                PQfreemem(notify);
3392
3393                return notify_result;
3394        }
3395}
3396
3397/* get the list of connection attributes */
3398static PyObject *
3399connDir(connObject *self, PyObject *noargs)
3400{
3401        PyObject *attrs;
3402
3403        attrs = PyObject_Dir(PyObject_Type((PyObject *)self));
3404        PyObject_CallMethod(attrs, "extend", "[sssssssss]",
3405                "host", "port", "db", "options", "error", "status", "user",
3406                "protocol_version", "server_version");
3407
3408        return attrs;
3409}
3410
3411/* connection object methods */
3412static struct PyMethodDef connMethods[] = {
3413        {"__dir__", (PyCFunction) connDir,  METH_NOARGS, NULL},
3414
3415        {"source", (PyCFunction) connSource, METH_NOARGS, connSource__doc__},
3416        {"query", (PyCFunction) connQuery, METH_VARARGS, connQuery__doc__},
3417        {"reset", (PyCFunction) connReset, METH_NOARGS, connReset__doc__},
3418        {"cancel", (PyCFunction) connCancel, METH_NOARGS, connCancel__doc__},
3419        {"close", (PyCFunction) connClose, METH_NOARGS, connClose__doc__},
3420        {"fileno", (PyCFunction) connFileno, METH_NOARGS, connFileno__doc__},
3421        {"get_cast_hook", (PyCFunction) connGetCastHook, METH_NOARGS,
3422                        connGetCastHook__doc__},
3423        {"set_cast_hook", (PyCFunction) connSetCastHook, METH_O,
3424                        connSetCastHook__doc__},
3425        {"get_notice_receiver", (PyCFunction) connGetNoticeReceiver, METH_NOARGS,
3426                        connGetNoticeReceiver__doc__},
3427        {"set_notice_receiver", (PyCFunction) connSetNoticeReceiver, METH_O,
3428                        connSetNoticeReceiver__doc__},
3429        {"getnotify", (PyCFunction) connGetNotify, METH_NOARGS,
3430                        connGetNotify__doc__},
3431        {"inserttable", (PyCFunction) connInsertTable, METH_VARARGS,
3432                        connInsertTable__doc__},
3433        {"transaction", (PyCFunction) connTransaction, METH_NOARGS,
3434                        connTransaction__doc__},
3435        {"parameter", (PyCFunction) connParameter, METH_VARARGS,
3436                        connParameter__doc__},
3437        {"date_format", (PyCFunction) connDateFormat, METH_NOARGS,
3438                        connDateFormat__doc__},
3439
3440#ifdef ESCAPING_FUNCS
3441        {"escape_literal", (PyCFunction) connEscapeLiteral, METH_O,
3442                        connEscapeLiteral__doc__},
3443        {"escape_identifier", (PyCFunction) connEscapeIdentifier, METH_O,
3444                        connEscapeIdentifier__doc__},
3445#endif  /* ESCAPING_FUNCS */
3446        {"escape_string", (PyCFunction) connEscapeString, METH_O,
3447                        connEscapeString__doc__},
3448        {"escape_bytea", (PyCFunction) connEscapeBytea, METH_O,
3449                        connEscapeBytea__doc__},
3450
3451#ifdef DIRECT_ACCESS
3452        {"putline", (PyCFunction) connPutLine, METH_VARARGS, connPutLine__doc__},
3453        {"getline", (PyCFunction) connGetLine, METH_NOARGS, connGetLine__doc__},
3454        {"endcopy", (PyCFunction) connEndCopy, METH_NOARGS, connEndCopy__doc__},
3455#endif /* DIRECT_ACCESS */
3456
3457#ifdef LARGE_OBJECTS
3458        {"locreate", (PyCFunction) connCreateLO, METH_VARARGS, connCreateLO__doc__},
3459        {"getlo", (PyCFunction) connGetLO, METH_VARARGS, connGetLO__doc__},
3460        {"loimport", (PyCFunction) connImportLO, METH_VARARGS, connImportLO__doc__},
3461#endif /* LARGE_OBJECTS */
3462
3463        {NULL, NULL} /* sentinel */
3464};
3465
3466/* gets connection attributes */
3467static PyObject *
3468connGetAttr(connObject *self, PyObject *nameobj)
3469{
3470        const char *name = PyStr_AsString(nameobj);
3471
3472        /*
3473         * Although we could check individually, there are only a few
3474         * attributes that don't require a live connection and unless someone
3475         * has an urgent need, this will have to do
3476         */
3477
3478        /* first exception - close which returns a different error */
3479        if (strcmp(name, "close") && !self->cnx)
3480        {
3481                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
3482                return NULL;
3483        }
3484
3485        /* list PostgreSQL connection fields */
3486
3487        /* postmaster host */
3488        if (!strcmp(name, "host"))
3489        {
3490                char *r = PQhost(self->cnx);
3491                if (!r || r[0] == '/') /* Pg >= 9.6 can return a Unix socket path */
3492                        r = "localhost";
3493                return PyStr_FromString(r);
3494        }
3495
3496        /* postmaster port */
3497        if (!strcmp(name, "port"))
3498                return PyInt_FromLong(atol(PQport(self->cnx)));
3499
3500        /* selected database */
3501        if (!strcmp(name, "db"))
3502                return PyStr_FromString(PQdb(self->cnx));
3503
3504        /* selected options */
3505        if (!strcmp(name, "options"))
3506                return PyStr_FromString(PQoptions(self->cnx));
3507
3508        /* error (status) message */
3509        if (!strcmp(name, "error"))
3510                return PyStr_FromString(PQerrorMessage(self->cnx));
3511
3512        /* connection status : 1 - OK, 0 - BAD */
3513        if (!strcmp(name, "status"))
3514                return PyInt_FromLong(PQstatus(self->cnx) == CONNECTION_OK ? 1 : 0);
3515
3516        /* provided user name */
3517        if (!strcmp(name, "user"))
3518                return PyStr_FromString(PQuser(self->cnx));
3519
3520        /* protocol version */
3521        if (!strcmp(name, "protocol_version"))
3522                return PyInt_FromLong(PQprotocolVersion(self->cnx));
3523
3524        /* backend version */
3525        if (!strcmp(name, "server_version"))
3526                return PyInt_FromLong(PQserverVersion(self->cnx));
3527
3528        return PyObject_GenericGetAttr((PyObject *) self, nameobj);
3529}
3530
3531/* connection type definition */
3532static PyTypeObject connType = {
3533        PyVarObject_HEAD_INIT(NULL, 0)
3534        "pg.Connection",                        /* tp_name */
3535        sizeof(connObject),                     /* tp_basicsize */
3536        0,                                                      /* tp_itemsize */
3537        (destructor) connDelete,        /* tp_dealloc */
3538        0,                                                      /* tp_print */
3539        0,                                                      /* tp_getattr */
3540        0,                                                      /* tp_setattr */
3541        0,                                                      /* tp_reserved */
3542        0,                                                      /* tp_repr */
3543        0,                                                      /* tp_as_number */
3544        0,                                                      /* tp_as_sequence */
3545        0,                                                      /* tp_as_mapping */
3546        0,                                                      /* tp_hash */
3547        0,                                                      /* tp_call */
3548        0,                                                      /* tp_str */
3549        (getattrofunc) connGetAttr,     /* tp_getattro */
3550        0,                                                      /* tp_setattro */
3551        0,                                                      /* tp_as_buffer */
3552        Py_TPFLAGS_DEFAULT,                     /* tp_flags */
3553        0,                                                      /* tp_doc */
3554        0,                                                      /* tp_traverse */
3555        0,                                                      /* tp_clear */
3556        0,                                                      /* tp_richcompare */
3557        0,                                                      /* tp_weaklistoffset */
3558        0,                                                      /* tp_iter */
3559        0,                                                      /* tp_iternext */
3560        connMethods,                            /* tp_methods */
3561};
3562
3563/* --------------------------------------------------------------------- */
3564/* source object                                                                                                                 */
3565/* --------------------------------------------------------------------- */
3566/* checks source object validity */
3567static int
3568check_source_obj(sourceObject *self, int level)
3569{
3570        if (!self->valid)
3571        {
3572                set_error_msg(OperationalError, "Object has been closed");
3573                return 0;
3574        }
3575
3576        if ((level & CHECK_RESULT) && !self->result)
3577        {
3578                set_error_msg(DatabaseError, "No result");
3579                return 0;
3580        }
3581
3582        if ((level & CHECK_DQL) && self->result_type != RESULT_DQL)
3583        {
3584                set_error_msg(DatabaseError, "Last query did not return tuples");
3585                return 0;
3586        }
3587
3588        if ((level & CHECK_CNX) && !check_cnx_obj(self->pgcnx))
3589                return 0;
3590
3591        return 1;
3592}
3593
3594/* destructor */
3595static void
3596sourceDealloc(sourceObject *self)
3597{
3598        if (self->result)
3599                PQclear(self->result);
3600
3601        Py_XDECREF(self->pgcnx);
3602        PyObject_Del(self);
3603}
3604
3605/* closes object */
3606static char sourceClose__doc__[] =
3607"close() -- close query object without deleting it\n\n"
3608"All instances of the query object can no longer be used after this call.\n";
3609
3610static PyObject *
3611sourceClose(sourceObject *self, PyObject *noargs)
3612{
3613        /* frees result if necessary and invalidates object */
3614        if (self->result)
3615        {
3616                PQclear(self->result);
3617                self->result_type = RESULT_EMPTY;
3618                self->result = NULL;
3619        }
3620
3621        self->valid = 0;
3622
3623        /* return None */
3624        Py_INCREF(Py_None);
3625        return Py_None;
3626}
3627
3628/* database query */
3629static char sourceExecute__doc__[] =
3630"execute(sql) -- execute a SQL statement (string)\n\n"
3631"On success, this call returns the number of affected rows, or None\n"
3632"for DQL (SELECT, ...) statements.  The fetch (fetch(), fetchone()\n"
3633"and fetchall()) methods can be used to get result rows.\n";
3634
3635static PyObject *
3636sourceExecute(sourceObject *self, PyObject *sql)
3637{
3638        PyObject   *tmp_obj = NULL; /* auxiliary string object */
3639        char       *query;
3640        int                     encoding;
3641
3642        /* checks validity */
3643        if (!check_source_obj(self, CHECK_CNX))
3644                return NULL;
3645
3646        encoding = PQclientEncoding(self->pgcnx->cnx);
3647
3648        if (PyBytes_Check(sql))
3649        {
3650                query = PyBytes_AsString(sql);
3651        }
3652        else if (PyUnicode_Check(sql))
3653        {
3654                tmp_obj = get_encoded_string(sql, encoding);
3655                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
3656                query = PyBytes_AsString(tmp_obj);
3657        }
3658        else
3659        {
3660                PyErr_SetString(PyExc_TypeError,
3661                        "Method execute() expects a string as argument");
3662                return NULL;
3663        }
3664
3665        /* frees previous result */
3666        if (self->result)
3667        {
3668                PQclear(self->result);
3669                self->result = NULL;
3670        }
3671        self->max_row = 0;
3672        self->current_row = 0;
3673        self->num_fields = 0;
3674        self->encoding = encoding;
3675
3676        /* gets result */
3677        Py_BEGIN_ALLOW_THREADS
3678        self->result = PQexec(self->pgcnx->cnx, query);
3679        Py_END_ALLOW_THREADS
3680
3681        /* we don't need the auxiliary string any more */
3682        Py_XDECREF(tmp_obj);
3683
3684        /* checks result validity */
3685        if (!self->result)
3686        {
3687                PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->pgcnx->cnx));
3688                return NULL;
3689        }
3690
3691        /* this may have changed the datestyle, so we reset the date format
3692           in order to force fetching it newly when next time requested */
3693        self->pgcnx->date_format = date_format; /* this is normally NULL */
3694
3695        /* checks result status */
3696        switch (PQresultStatus(self->result))
3697        {
3698                /* query succeeded */
3699                case PGRES_TUPLES_OK:   /* DQL: returns None (DB-SIG compliant) */
3700                        self->result_type = RESULT_DQL;
3701                        self->max_row = PQntuples(self->result);
3702                        self->num_fields = PQnfields(self->result);
3703                        Py_INCREF(Py_None);
3704                        return Py_None;
3705                case PGRES_COMMAND_OK:  /* other requests */
3706                case PGRES_COPY_OUT:
3707                case PGRES_COPY_IN:
3708                        {
3709                                long    num_rows;
3710                                char   *temp;
3711                                temp = PQcmdTuples(self->result);
3712                                if (temp[0])
3713                                {
3714                                        self->result_type = RESULT_DML;
3715                                        num_rows = atol(temp);
3716                                }
3717                                else
3718                                {
3719                                        self->result_type = RESULT_DDL;
3720                                        num_rows = -1;
3721                                }
3722                                return PyInt_FromLong(num_rows);
3723                        }
3724
3725                /* query failed */
3726                case PGRES_EMPTY_QUERY:
3727                        PyErr_SetString(PyExc_ValueError, "Empty query");
3728                        break;
3729                case PGRES_BAD_RESPONSE:
3730                case PGRES_FATAL_ERROR:
3731                case PGRES_NONFATAL_ERROR:
3732                        set_error(ProgrammingError, "Cannot execute command",
3733                                self->pgcnx->cnx, self->result);
3734                        break;
3735                default:
3736                        set_error_msg(InternalError, "Internal error: "
3737                                "unknown result status");
3738        }
3739
3740        /* frees result and returns error */
3741        PQclear(self->result);
3742        self->result = NULL;
3743        self->result_type = RESULT_EMPTY;
3744        return NULL;
3745}
3746
3747/* gets oid status for last query (valid for INSERTs, 0 for other) */
3748static char sourceStatusOID__doc__[] =
3749"oidstatus() -- return oid of last inserted row (if available)";
3750
3751static PyObject *
3752sourceStatusOID(sourceObject *self, PyObject *noargs)
3753{
3754        Oid                     oid;
3755
3756        /* checks validity */
3757        if (!check_source_obj(self, CHECK_RESULT))
3758                return NULL;
3759
3760        /* retrieves oid status */
3761        if ((oid = PQoidValue(self->result)) == InvalidOid)
3762        {
3763                Py_INCREF(Py_None);
3764                return Py_None;
3765        }
3766
3767        return PyInt_FromLong(oid);
3768}
3769
3770/* fetches rows from last result */
3771static char sourceFetch__doc__[] =
3772"fetch(num) -- return the next num rows from the last result in a list\n\n"
3773"If num parameter is omitted arraysize attribute value is used.\n"
3774"If size equals -1, all rows are fetched.\n";
3775
3776static PyObject *
3777sourceFetch(sourceObject *self, PyObject *args)
3778{
3779        PyObject   *reslist;
3780        int                     i,
3781                                k;
3782        long            size;
3783#if IS_PY3
3784        int                     encoding;
3785#endif
3786
3787        /* checks validity */
3788        if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL | CHECK_CNX))
3789                return NULL;
3790
3791        /* checks args */
3792        size = self->arraysize;
3793        if (!PyArg_ParseTuple(args, "|l", &size))
3794        {
3795                PyErr_SetString(PyExc_TypeError,
3796                        "fetch(num), with num (integer, optional)");
3797                return NULL;
3798        }
3799
3800        /* seeks last line */
3801        /* limit size to be within the amount of data we actually have */
3802        if (size == -1 || (self->max_row - self->current_row) < size)
3803                size = self->max_row - self->current_row;
3804
3805        /* allocate list for result */
3806        if (!(reslist = PyList_New(0))) return NULL;
3807
3808#if IS_PY3
3809        encoding = self->encoding;
3810#endif
3811
3812        /* builds result */
3813        for (i = 0, k = self->current_row; i < size; ++i, ++k)
3814        {
3815                PyObject   *rowtuple;
3816                int                     j;
3817
3818                if (!(rowtuple = PyTuple_New(self->num_fields)))
3819                {
3820                        Py_DECREF(reslist); return NULL;
3821                }
3822
3823                for (j = 0; j < self->num_fields; ++j)
3824                {
3825                        PyObject   *str;
3826
3827                        if (PQgetisnull(self->result, k, j))
3828                        {
3829                                Py_INCREF(Py_None);
3830                                str = Py_None;
3831                        }
3832                        else
3833                        {
3834                                char *s = PQgetvalue(self->result, k, j);
3835                                Py_ssize_t size = PQgetlength(self->result, k, j);
3836#if IS_PY3
3837                                if (PQfformat(self->result, j) == 0) /* textual format */
3838                                {
3839                                        str = get_decoded_string(s, size, encoding);
3840                                        if (!str) /* cannot decode */
3841                                                str = PyBytes_FromStringAndSize(s, size);
3842                                }
3843                                else
3844#endif
3845                                str = PyBytes_FromStringAndSize(s, size);
3846                        }
3847                        PyTuple_SET_ITEM(rowtuple, j, str);
3848                }
3849
3850                if (PyList_Append(reslist, rowtuple))
3851                {
3852                        Py_DECREF(rowtuple); Py_DECREF(reslist); return NULL;
3853                }
3854                Py_DECREF(rowtuple);
3855        }
3856
3857        self->current_row = k;
3858        return reslist;
3859}
3860
3861/* changes current row (internal wrapper for all "move" methods) */
3862static PyObject *
3863pgsource_move(sourceObject *self, int move)
3864{
3865        /* checks validity */
3866        if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
3867                return NULL;
3868
3869        /* changes the current row */
3870        switch (move)
3871        {
3872                case QUERY_MOVEFIRST:
3873                        self->current_row = 0;
3874                        break;
3875                case QUERY_MOVELAST:
3876                        self->current_row = self->max_row - 1;
3877                        break;
3878                case QUERY_MOVENEXT:
3879                        if (self->current_row != self->max_row)
3880                                ++self->current_row;
3881                        break;
3882                case QUERY_MOVEPREV:
3883                        if (self->current_row > 0)
3884                                self->current_row--;
3885                        break;
3886        }
3887
3888        Py_INCREF(Py_None);
3889        return Py_None;
3890}
3891
3892/* move to first result row */
3893static char sourceMoveFirst__doc__[] =
3894"movefirst() -- move to first result row";
3895
3896static PyObject *
3897sourceMoveFirst(sourceObject *self, PyObject *noargs)
3898{
3899        return pgsource_move(self, QUERY_MOVEFIRST);
3900}
3901
3902/* move to last result row */
3903static char sourceMoveLast__doc__[] =
3904"movelast() -- move to last valid result row";
3905
3906static PyObject *
3907sourceMoveLast(sourceObject *self, PyObject *noargs)
3908{
3909        return pgsource_move(self, QUERY_MOVELAST);
3910}
3911
3912/* move to next result row */
3913static char sourceMoveNext__doc__[] =
3914"movenext() -- move to next result row";
3915
3916static PyObject *
3917sourceMoveNext(sourceObject *self, PyObject *noargs)
3918{
3919        return pgsource_move(self, QUERY_MOVENEXT);
3920}
3921
3922/* move to previous result row */
3923static char sourceMovePrev__doc__[] =
3924"moveprev() -- move to previous result row";
3925
3926static PyObject *
3927sourceMovePrev(sourceObject *self, PyObject *noargs)
3928{
3929        return pgsource_move(self, QUERY_MOVEPREV);
3930}
3931
3932/* put copy data */
3933static char sourcePutData__doc__[] =
3934"putdata(buffer) -- send data to server during copy from stdin";
3935
3936static PyObject *
3937sourcePutData(sourceObject *self, PyObject *buffer)
3938{
3939        PyObject   *tmp_obj = NULL; /* an auxiliary object */
3940        char       *buf; /* the buffer as encoded string */
3941        Py_ssize_t      nbytes; /* length of string */
3942        char       *errormsg = NULL; /* error message */
3943        int                     res; /* direct result of the operation */
3944        PyObject   *ret; /* return value */
3945
3946        /* checks validity */
3947        if (!check_source_obj(self, CHECK_CNX))
3948                return NULL;
3949
3950        /* make sure that the connection object is valid */
3951        if (!self->pgcnx->cnx)
3952                return NULL;
3953
3954        if (buffer == Py_None)
3955        {
3956                /* pass None for terminating the operation */
3957                buf = errormsg = NULL;
3958        }
3959        else if (PyBytes_Check(buffer))
3960        {
3961                /* or pass a byte string */
3962                PyBytes_AsStringAndSize(buffer, &buf, &nbytes);
3963        }
3964        else if (PyUnicode_Check(buffer))
3965        {
3966                /* or pass a unicode string */
3967                tmp_obj = get_encoded_string(
3968                        buffer, PQclientEncoding(self->pgcnx->cnx));
3969                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
3970                PyBytes_AsStringAndSize(tmp_obj, &buf, &nbytes);
3971        }
3972        else if (PyErr_GivenExceptionMatches(buffer, PyExc_BaseException))
3973        {
3974                /* or pass a Python exception for sending an error message */
3975                tmp_obj = PyObject_Str(buffer);
3976                if (PyUnicode_Check(tmp_obj))
3977                {
3978                        PyObject *obj = tmp_obj;
3979                        tmp_obj = get_encoded_string(
3980                                obj, PQclientEncoding(self->pgcnx->cnx));
3981                        Py_DECREF(obj);
3982                        if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
3983                }
3984                errormsg = PyBytes_AsString(tmp_obj);
3985                buf = NULL;
3986        }
3987        else
3988        {
3989                PyErr_SetString(PyExc_TypeError,
3990                        "Method putdata() expects a buffer, None"
3991                         " or an exception as argument");
3992                return NULL;
3993        }
3994
3995        /* checks validity */
3996        if (!check_source_obj(self, CHECK_CNX | CHECK_RESULT) ||
3997                        PQresultStatus(self->result) != PGRES_COPY_IN)
3998        {
3999                PyErr_SetString(PyExc_IOError,
4000                        "Connection is invalid or not in copy_in state");
4001                Py_XDECREF(tmp_obj);
4002                return NULL;
4003        }
4004
4005        if (buf)
4006        {
4007                res = nbytes ? PQputCopyData(self->pgcnx->cnx, buf, (int)nbytes) : 1;
4008        }
4009        else
4010        {
4011                res = PQputCopyEnd(self->pgcnx->cnx, errormsg);
4012        }
4013
4014        Py_XDECREF(tmp_obj);
4015
4016        if (res != 1)
4017        {
4018                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->pgcnx->cnx));
4019                return NULL;
4020        }
4021
4022        if (buf) /* buffer has been sent */
4023        {
4024                ret = Py_None;
4025                Py_INCREF(ret);
4026        }
4027        else /* copy is done */
4028        {
4029                PGresult   *result; /* final result of the operation */
4030
4031                Py_BEGIN_ALLOW_THREADS;
4032                result = PQgetResult(self->pgcnx->cnx);
4033                Py_END_ALLOW_THREADS;
4034
4035                if (PQresultStatus(result) == PGRES_COMMAND_OK)
4036                {
4037                        char   *temp;
4038                        long    num_rows;
4039
4040                        temp = PQcmdTuples(result);
4041                        num_rows = temp[0] ? atol(temp) : -1;
4042                        ret = PyInt_FromLong(num_rows);
4043                }
4044                else
4045                {
4046                        if (!errormsg) errormsg = PQerrorMessage(self->pgcnx->cnx);
4047                        PyErr_SetString(PyExc_IOError, errormsg);
4048                        ret = NULL;
4049                }
4050
4051                PQclear(self->result);
4052                self->result = NULL;
4053                self->result_type = RESULT_EMPTY;
4054        }
4055
4056        return ret; /* None or number of rows */
4057}
4058
4059/* get copy data */
4060static char sourceGetData__doc__[] =
4061"getdata(decode) -- receive data to server during copy to stdout";
4062
4063static PyObject *
4064sourceGetData(sourceObject *self, PyObject *args)
4065{
4066        int                *decode = 0; /* decode flag */
4067        char       *buffer; /* the copied buffer as encoded byte string */
4068        Py_ssize_t      nbytes; /* length of the byte string */
4069        PyObject   *ret; /* return value */
4070
4071        /* checks validity */
4072        if (!check_source_obj(self, CHECK_CNX))
4073                return NULL;
4074
4075        /* make sure that the connection object is valid */
4076        if (!self->pgcnx->cnx)
4077                return NULL;
4078
4079        if (!PyArg_ParseTuple(args, "|i", &decode))
4080                return NULL;
4081
4082        /* checks validity */
4083        if (!check_source_obj(self, CHECK_CNX | CHECK_RESULT) ||
4084                        PQresultStatus(self->result) != PGRES_COPY_OUT)
4085        {
4086                PyErr_SetString(PyExc_IOError,
4087                        "Connection is invalid or not in copy_out state");
4088                return NULL;
4089        }
4090
4091        nbytes = PQgetCopyData(self->pgcnx->cnx, &buffer, 0);
4092
4093        if (!nbytes || nbytes < -1) /* an error occurred */
4094        {
4095                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->pgcnx->cnx));
4096                return NULL;
4097        }
4098
4099        if (nbytes == -1) /* copy is done */
4100        {
4101                PGresult   *result; /* final result of the operation */
4102
4103                Py_BEGIN_ALLOW_THREADS;
4104                result = PQgetResult(self->pgcnx->cnx);
4105                Py_END_ALLOW_THREADS;
4106
4107                if (PQresultStatus(result) == PGRES_COMMAND_OK)
4108                {
4109                        char   *temp;
4110                        long    num_rows;
4111
4112                        temp = PQcmdTuples(result);
4113                        num_rows = temp[0] ? atol(temp) : -1;
4114                        ret = PyInt_FromLong(num_rows);
4115                }
4116                else
4117                {
4118                        PyErr_SetString(PyExc_IOError, PQerrorMessage(self->pgcnx->cnx));
4119                        ret = NULL;
4120                }
4121
4122                PQclear(self->result);
4123                self->result = NULL;
4124                self->result_type = RESULT_EMPTY;
4125        }
4126        else /* a row has been returned */
4127        {
4128                ret = decode ? get_decoded_string(
4129                                buffer, nbytes, PQclientEncoding(self->pgcnx->cnx)) :
4130                        PyBytes_FromStringAndSize(buffer, nbytes);
4131                PQfreemem(buffer);
4132        }
4133
4134        return ret; /* buffer or number of rows */
4135}
4136
4137/* finds field number from string/integer (internal use only) */
4138static int
4139sourceFieldindex(sourceObject *self, PyObject *param, const char *usage)
4140{
4141        int                     num;
4142
4143        /* checks validity */
4144        if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
4145                return -1;
4146
4147        /* gets field number */
4148        if (PyStr_Check(param))
4149                num = PQfnumber(self->result, PyBytes_AsString(param));
4150        else if (PyInt_Check(param))
4151                num = (int)PyInt_AsLong(param);
4152        else
4153        {
4154                PyErr_SetString(PyExc_TypeError, usage);
4155                return -1;
4156        }
4157
4158        /* checks field validity */
4159        if (num < 0 || num >= self->num_fields)
4160        {
4161                PyErr_SetString(PyExc_ValueError, "Unknown field");
4162                return -1;
4163        }
4164
4165        return num;
4166}
4167
4168/* builds field information from position (internal use only) */
4169static PyObject *
4170pgsource_buildinfo(sourceObject *self, int num)
4171{
4172        PyObject *result;
4173
4174        /* allocates tuple */
4175        result = PyTuple_New(5);
4176        if (!result)
4177                return NULL;
4178
4179        /* affects field information */
4180        PyTuple_SET_ITEM(result, 0, PyInt_FromLong(num));
4181        PyTuple_SET_ITEM(result, 1,
4182                PyStr_FromString(PQfname(self->result, num)));
4183        PyTuple_SET_ITEM(result, 2,
4184                PyInt_FromLong(PQftype(self->result, num)));
4185        PyTuple_SET_ITEM(result, 3,
4186                PyInt_FromLong(PQfsize(self->result, num)));
4187        PyTuple_SET_ITEM(result, 4,
4188                PyInt_FromLong(PQfmod(self->result, num)));
4189
4190        return result;
4191}
4192
4193/* lists fields info */
4194static char sourceListInfo__doc__[] =
4195"listinfo() -- get information for all fields (position, name, type oid)";
4196
4197static PyObject *
4198sourceListInfo(sourceObject *self, PyObject *noargs)
4199{
4200        int                     i;
4201        PyObject   *result,
4202                           *info;
4203
4204        /* checks validity */
4205        if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
4206                return NULL;
4207
4208        /* builds result */
4209        if (!(result = PyTuple_New(self->num_fields)))
4210                return NULL;
4211
4212        for (i = 0; i < self->num_fields; ++i)
4213        {
4214                info = pgsource_buildinfo(self, i);
4215                if (!info)
4216                {
4217                        Py_DECREF(result);
4218                        return NULL;
4219                }
4220                PyTuple_SET_ITEM(result, i, info);
4221        }
4222
4223        /* returns result */
4224        return result;
4225};
4226
4227/* list fields information for last result */
4228static char sourceFieldInfo__doc__[] =
4229"fieldinfo(desc) -- get specified field info (position, name, type oid)";
4230
4231static PyObject *
4232sourceFieldInfo(sourceObject *self, PyObject *desc)
4233{
4234        int                     num;
4235
4236        /* checks args and validity */
4237        if ((num = sourceFieldindex(self, desc,
4238                        "Method fieldinfo() needs a string or integer as argument")) == -1)
4239                return NULL;
4240
4241        /* returns result */
4242        return pgsource_buildinfo(self, num);
4243};
4244
4245/* retrieve field value */
4246static char sourceField__doc__[] =
4247"field(desc) -- return specified field value";
4248
4249static PyObject *
4250sourceField(sourceObject *self, PyObject *desc)
4251{
4252        int                     num;
4253
4254        /* checks args and validity */
4255        if ((num = sourceFieldindex(self, desc,
4256                        "Method field() needs a string or integer as argument")) == -1)
4257                return NULL;
4258
4259        return PyStr_FromString(
4260                PQgetvalue(self->result, self->current_row, num));
4261}
4262
4263/* get the list of source object attributes */
4264static PyObject *
4265sourceDir(connObject *self, PyObject *noargs)
4266{
4267        PyObject *attrs;
4268
4269        attrs = PyObject_Dir(PyObject_Type((PyObject *)self));
4270        PyObject_CallMethod(attrs, "extend", "[sssss]",
4271                "pgcnx", "arraysize", "resulttype", "ntuples", "nfields");
4272
4273        return attrs;
4274}
4275
4276/* source object methods */
4277static PyMethodDef sourceMethods[] = {
4278        {"__dir__", (PyCFunction) sourceDir,  METH_NOARGS, NULL},
4279        {"close", (PyCFunction) sourceClose, METH_NOARGS, sourceClose__doc__},
4280        {"execute", (PyCFunction) sourceExecute, METH_O, sourceExecute__doc__},
4281        {"oidstatus", (PyCFunction) sourceStatusOID, METH_NOARGS,
4282                        sourceStatusOID__doc__},
4283        {"fetch", (PyCFunction) sourceFetch, METH_VARARGS,
4284                        sourceFetch__doc__},
4285        {"movefirst", (PyCFunction) sourceMoveFirst, METH_NOARGS,
4286                        sourceMoveFirst__doc__},
4287        {"movelast", (PyCFunction) sourceMoveLast, METH_NOARGS,
4288                        sourceMoveLast__doc__},
4289        {"movenext", (PyCFunction) sourceMoveNext, METH_NOARGS,
4290                        sourceMoveNext__doc__},
4291        {"moveprev", (PyCFunction) sourceMovePrev, METH_NOARGS,
4292                        sourceMovePrev__doc__},
4293        {"putdata", (PyCFunction) sourcePutData, METH_O, sourcePutData__doc__},
4294        {"getdata", (PyCFunction) sourceGetData, METH_VARARGS,
4295                        sourceGetData__doc__},
4296        {"field", (PyCFunction) sourceField, METH_O,
4297                        sourceField__doc__},
4298        {"fieldinfo", (PyCFunction) sourceFieldInfo, METH_O,
4299                        sourceFieldInfo__doc__},
4300        {"listinfo", (PyCFunction) sourceListInfo, METH_NOARGS,
4301                        sourceListInfo__doc__},
4302        {NULL, NULL}
4303};
4304
4305/* gets source object attributes */
4306static PyObject *
4307sourceGetAttr(sourceObject *self, PyObject *nameobj)
4308{
4309        const char *name = PyStr_AsString(nameobj);
4310
4311        /* pg connection object */
4312        if (!strcmp(name, "pgcnx"))
4313        {
4314                if (check_source_obj(self, 0))
4315                {
4316                        Py_INCREF(self->pgcnx);
4317                        return (PyObject *) (self->pgcnx);
4318                }
4319                Py_INCREF(Py_None);
4320                return Py_None;
4321        }
4322
4323        /* arraysize */
4324        if (!strcmp(name, "arraysize"))
4325                return PyInt_FromLong(self->arraysize);
4326
4327        /* resulttype */
4328        if (!strcmp(name, "resulttype"))
4329                return PyInt_FromLong(self->result_type);
4330
4331        /* ntuples */
4332        if (!strcmp(name, "ntuples"))
4333                return PyInt_FromLong(self->max_row);
4334
4335        /* nfields */
4336        if (!strcmp(name, "nfields"))
4337                return PyInt_FromLong(self->num_fields);
4338
4339        /* seeks name in methods (fallback) */
4340        return PyObject_GenericGetAttr((PyObject *) self, nameobj);
4341}
4342
4343/* sets query object attributes */
4344static int
4345sourceSetAttr(sourceObject *self, char *name, PyObject *v)
4346{
4347        /* arraysize */
4348        if (!strcmp(name, "arraysize"))
4349        {
4350                if (!PyInt_Check(v))
4351                {
4352                        PyErr_SetString(PyExc_TypeError, "arraysize must be integer");
4353                        return -1;
4354                }
4355
4356                self->arraysize = PyInt_AsLong(v);
4357                return 0;
4358        }
4359
4360        /* unknown attribute */
4361        PyErr_SetString(PyExc_TypeError, "Not a writable attribute");
4362        return -1;
4363}
4364
4365/* return source object as string in human readable form */
4366static PyObject *
4367sourceStr(sourceObject *self)
4368{
4369        switch (self->result_type)
4370        {
4371                case RESULT_DQL:
4372                        return format_result(self->result);
4373                case RESULT_DDL:
4374                case RESULT_DML:
4375                        return PyStr_FromString(PQcmdStatus(self->result));
4376                case RESULT_EMPTY:
4377                default:
4378                        return PyStr_FromString("(empty PostgreSQL source object)");
4379        }
4380}
4381
4382static char source__doc__[] = "PyGreSQL source object";
4383
4384/* source type definition */
4385static PyTypeObject sourceType = {
4386        PyVarObject_HEAD_INIT(NULL, 0)
4387        "pgdb.Source",                                  /* tp_name */
4388        sizeof(sourceObject),                   /* tp_basicsize */
4389        0,                                                              /* tp_itemsize */
4390        /* methods */
4391        (destructor) sourceDealloc,             /* tp_dealloc */
4392        0,                                                              /* tp_print */
4393        0,                                                              /* tp_getattr */
4394        (setattrfunc) sourceSetAttr,    /* tp_setattr */
4395        0,                                                              /* tp_compare */
4396        0,                                                              /* tp_repr */
4397        0,                                                              /* tp_as_number */
4398        0,                                                              /* tp_as_sequence */
4399        0,                                                              /* tp_as_mapping */
4400        0,                                                              /* tp_hash */
4401        0,                                                              /* tp_call */
4402        (reprfunc) sourceStr,                   /* tp_str */
4403        (getattrofunc) sourceGetAttr,   /* tp_getattro */
4404        0,                                                              /* tp_setattro */
4405        0,                                                              /* tp_as_buffer */
4406        Py_TPFLAGS_DEFAULT,                             /* tp_flags */
4407        source__doc__,                                  /* tp_doc */
4408        0,                                                              /* tp_traverse */
4409        0,                                                              /* tp_clear */
4410        0,                                                              /* tp_richcompare */
4411        0,                                                              /* tp_weaklistoffset */
4412        0,                                                              /* tp_iter */
4413        0,                                                              /* tp_iternext */
4414        sourceMethods,                                  /* tp_methods */
4415};
4416
4417/* connects to a database */
4418static char pgConnect__doc__[] =
4419"connect(dbname, host, port, opt) -- connect to a PostgreSQL database\n\n"
4420"The connection uses the specified parameters (optional, keywords aware).\n";
4421
4422static PyObject *
4423pgConnect(PyObject *self, PyObject *args, PyObject *dict)
4424{
4425        static const char *kwlist[] = {"dbname", "host", "port", "opt",
4426        "user", "passwd", NULL};
4427
4428        char       *pghost,
4429                           *pgopt,
4430                           *pgdbname,
4431                           *pguser,
4432                           *pgpasswd;
4433        int                     pgport;
4434        char            port_buffer[20];
4435        connObject *npgobj;
4436
4437        pghost = pgopt = pgdbname = pguser = pgpasswd = NULL;
4438        pgport = -1;
4439
4440        /*
4441         * parses standard arguments With the right compiler warnings, this
4442         * will issue a diagnostic. There is really no way around it.  If I
4443         * don't declare kwlist as const char *kwlist[] then it complains when
4444         * I try to assign all those constant strings to it.
4445         */
4446        if (!PyArg_ParseTupleAndKeywords(args, dict, "|zzizzz", (char **) kwlist,
4447                &pgdbname, &pghost, &pgport, &pgopt, &pguser, &pgpasswd))
4448                return NULL;
4449
4450#ifdef DEFAULT_VARS
4451        /* handles defaults variables (for uninitialised vars) */
4452        if ((!pghost) && (pg_default_host != Py_None))
4453                pghost = PyBytes_AsString(pg_default_host);
4454
4455        if ((pgport == -1) && (pg_default_port != Py_None))
4456                pgport = (int)PyInt_AsLong(pg_default_port);
4457
4458        if ((!pgopt) && (pg_default_opt != Py_None))
4459                pgopt = PyBytes_AsString(pg_default_opt);
4460
4461        if ((!pgdbname) && (pg_default_base != Py_None))
4462                pgdbname = PyBytes_AsString(pg_default_base);
4463
4464        if ((!pguser) && (pg_default_user != Py_None))
4465                pguser = PyBytes_AsString(pg_default_user);
4466
4467        if ((!pgpasswd) && (pg_default_passwd != Py_None))
4468                pgpasswd = PyBytes_AsString(pg_default_passwd);
4469#endif /* DEFAULT_VARS */
4470
4471        if (!(npgobj = PyObject_NEW(connObject, &connType)))
4472        {
4473                set_error_msg(InternalError, "Can't create new connection object");
4474                return NULL;
4475        }
4476
4477        npgobj->valid = 1;
4478        npgobj->cnx = NULL;
4479        npgobj->date_format = date_format;
4480        npgobj->cast_hook = NULL;
4481        npgobj->notice_receiver = NULL;
4482
4483        if (pgport != -1)
4484        {
4485                memset(port_buffer, 0, sizeof(port_buffer));
4486                sprintf(port_buffer, "%d", pgport);
4487        }
4488
4489        Py_BEGIN_ALLOW_THREADS
4490        npgobj->cnx = PQsetdbLogin(pghost, pgport == -1 ? NULL : port_buffer,
4491                pgopt, NULL, pgdbname, pguser, pgpasswd);
4492        Py_END_ALLOW_THREADS
4493
4494        if (PQstatus(npgobj->cnx) == CONNECTION_BAD)
4495        {
4496                set_error(InternalError, "Cannot connect", npgobj->cnx, NULL);
4497                Py_XDECREF(npgobj);
4498                return NULL;
4499        }
4500
4501        return (PyObject *) npgobj;
4502}
4503
4504static void
4505queryDealloc(queryObject *self)
4506{
4507        Py_XDECREF(self->pgcnx);
4508        if (self->result)
4509                PQclear(self->result);
4510
4511        PyObject_Del(self);
4512}
4513
4514/* get number of rows */
4515static char queryNTuples__doc__[] =
4516"ntuples() -- return number of tuples returned by query";
4517
4518static PyObject *
4519queryNTuples(queryObject *self, PyObject *noargs)
4520{
4521        return PyInt_FromLong((long) PQntuples(self->result));
4522}
4523
4524/* list fields names from query result */
4525static char queryListFields__doc__[] =
4526"listfields() -- List field names from result";
4527
4528static PyObject *
4529queryListFields(queryObject *self, PyObject *noargs)
4530{
4531        int                     i,
4532                                n;
4533        char       *name;
4534        PyObject   *fieldstuple,
4535                           *str;
4536
4537        /* builds tuple */
4538        n = PQnfields(self->result);
4539        fieldstuple = PyTuple_New(n);
4540
4541        for (i = 0; i < n; ++i)
4542        {
4543                name = PQfname(self->result, i);
4544                str = PyStr_FromString(name);
4545                PyTuple_SET_ITEM(fieldstuple, i, str);
4546        }
4547
4548        return fieldstuple;
4549}
4550
4551/* get field name from last result */
4552static char queryFieldName__doc__[] =
4553"fieldname(num) -- return name of field from result from its position";
4554
4555static PyObject *
4556queryFieldName(queryObject *self, PyObject *args)
4557{
4558        int             i;
4559        char   *name;
4560
4561        /* gets args */
4562        if (!PyArg_ParseTuple(args, "i", &i))
4563        {
4564                PyErr_SetString(PyExc_TypeError,
4565                        "Method fieldname() takes an integer as argument");
4566                return NULL;
4567        }
4568
4569        /* checks number validity */
4570        if (i >= PQnfields(self->result))
4571        {
4572                PyErr_SetString(PyExc_ValueError, "Invalid field number");
4573                return NULL;
4574        }
4575
4576        /* gets fields name and builds object */
4577        name = PQfname(self->result, i);
4578        return PyStr_FromString(name);
4579}
4580
4581/* gets fields number from name in last result */
4582static char queryFieldNumber__doc__[] =
4583"fieldnum(name) -- return position in query for field from its name";
4584
4585static PyObject *
4586queryFieldNumber(queryObject *self, PyObject *args)
4587{
4588        int             num;
4589        char   *name;
4590
4591        /* gets args */
4592        if (!PyArg_ParseTuple(args, "s", &name))
4593        {
4594                PyErr_SetString(PyExc_TypeError,
4595                        "Method fieldnum() takes a string as argument");
4596                return NULL;
4597        }
4598
4599        /* gets field number */
4600        if ((num = PQfnumber(self->result, name)) == -1)
4601        {
4602                PyErr_SetString(PyExc_ValueError, "Unknown field");
4603                return NULL;
4604        }
4605
4606        return PyInt_FromLong(num);
4607}
4608
4609/* retrieves last result */
4610static char queryGetResult__doc__[] =
4611"getresult() -- Get the result of a query\n\n"
4612"The result is returned as a list of rows, each one a tuple of fields\n"
4613"in the order returned by the server.\n";
4614
4615static PyObject *
4616queryGetResult(queryObject *self, PyObject *noargs)
4617{
4618        PyObject   *reslist;
4619        int                     i, m, n, *col_types;
4620        int                     encoding = self->encoding;
4621
4622        /* stores result in tuple */
4623        m = PQntuples(self->result);
4624        n = PQnfields(self->result);
4625        if (!(reslist = PyList_New(m))) return NULL;
4626
4627        if (!(col_types = get_col_types(self->result, n))) return NULL;
4628
4629        for (i = 0; i < m; ++i)
4630        {
4631                PyObject   *rowtuple;
4632                int                     j;
4633
4634                if (!(rowtuple = PyTuple_New(n)))
4635                {
4636                        Py_DECREF(reslist);
4637                        reslist = NULL;
4638                        goto exit;
4639                }
4640
4641                for (j = 0; j < n; ++j)
4642                {
4643                        PyObject * val;
4644
4645                        if (PQgetisnull(self->result, i, j))
4646                        {
4647                                Py_INCREF(Py_None);
4648                                val = Py_None;
4649                        }
4650                        else /* not null */
4651                        {
4652                                /* get the string representation of the value */
4653                                /* note: this is always null-terminated text format */
4654                                char   *s = PQgetvalue(self->result, i, j);
4655                                /* get the PyGreSQL type of the column */
4656                                int             type = col_types[j];
4657
4658                                if (type & PYGRES_ARRAY)
4659                                        val = cast_array(s, PQgetlength(self->result, i, j),
4660                                                encoding, type, NULL, 0);
4661                                else if (type == PYGRES_BYTEA)
4662                                        val = cast_bytea_text(s);
4663                                else if (type == PYGRES_OTHER)
4664                                        val = cast_other(s,
4665                                                PQgetlength(self->result, i, j), encoding,
4666                                                PQftype(self->result, j), self->pgcnx->cast_hook);
4667                                else if (type & PYGRES_TEXT)
4668                                        val = cast_sized_text(s, PQgetlength(self->result, i, j),
4669                                                encoding, type);
4670                                else
4671                                        val = cast_unsized_simple(s, type);
4672                        }
4673
4674                        if (!val)
4675                        {
4676                                Py_DECREF(reslist);
4677                                Py_DECREF(rowtuple);
4678                                reslist = NULL;
4679                                goto exit;
4680                        }
4681
4682                        PyTuple_SET_ITEM(rowtuple, j, val);
4683                }
4684
4685                PyList_SET_ITEM(reslist, i, rowtuple);
4686        }
4687
4688exit:
4689        PyMem_Free(col_types);
4690
4691        /* returns list */
4692        return reslist;
4693}
4694
4695/* retrieves last result as a list of dictionaries*/
4696static char queryDictResult__doc__[] =
4697"dictresult() -- Get the result of a query\n\n"
4698"The result is returned as a list of rows, each one a dictionary with\n"
4699"the field names used as the labels.\n";
4700
4701static PyObject *
4702queryDictResult(queryObject *self, PyObject *noargs)
4703{
4704        PyObject   *reslist;
4705        int                     i,
4706                                m,
4707                                n,
4708                           *col_types;
4709        int                     encoding = self->encoding;
4710
4711        /* stores result in list */
4712        m = PQntuples(self->result);
4713        n = PQnfields(self->result);
4714        if (!(reslist = PyList_New(m))) return NULL;
4715
4716        if (!(col_types = get_col_types(self->result, n))) return NULL;
4717
4718        for (i = 0; i < m; ++i)
4719        {
4720                PyObject   *dict;
4721                int                     j;
4722
4723                if (!(dict = PyDict_New()))
4724                {
4725                        Py_DECREF(reslist);
4726                        reslist = NULL;
4727                        goto exit;
4728                }
4729
4730                for (j = 0; j < n; ++j)
4731                {
4732                        PyObject * val;
4733
4734                        if (PQgetisnull(self->result, i, j))
4735                        {
4736                                Py_INCREF(Py_None);
4737                                val = Py_None;
4738                        }
4739                        else /* not null */
4740                        {
4741                                /* get the string representation of the value */
4742                                /* note: this is always null-terminated text format */
4743                                char   *s = PQgetvalue(self->result, i, j);
4744                                /* get the PyGreSQL type of the column */
4745                                int             type = col_types[j];
4746
4747                                if (type & PYGRES_ARRAY)
4748                                        val = cast_array(s, PQgetlength(self->result, i, j),
4749                                                encoding, type, NULL, 0);
4750                                else if (type == PYGRES_BYTEA)
4751                                        val = cast_bytea_text(s);
4752                                else if (type == PYGRES_OTHER)
4753                                        val = cast_other(s,
4754                                                PQgetlength(self->result, i, j), encoding,
4755                                                PQftype(self->result, j), self->pgcnx->cast_hook);
4756                                else if (type & PYGRES_TEXT)
4757                                        val = cast_sized_text(s, PQgetlength(self->result, i, j),
4758                                                encoding, type);
4759                                else
4760                                        val = cast_unsized_simple(s, type);
4761                        }
4762
4763                        if (!val)
4764                        {
4765                                Py_DECREF(dict);
4766                                Py_DECREF(reslist);
4767                                reslist = NULL;
4768                                goto exit;
4769                        }
4770
4771                        PyDict_SetItemString(dict, PQfname(self->result, j), val);
4772                        Py_DECREF(val);
4773                }
4774
4775                PyList_SET_ITEM(reslist, i, dict);
4776        }
4777
4778exit:
4779        PyMem_Free(col_types);
4780
4781        /* returns list */
4782        return reslist;
4783}
4784
4785/* retrieves last result as named tuples */
4786static char queryNamedResult__doc__[] =
4787"namedresult() -- Get the result of a query\n\n"
4788"The result is returned as a list of rows, each one a tuple of fields\n"
4789"in the order returned by the server.\n";
4790
4791static PyObject *
4792queryNamedResult(queryObject *self, PyObject *noargs)
4793{
4794        PyObject   *ret;
4795
4796        if (namedresult)
4797        {
4798                ret = PyObject_CallFunction(namedresult, "(O)", self);
4799
4800                if (ret == NULL)
4801                        return NULL;
4802                }
4803        else
4804        {
4805                ret = queryGetResult(self, NULL);
4806        }
4807
4808        return ret;
4809}
4810
4811/* gets notice object attributes */
4812static PyObject *
4813noticeGetAttr(noticeObject *self, PyObject *nameobj)
4814{
4815        PGresult const *res = self->res;
4816        const char *name = PyStr_AsString(nameobj);
4817        int fieldcode;
4818
4819        if (!res)
4820        {
4821                PyErr_SetString(PyExc_TypeError, "Cannot get current notice");
4822                return NULL;
4823        }
4824
4825        /* pg connection object */
4826        if (!strcmp(name, "pgcnx"))
4827        {
4828                if (self->pgcnx && check_cnx_obj(self->pgcnx))
4829                {
4830                        Py_INCREF(self->pgcnx);
4831                        return (PyObject *) self->pgcnx;
4832                }
4833                else
4834                {
4835                        Py_INCREF(Py_None);
4836                        return Py_None;
4837                }
4838        }
4839
4840        /* full message */
4841        if (!strcmp(name, "message"))
4842                return PyStr_FromString(PQresultErrorMessage(res));
4843
4844        /* other possible fields */
4845        fieldcode = 0;
4846        if (!strcmp(name, "severity"))
4847                fieldcode = PG_DIAG_SEVERITY;
4848        else if (!strcmp(name, "primary"))
4849                fieldcode = PG_DIAG_MESSAGE_PRIMARY;
4850        else if (!strcmp(name, "detail"))
4851                fieldcode = PG_DIAG_MESSAGE_DETAIL;
4852        else if (!strcmp(name, "hint"))
4853                fieldcode = PG_DIAG_MESSAGE_HINT;
4854        if (fieldcode)
4855        {
4856                char *s = PQresultErrorField(res, fieldcode);
4857                if (s)
4858                        return PyStr_FromString(s);
4859                else
4860                {
4861                        Py_INCREF(Py_None); return Py_None;
4862                }
4863        }
4864
4865        return PyObject_GenericGetAttr((PyObject *) self, nameobj);
4866}
4867
4868/* return notice as string in human readable form */
4869static PyObject *
4870noticeStr(noticeObject *self)
4871{
4872        return noticeGetAttr(self, PyBytes_FromString("message"));
4873}
4874
4875/* get the list of notice attributes */
4876static PyObject *
4877noticeDir(noticeObject *self, PyObject *noargs)
4878{
4879        PyObject *attrs;
4880
4881        attrs = PyObject_Dir(PyObject_Type((PyObject *)self));
4882        PyObject_CallMethod(attrs, "extend", "[ssssss]",
4883                "pgcnx", "severity", "message", "primary", "detail", "hint");
4884
4885        return attrs;
4886}
4887
4888/* notice object methods */
4889static struct PyMethodDef noticeMethods[] = {
4890        {"__dir__", (PyCFunction) noticeDir,  METH_NOARGS, NULL},
4891        {NULL, NULL}
4892};
4893
4894/* notice type definition */
4895static PyTypeObject noticeType = {
4896        PyVarObject_HEAD_INIT(NULL, 0)
4897        "pg.Notice",                                    /* tp_name */
4898        sizeof(noticeObject),                   /* tp_basicsize */
4899        0,                                                              /* tp_itemsize */
4900        /* methods */
4901        0,                                                              /* tp_dealloc */
4902        0,                                                              /* tp_print */
4903        0,                                                              /* tp_getattr */
4904        0,                                                              /* tp_setattr */
4905        0,                                                              /* tp_compare */
4906        0,                                                              /* tp_repr */
4907        0,                                                              /* tp_as_number */
4908        0,                                                              /* tp_as_sequence */
4909        0,                                                              /* tp_as_mapping */
4910        0,                                                              /* tp_hash */
4911        0,                                                              /* tp_call */
4912        (reprfunc) noticeStr,                   /* tp_str */
4913        (getattrofunc) noticeGetAttr,   /* tp_getattro */
4914        PyObject_GenericSetAttr,                /* tp_setattro */
4915        0,                                                              /* tp_as_buffer */
4916        Py_TPFLAGS_DEFAULT,                             /* tp_flags */
4917        0,                                                              /* tp_doc */
4918        0,                                                              /* tp_traverse */
4919        0,                                                              /* tp_clear */
4920        0,                                                              /* tp_richcompare */
4921        0,                                                              /* tp_weaklistoffset */
4922        0,                                                              /* tp_iter */
4923        0,                                                              /* tp_iternext */
4924        noticeMethods,                                  /* tp_methods */
4925};
4926
4927/* query object methods */
4928static struct PyMethodDef queryMethods[] = {
4929        {"getresult", (PyCFunction) queryGetResult, METH_NOARGS,
4930                        queryGetResult__doc__},
4931        {"dictresult", (PyCFunction) queryDictResult, METH_NOARGS,
4932                        queryDictResult__doc__},
4933        {"namedresult", (PyCFunction) queryNamedResult, METH_NOARGS,
4934                        queryNamedResult__doc__},
4935        {"fieldname", (PyCFunction) queryFieldName, METH_VARARGS,
4936                         queryFieldName__doc__},
4937        {"fieldnum", (PyCFunction) queryFieldNumber, METH_VARARGS,
4938                        queryFieldNumber__doc__},
4939        {"listfields", (PyCFunction) queryListFields, METH_NOARGS,
4940                        queryListFields__doc__},
4941        {"ntuples", (PyCFunction) queryNTuples, METH_NOARGS,
4942                        queryNTuples__doc__},
4943        {NULL, NULL}
4944};
4945
4946/* query type definition */
4947static PyTypeObject queryType = {
4948        PyVarObject_HEAD_INIT(NULL, 0)
4949        "pg.Query",                                             /* tp_name */
4950        sizeof(queryObject),                    /* tp_basicsize */
4951        0,                                                              /* tp_itemsize */
4952        /* methods */
4953        (destructor) queryDealloc,              /* tp_dealloc */
4954        0,                                                              /* tp_print */
4955        0,                                                              /* tp_getattr */
4956        0,                                                              /* tp_setattr */
4957        0,                                                              /* tp_compare */
4958        0,                                                              /* tp_repr */
4959        0,                                                              /* tp_as_number */
4960        0,                                                              /* tp_as_sequence */
4961        0,                                                              /* tp_as_mapping */
4962        0,                                                              /* tp_hash */
4963        0,                                                              /* tp_call */
4964        (reprfunc) queryStr,                    /* tp_str */
4965        PyObject_GenericGetAttr,                /* tp_getattro */
4966        0,                                                              /* tp_setattro */
4967        0,                                                              /* tp_as_buffer */
4968        Py_TPFLAGS_DEFAULT,                             /* tp_flags */
4969        0,                                                              /* tp_doc */
4970        0,                                                              /* tp_traverse */
4971        0,                                                              /* tp_clear */
4972        0,                                                              /* tp_richcompare */
4973        0,                                                              /* tp_weaklistoffset */
4974        0,                                                              /* tp_iter */
4975        0,                                                              /* tp_iternext */
4976        queryMethods,                                   /* tp_methods */
4977};
4978
4979/* --------------------------------------------------------------------- */
4980
4981/* MODULE FUNCTIONS */
4982
4983/* escape string */
4984static char pgEscapeString__doc__[] =
4985"escape_string(string) -- escape a string for use within SQL";
4986
4987static PyObject *
4988pgEscapeString(PyObject *self, PyObject *string)
4989{
4990        PyObject   *tmp_obj = NULL, /* auxiliary string object */
4991                           *to_obj; /* string object to return */
4992        char       *from, /* our string argument as encoded string */
4993                           *to; /* the result as encoded string */
4994        Py_ssize_t      from_length; /* length of string */
4995        size_t          to_length; /* length of result */
4996        int                     encoding = -1; /* client encoding */
4997
4998        if (PyBytes_Check(string))
4999        {
5000                PyBytes_AsStringAndSize(string, &from, &from_length);
5001        }
5002        else if (PyUnicode_Check(string))
5003        {
5004                encoding = pg_encoding_ascii;
5005                tmp_obj = get_encoded_string(string, encoding);
5006                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
5007                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
5008        }
5009        else
5010        {
5011                PyErr_SetString(PyExc_TypeError,
5012                        "Method escape_string() expects a string as argument");
5013                return NULL;
5014        }
5015
5016        to_length = 2*from_length + 1;
5017        if ((Py_ssize_t)to_length < from_length) /* overflow */
5018        {
5019                to_length = from_length;
5020                from_length = (from_length - 1)/2;
5021        }
5022        to = (char *)PyMem_Malloc(to_length);
5023        to_length = (int)PQescapeString(to, from, (size_t)from_length);
5024
5025        Py_XDECREF(tmp_obj);
5026
5027        if (encoding == -1)
5028                to_obj = PyBytes_FromStringAndSize(to, to_length);
5029        else
5030                to_obj = get_decoded_string(to, to_length, encoding);
5031        PyMem_Free(to);
5032        return to_obj;
5033}
5034
5035/* escape bytea */
5036static char pgEscapeBytea__doc__[] =
5037"escape_bytea(data) -- escape binary data for use within SQL as type bytea";
5038
5039static PyObject *
5040pgEscapeBytea(PyObject *self, PyObject *data)
5041{
5042        PyObject   *tmp_obj = NULL, /* auxiliary string object */
5043                           *to_obj; /* string object to return */
5044        char       *from, /* our string argument as encoded string */
5045                           *to; /* the result as encoded string */
5046        Py_ssize_t      from_length; /* length of string */
5047        size_t          to_length; /* length of result */
5048        int                     encoding = -1; /* client encoding */
5049
5050        if (PyBytes_Check(data))
5051        {
5052                PyBytes_AsStringAndSize(data, &from, &from_length);
5053        }
5054        else if (PyUnicode_Check(data))
5055        {
5056                encoding = pg_encoding_ascii;
5057                tmp_obj = get_encoded_string(data, encoding);
5058                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
5059                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
5060        }
5061        else
5062        {
5063                PyErr_SetString(PyExc_TypeError,
5064                        "Method escape_bytea() expects a string as argument");
5065                return NULL;
5066        }
5067
5068        to = (char *)PQescapeBytea(
5069                (unsigned char*)from, (size_t)from_length, &to_length);
5070
5071        Py_XDECREF(tmp_obj);
5072
5073        if (encoding == -1)
5074                to_obj = PyBytes_FromStringAndSize(to, to_length - 1);
5075        else
5076                to_obj = get_decoded_string(to, to_length - 1, encoding);
5077        if (to)
5078                PQfreemem(to);
5079        return to_obj;
5080}
5081
5082/* unescape bytea */
5083static char pgUnescapeBytea__doc__[] =
5084"unescape_bytea(string) -- unescape bytea data retrieved as text";
5085
5086static PyObject *
5087pgUnescapeBytea(PyObject *self, PyObject *data)
5088{
5089        PyObject   *tmp_obj = NULL, /* auxiliary string object */
5090                           *to_obj; /* string object to return */
5091        char       *from, /* our string argument as encoded string */
5092                           *to; /* the result as encoded string */
5093        Py_ssize_t      from_length; /* length of string */
5094        size_t          to_length; /* length of result */
5095
5096        if (PyBytes_Check(data))
5097        {
5098                PyBytes_AsStringAndSize(data, &from, &from_length);
5099        }
5100        else if (PyUnicode_Check(data))
5101        {
5102                tmp_obj = get_encoded_string(data, pg_encoding_ascii);
5103                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
5104                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
5105        }
5106        else
5107        {
5108                PyErr_SetString(PyExc_TypeError,
5109                        "Method unescape_bytea() expects a string as argument");
5110                return NULL;
5111        }
5112
5113        to = (char *)PQunescapeBytea((unsigned char*)from, &to_length);
5114
5115        Py_XDECREF(tmp_obj);
5116
5117        if (!to) return PyErr_NoMemory();
5118
5119        to_obj = PyBytes_FromStringAndSize(to, to_length);
5120        PQfreemem(to);
5121
5122        return to_obj;
5123}
5124
5125/* set fixed datestyle */
5126static char pgSetDatestyle__doc__[] =
5127"set_datestyle(style) -- set which style is assumed";
5128
5129static PyObject *
5130pgSetDatestyle(PyObject *self, PyObject *args)
5131{
5132        const char         *datestyle = NULL;
5133
5134        /* gets arguments */
5135        if (!PyArg_ParseTuple(args, "z", &datestyle))
5136        {
5137                PyErr_SetString(PyExc_TypeError,
5138                        "Function set_datestyle() expects a string or None as argument");
5139                return NULL;
5140        }
5141
5142        date_format = datestyle ? date_style_to_format(datestyle) : NULL;
5143
5144        Py_INCREF(Py_None); return Py_None;
5145}
5146
5147/* get fixed datestyle */
5148static char pgGetDatestyle__doc__[] =
5149"get_datestyle() -- get which date style is assumed";
5150
5151static PyObject *
5152pgGetDatestyle(PyObject *self, PyObject *noargs)
5153{
5154        if (date_format)
5155        {
5156                return PyStr_FromString(date_format_to_style(date_format));
5157        }
5158        else
5159        {
5160                Py_INCREF(Py_None); return Py_None;
5161        }
5162}
5163
5164/* get decimal point */
5165static char pgGetDecimalPoint__doc__[] =
5166"get_decimal_point() -- get decimal point to be used for money values";
5167
5168static PyObject *
5169pgGetDecimalPoint(PyObject *self, PyObject *noargs)
5170{
5171        PyObject *ret;
5172        char s[2];
5173
5174        if (decimal_point)
5175        {
5176                s[0] = decimal_point; s[1] = '\0';
5177                ret = PyStr_FromString(s);
5178        }
5179        else
5180        {
5181                Py_INCREF(Py_None); ret = Py_None;
5182        }
5183
5184        return ret;
5185}
5186
5187/* set decimal point */
5188static char pgSetDecimalPoint__doc__[] =
5189"set_decimal_point(char) -- set decimal point to be used for money values";
5190
5191static PyObject *
5192pgSetDecimalPoint(PyObject *self, PyObject *args)
5193{
5194        PyObject *ret = NULL;
5195        char *s = NULL;
5196
5197        /* gets arguments */
5198        if (PyArg_ParseTuple(args, "z", &s))
5199        {
5200                if (!s)
5201                        s = "\0";
5202                else if (*s && (*(s+1) || !strchr(".,;: '*/_`|", *s)))
5203                        s = NULL;
5204        }
5205
5206        if (s)
5207        {
5208                decimal_point = *s;
5209                Py_INCREF(Py_None); ret = Py_None;
5210        }
5211        else
5212                PyErr_SetString(PyExc_TypeError,
5213                        "Function set_decimal_mark() expects"
5214                        " a decimal mark character as argument");
5215
5216        return ret;
5217}
5218
5219/* get decimal type */
5220static char pgGetDecimal__doc__[] =
5221"get_decimal() -- get the decimal type to be used for numeric values";
5222
5223static PyObject *
5224pgGetDecimal(PyObject *self, PyObject *noargs)
5225{
5226        PyObject *ret;
5227
5228        ret = decimal ? decimal : Py_None;
5229        Py_INCREF(ret);
5230
5231        return ret;
5232}
5233
5234/* set decimal type */
5235static char pgSetDecimal__doc__[] =
5236"set_decimal(cls) -- set a decimal type to be used for numeric values";
5237
5238static PyObject *
5239pgSetDecimal(PyObject *self, PyObject *cls)
5240{
5241        PyObject *ret = NULL;
5242
5243        if (cls == Py_None)
5244        {
5245                Py_XDECREF(decimal); decimal = NULL;
5246                Py_INCREF(Py_None); ret = Py_None;
5247        }
5248        else if (PyCallable_Check(cls))
5249        {
5250                Py_XINCREF(cls); Py_XDECREF(decimal); decimal = cls;
5251                Py_INCREF(Py_None); ret = Py_None;
5252        }
5253        else
5254                PyErr_SetString(PyExc_TypeError,
5255                        "Function set_decimal() expects"
5256                         " a callable or None as argument");
5257
5258        return ret;
5259}
5260
5261/* get usage of bool values */
5262static char pgGetBool__doc__[] =
5263"get_bool() -- check whether boolean values are converted to bool";
5264
5265static PyObject *
5266pgGetBool(PyObject *self, PyObject *noargs)
5267{
5268        PyObject *ret;
5269
5270        ret = bool_as_text ? Py_False : Py_True;
5271        Py_INCREF(ret);
5272
5273        return ret;
5274}
5275
5276/* set usage of bool values */
5277static char pgSetBool__doc__[] =
5278"set_bool(on) -- set whether boolean values should be converted to bool";
5279
5280static PyObject *
5281pgSetBool(PyObject *self, PyObject *args)
5282{
5283        PyObject *ret = NULL;
5284        int                     i;
5285
5286        /* gets arguments */
5287        if (PyArg_ParseTuple(args, "i", &i))
5288        {
5289                bool_as_text = i ? 0 : 1;
5290                Py_INCREF(Py_None); ret = Py_None;
5291        }
5292        else
5293                PyErr_SetString(PyExc_TypeError,
5294                        "Function set_bool() expects a boolean value as argument");
5295
5296        return ret;
5297}
5298
5299/* get conversion of arrays to lists */
5300static char pgGetArray__doc__[] =
5301"get_array() -- check whether arrays are converted as lists";
5302
5303static PyObject *
5304pgGetArray(PyObject *self, PyObject *noargs)
5305{
5306        PyObject *ret;
5307
5308        ret = array_as_text ? Py_False : Py_True;
5309        Py_INCREF(ret);
5310
5311        return ret;
5312}
5313
5314/* set conversion of arrays to lists */
5315static char pgSetArray__doc__[] =
5316"set_array(on) -- set whether arrays should be converted to lists";
5317
5318static PyObject *
5319pgSetArray(PyObject *self, PyObject *args)
5320{
5321        PyObject *ret = NULL;
5322        int                     i;
5323
5324        /* gets arguments */
5325        if (PyArg_ParseTuple(args, "i", &i))
5326        {
5327                array_as_text = i ? 0 : 1;
5328                Py_INCREF(Py_None); ret = Py_None;
5329        }
5330        else
5331                PyErr_SetString(PyExc_TypeError,
5332                        "Function set_array() expects a boolean value as argument");
5333
5334        return ret;
5335}
5336
5337/* check whether bytea values are unescaped */
5338static char pgGetByteaEscaped__doc__[] =
5339"get_bytea_escaped() -- check whether bytea will be returned escaped";
5340
5341static PyObject *
5342pgGetByteaEscaped(PyObject *self, PyObject *noargs)
5343{
5344        PyObject *ret;
5345
5346        ret = bytea_escaped ? Py_True : Py_False;
5347        Py_INCREF(ret);
5348
5349        return ret;
5350}
5351
5352/* set usage of bool values */
5353static char pgSetByteaEscaped__doc__[] =
5354"set_bytea_escaped(on) -- set whether bytea will be returned escaped";
5355
5356static PyObject *
5357pgSetByteaEscaped(PyObject *self, PyObject *args)
5358{
5359        PyObject *ret = NULL;
5360        int                     i;
5361
5362        /* gets arguments */
5363        if (PyArg_ParseTuple(args, "i", &i))
5364        {
5365                bytea_escaped = i ? 1 : 0;
5366                Py_INCREF(Py_None); ret = Py_None;
5367        }
5368        else
5369                PyErr_SetString(PyExc_TypeError,
5370                        "Function set_bytea_escaped() expects a boolean value as argument");
5371
5372        return ret;
5373}
5374
5375/* get named result factory */
5376static char pgGetNamedresult__doc__[] =
5377"get_namedresult() -- get the function used for getting named results";
5378
5379static PyObject *
5380pgGetNamedresult(PyObject *self, PyObject *noargs)
5381{
5382        PyObject *ret;
5383
5384        ret = namedresult ? namedresult : Py_None;
5385        Py_INCREF(ret);
5386
5387        return ret;
5388}
5389
5390/* set named result factory */
5391static char pgSetNamedresult__doc__[] =
5392"set_namedresult(func) -- set a function to be used for getting named results";
5393
5394static PyObject *
5395pgSetNamedresult(PyObject *self, PyObject *func)
5396{
5397        PyObject *ret = NULL;
5398
5399        if (func == Py_None)
5400        {
5401                Py_XDECREF(namedresult); namedresult = NULL;
5402                Py_INCREF(Py_None); ret = Py_None;
5403        }
5404        else if (PyCallable_Check(func))
5405        {
5406                Py_XINCREF(func); Py_XDECREF(namedresult); namedresult = func;
5407                Py_INCREF(Py_None); ret = Py_None;
5408        }
5409        else
5410                PyErr_SetString(PyExc_TypeError,
5411                        "Function set_namedresult() expects"
5412                         " a callable or None as argument");
5413
5414        return ret;
5415}
5416
5417/* get json decode function */
5418static char pgGetJsondecode__doc__[] =
5419"get_jsondecode() -- get the function used for decoding json results";
5420
5421static PyObject *
5422pgGetJsondecode(PyObject *self, PyObject *noargs)
5423{
5424        PyObject *ret;
5425
5426        ret = jsondecode;
5427        if (!ret)
5428                ret = Py_None;
5429        Py_INCREF(ret);
5430
5431        return ret;
5432}
5433
5434/* set json decode function */
5435static char pgSetJsondecode__doc__[] =
5436"set_jsondecode(func) -- set a function to be used for decoding json results";
5437
5438static PyObject *
5439pgSetJsondecode(PyObject *self, PyObject *func)
5440{
5441        PyObject *ret = NULL;
5442
5443        if (func == Py_None)
5444        {
5445                Py_XDECREF(jsondecode); jsondecode = NULL;
5446                Py_INCREF(Py_None); ret = Py_None;
5447        }
5448        else if (PyCallable_Check(func))
5449        {
5450                Py_XINCREF(func); Py_XDECREF(jsondecode); jsondecode = func;
5451                Py_INCREF(Py_None); ret = Py_None;
5452        }
5453        else
5454                PyErr_SetString(PyExc_TypeError,
5455                        "Function jsondecode() expects"
5456                         " a callable or None as argument");
5457
5458        return ret;
5459}
5460
5461#ifdef DEFAULT_VARS
5462
5463/* gets default host */
5464static char pgGetDefHost__doc__[] =
5465"get_defhost() -- return default database host";
5466
5467static PyObject *
5468pgGetDefHost(PyObject *self, PyObject *noargs)
5469{
5470        Py_XINCREF(pg_default_host);
5471        return pg_default_host;
5472}
5473
5474/* sets default host */
5475static char pgSetDefHost__doc__[] =
5476"set_defhost(string) -- set default database host and return previous value";
5477
5478static PyObject *
5479pgSetDefHost(PyObject *self, PyObject *args)
5480{
5481        char       *temp = NULL;
5482        PyObject   *old;
5483
5484        /* gets arguments */
5485        if (!PyArg_ParseTuple(args, "z", &temp))
5486        {
5487                PyErr_SetString(PyExc_TypeError,
5488                        "Function set_defhost() expects a string or None as argument");
5489                return NULL;
5490        }
5491
5492        /* adjusts value */
5493        old = pg_default_host;
5494
5495        if (temp)
5496                pg_default_host = PyStr_FromString(temp);
5497        else
5498        {
5499                Py_INCREF(Py_None);
5500                pg_default_host = Py_None;
5501        }
5502
5503        return old;
5504}
5505
5506/* gets default base */
5507static char pgGetDefBase__doc__[] =
5508"get_defbase() -- return default database name";
5509
5510static PyObject *
5511pgGetDefBase(PyObject *self, PyObject *noargs)
5512{
5513        Py_XINCREF(pg_default_base);
5514        return pg_default_base;
5515}
5516
5517/* sets default base */
5518static char pgSetDefBase__doc__[] =
5519"set_defbase(string) -- set default database name and return previous value";
5520
5521static PyObject *
5522pgSetDefBase(PyObject *self, PyObject *args)
5523{
5524        char       *temp = NULL;
5525        PyObject   *old;
5526
5527        /* gets arguments */
5528        if (!PyArg_ParseTuple(args, "z", &temp))
5529        {
5530                PyErr_SetString(PyExc_TypeError,
5531                        "Function set_defbase() Argument a string or None as argument");
5532                return NULL;
5533        }
5534
5535        /* adjusts value */
5536        old = pg_default_base;
5537
5538        if (temp)
5539                pg_default_base = PyStr_FromString(temp);
5540        else
5541        {
5542                Py_INCREF(Py_None);
5543                pg_default_base = Py_None;
5544        }
5545
5546        return old;
5547}
5548
5549/* gets default options */
5550static char pgGetDefOpt__doc__[] =
5551"get_defopt() -- return default database options";
5552
5553static PyObject *
5554pgGetDefOpt(PyObject *self, PyObject *noargs)
5555{
5556        Py_XINCREF(pg_default_opt);
5557        return pg_default_opt;
5558}
5559
5560/* sets default opt */
5561static char pgSetDefOpt__doc__[] =
5562"set_defopt(string) -- set default options and return previous value";
5563
5564static PyObject *
5565pgSetDefOpt(PyObject *self, PyObject *args)
5566{
5567        char       *temp = NULL;
5568        PyObject   *old;
5569
5570        /* gets arguments */
5571        if (!PyArg_ParseTuple(args, "z", &temp))
5572        {
5573                PyErr_SetString(PyExc_TypeError,
5574                        "Function set_defopt() expects a string or None as argument");
5575                return NULL;
5576        }
5577
5578        /* adjusts value */
5579        old = pg_default_opt;
5580
5581        if (temp)
5582                pg_default_opt = PyStr_FromString(temp);
5583        else
5584        {
5585                Py_INCREF(Py_None);
5586                pg_default_opt = Py_None;
5587        }
5588
5589        return old;
5590}
5591
5592/* gets default username */
5593static char pgGetDefUser__doc__[] =
5594"get_defuser() -- return default database username";
5595
5596static PyObject *
5597pgGetDefUser(PyObject *self, PyObject *noargs)
5598{
5599        Py_XINCREF(pg_default_user);
5600        return pg_default_user;
5601}
5602
5603/* sets default username */
5604
5605static char pgSetDefUser__doc__[] =
5606"set_defuser(name) -- set default username and return previous value";
5607
5608static PyObject *
5609pgSetDefUser(PyObject *self, PyObject *args)
5610{
5611        char       *temp = NULL;
5612        PyObject   *old;
5613
5614        /* gets arguments */
5615        if (!PyArg_ParseTuple(args, "z", &temp))
5616        {
5617                PyErr_SetString(PyExc_TypeError,
5618                        "Function set_defuser() expects a string or None as argument");
5619                return NULL;
5620        }
5621
5622        /* adjusts value */
5623        old = pg_default_user;
5624
5625        if (temp)
5626                pg_default_user = PyStr_FromString(temp);
5627        else
5628        {
5629                Py_INCREF(Py_None);
5630                pg_default_user = Py_None;
5631        }
5632
5633        return old;
5634}
5635
5636/* sets default password */
5637static char pgSetDefPassword__doc__[] =
5638"set_defpasswd(password) -- set default database password";
5639
5640static PyObject *
5641pgSetDefPassword(PyObject *self, PyObject *args)
5642{
5643        char       *temp = NULL;
5644
5645        /* gets arguments */
5646        if (!PyArg_ParseTuple(args, "z", &temp))
5647        {
5648                PyErr_SetString(PyExc_TypeError,
5649                        "Function set_defpasswd() expects a string or None as argument");
5650                return NULL;
5651        }
5652
5653        if (temp)
5654                pg_default_passwd = PyStr_FromString(temp);
5655        else
5656        {
5657                Py_INCREF(Py_None);
5658                pg_default_passwd = Py_None;
5659        }
5660
5661        Py_INCREF(Py_None);
5662        return Py_None;
5663}
5664
5665/* gets default port */
5666static char pgGetDefPort__doc__[] =
5667"get_defport() -- return default database port";
5668
5669static PyObject *
5670pgGetDefPort(PyObject *self, PyObject *noargs)
5671{
5672        Py_XINCREF(pg_default_port);
5673        return pg_default_port;
5674}
5675
5676/* sets default port */
5677static char pgSetDefPort__doc__[] =
5678"set_defport(port) -- set default port and return previous value";
5679
5680static PyObject *
5681pgSetDefPort(PyObject *self, PyObject *args)
5682{
5683        long int        port = -2;
5684        PyObject   *old;
5685
5686        /* gets arguments */
5687        if ((!PyArg_ParseTuple(args, "l", &port)) || (port < -1))
5688        {
5689                PyErr_SetString(PyExc_TypeError,
5690                        "Function set_deport expects"
5691                         " a positive integer or -1 as argument");
5692                return NULL;
5693        }
5694
5695        /* adjusts value */
5696        old = pg_default_port;
5697
5698        if (port != -1)
5699                pg_default_port = PyInt_FromLong(port);
5700        else
5701        {
5702                Py_INCREF(Py_None);
5703                pg_default_port = Py_None;
5704        }
5705
5706        return old;
5707}
5708#endif /* DEFAULT_VARS */
5709
5710/* cast a string with a text representation of an array to a list */
5711static char pgCastArray__doc__[] =
5712"cast_array(string, cast=None, delim=',') -- cast a string as an array";
5713
5714PyObject *
5715pgCastArray(PyObject *self, PyObject *args, PyObject *dict)
5716{
5717        static const char *kwlist[] = {"string", "cast", "delim", NULL};
5718        PyObject   *string_obj, *cast_obj = NULL, *ret;
5719        char       *string, delim = ',';
5720        Py_ssize_t      size;
5721        int                     encoding;
5722
5723        if (!PyArg_ParseTupleAndKeywords(args, dict, "O|Oc",
5724                        (char **) kwlist, &string_obj, &cast_obj, &delim))
5725                return NULL;
5726
5727        if (PyBytes_Check(string_obj))
5728        {
5729                PyBytes_AsStringAndSize(string_obj, &string, &size);
5730                string_obj = NULL;
5731                encoding = pg_encoding_ascii;
5732        }
5733        else if (PyUnicode_Check(string_obj))
5734        {
5735                string_obj = PyUnicode_AsUTF8String(string_obj);
5736                if (!string_obj) return NULL; /* pass the UnicodeEncodeError */
5737                PyBytes_AsStringAndSize(string_obj, &string, &size);
5738                encoding = pg_encoding_utf8;
5739        }
5740        else
5741        {
5742                PyErr_SetString(PyExc_TypeError,
5743                        "Function cast_array() expects a string as first argument");
5744                return NULL;
5745        }
5746
5747        if (!cast_obj || cast_obj == Py_None)
5748        {
5749                if (cast_obj)
5750                {
5751                        Py_DECREF(cast_obj); cast_obj = NULL;
5752                }
5753        }
5754        else if (!PyCallable_Check(cast_obj))
5755        {
5756                PyErr_SetString(PyExc_TypeError,
5757                        "Function cast_array() expects a callable as second argument");
5758                return NULL;
5759        }
5760
5761        ret = cast_array(string, size, encoding, 0, cast_obj, delim);
5762
5763        Py_XDECREF(string_obj);
5764
5765        return ret;
5766}
5767
5768/* cast a string with a text representation of a record to a tuple */
5769static char pgCastRecord__doc__[] =
5770"cast_record(string, cast=None, delim=',') -- cast a string as a record";
5771
5772PyObject *
5773pgCastRecord(PyObject *self, PyObject *args, PyObject *dict)
5774{
5775        static const char *kwlist[] = {"string", "cast", "delim", NULL};
5776        PyObject   *string_obj, *cast_obj = NULL, *ret;
5777        char       *string, delim = ',';
5778        Py_ssize_t      size, len;
5779        int                     encoding;
5780
5781        if (!PyArg_ParseTupleAndKeywords(args, dict, "O|Oc",
5782                        (char **) kwlist, &string_obj, &cast_obj, &delim))
5783                return NULL;
5784
5785        if (PyBytes_Check(string_obj))
5786        {
5787                PyBytes_AsStringAndSize(string_obj, &string, &size);
5788                string_obj = NULL;
5789                encoding = pg_encoding_ascii;
5790        }
5791        else if (PyUnicode_Check(string_obj))
5792        {
5793                string_obj = PyUnicode_AsUTF8String(string_obj);
5794                if (!string_obj) return NULL; /* pass the UnicodeEncodeError */
5795                PyBytes_AsStringAndSize(string_obj, &string, &size);
5796                encoding = pg_encoding_utf8;
5797        }
5798        else
5799        {
5800                PyErr_SetString(PyExc_TypeError,
5801                        "Function cast_record() expects a string as first argument");
5802                return NULL;
5803        }
5804
5805        if (!cast_obj || PyCallable_Check(cast_obj))
5806        {
5807                len = 0;
5808        }
5809        else if (cast_obj == Py_None)
5810        {
5811                Py_DECREF(cast_obj); cast_obj = NULL; len = 0;
5812        }
5813        else if (PyTuple_Check(cast_obj) || PyList_Check(cast_obj))
5814        {
5815                len = PySequence_Size(cast_obj);
5816                if (!len)
5817                {
5818                        Py_DECREF(cast_obj); cast_obj = NULL;
5819                }
5820        }
5821        else
5822        {
5823                PyErr_SetString(PyExc_TypeError,
5824                        "Function cast_record() expects a callable"
5825                         " or tuple or list of callables as second argument");
5826                return NULL;
5827        }
5828
5829        ret = cast_record(string, size, encoding, 0, cast_obj, len, delim);
5830
5831        Py_XDECREF(string_obj);
5832
5833        return ret;
5834}
5835
5836/* cast a string with a text representation of an hstore to a dict */
5837static char pgCastHStore__doc__[] =
5838"cast_hstore(string) -- cast a string as an hstore";
5839
5840PyObject *
5841pgCastHStore(PyObject *self, PyObject *string)
5842{
5843        PyObject   *tmp_obj = NULL, *ret;
5844        char       *s;
5845        Py_ssize_t      size;
5846        int                     encoding;
5847
5848        if (PyBytes_Check(string))
5849        {
5850                PyBytes_AsStringAndSize(string, &s, &size);
5851                encoding = pg_encoding_ascii;
5852        }
5853        else if (PyUnicode_Check(string))
5854        {
5855                tmp_obj = PyUnicode_AsUTF8String(string);
5856                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
5857                PyBytes_AsStringAndSize(tmp_obj, &s, &size);
5858                encoding = pg_encoding_utf8;
5859        }
5860        else
5861        {
5862                PyErr_SetString(PyExc_TypeError,
5863                        "Function cast_hstore() expects a string as first argument");
5864                return NULL;
5865        }
5866
5867        ret = cast_hstore(s, size, encoding);
5868
5869        Py_XDECREF(tmp_obj);
5870
5871        return ret;
5872}
5873
5874/* List of functions defined in the module */
5875
5876static struct PyMethodDef pgMethods[] = {
5877        {"connect", (PyCFunction) pgConnect, METH_VARARGS|METH_KEYWORDS,
5878                        pgConnect__doc__},
5879        {"escape_string", (PyCFunction) pgEscapeString, METH_O,
5880                        pgEscapeString__doc__},
5881        {"escape_bytea", (PyCFunction) pgEscapeBytea, METH_O,
5882                        pgEscapeBytea__doc__},
5883        {"unescape_bytea", (PyCFunction) pgUnescapeBytea, METH_O,
5884                        pgUnescapeBytea__doc__},
5885        {"get_datestyle", (PyCFunction) pgGetDatestyle, METH_NOARGS,
5886                        pgGetDatestyle__doc__},
5887        {"set_datestyle", (PyCFunction) pgSetDatestyle, METH_VARARGS,
5888                        pgSetDatestyle__doc__},
5889        {"get_decimal_point", (PyCFunction) pgGetDecimalPoint, METH_NOARGS,
5890                        pgGetDecimalPoint__doc__},
5891        {"set_decimal_point", (PyCFunction) pgSetDecimalPoint, METH_VARARGS,
5892                        pgSetDecimalPoint__doc__},
5893        {"get_decimal", (PyCFunction) pgGetDecimal, METH_NOARGS,
5894                        pgGetDecimal__doc__},
5895        {"set_decimal", (PyCFunction) pgSetDecimal, METH_O,
5896                        pgSetDecimal__doc__},
5897        {"get_bool", (PyCFunction) pgGetBool, METH_NOARGS, pgGetBool__doc__},
5898        {"set_bool", (PyCFunction) pgSetBool, METH_VARARGS, pgSetBool__doc__},
5899        {"get_array", (PyCFunction) pgGetArray, METH_NOARGS, pgGetArray__doc__},
5900        {"set_array", (PyCFunction) pgSetArray, METH_VARARGS, pgSetArray__doc__},
5901        {"get_bytea_escaped", (PyCFunction) pgGetByteaEscaped, METH_NOARGS,
5902                pgGetByteaEscaped__doc__},
5903        {"set_bytea_escaped", (PyCFunction) pgSetByteaEscaped, METH_VARARGS,
5904                pgSetByteaEscaped__doc__},
5905        {"get_namedresult", (PyCFunction) pgGetNamedresult, METH_NOARGS,
5906                        pgGetNamedresult__doc__},
5907        {"set_namedresult", (PyCFunction) pgSetNamedresult, METH_O,
5908                        pgSetNamedresult__doc__},
5909        {"get_jsondecode", (PyCFunction) pgGetJsondecode, METH_NOARGS,
5910                        pgGetJsondecode__doc__},
5911        {"set_jsondecode", (PyCFunction) pgSetJsondecode, METH_O,
5912                        pgSetJsondecode__doc__},
5913        {"cast_array", (PyCFunction) pgCastArray, METH_VARARGS|METH_KEYWORDS,
5914                        pgCastArray__doc__},
5915        {"cast_record", (PyCFunction) pgCastRecord, METH_VARARGS|METH_KEYWORDS,
5916                        pgCastRecord__doc__},
5917        {"cast_hstore", (PyCFunction) pgCastHStore, METH_O, pgCastHStore__doc__},
5918
5919#ifdef DEFAULT_VARS
5920        {"get_defhost", pgGetDefHost, METH_NOARGS, pgGetDefHost__doc__},
5921        {"set_defhost", pgSetDefHost, METH_VARARGS, pgSetDefHost__doc__},
5922        {"get_defbase", pgGetDefBase, METH_NOARGS, pgGetDefBase__doc__},
5923        {"set_defbase", pgSetDefBase, METH_VARARGS, pgSetDefBase__doc__},
5924        {"get_defopt", pgGetDefOpt, METH_NOARGS, pgGetDefOpt__doc__},
5925        {"set_defopt", pgSetDefOpt, METH_VARARGS, pgSetDefOpt__doc__},
5926        {"get_defport", pgGetDefPort, METH_NOARGS, pgGetDefPort__doc__},
5927        {"set_defport", pgSetDefPort, METH_VARARGS, pgSetDefPort__doc__},
5928        {"get_defuser", pgGetDefUser, METH_NOARGS, pgGetDefUser__doc__},
5929        {"set_defuser", pgSetDefUser, METH_VARARGS, pgSetDefUser__doc__},
5930        {"set_defpasswd", pgSetDefPassword, METH_VARARGS, pgSetDefPassword__doc__},
5931#endif /* DEFAULT_VARS */
5932        {NULL, NULL} /* sentinel */
5933};
5934
5935static char pg__doc__[] = "Python interface to PostgreSQL DB";
5936
5937static struct PyModuleDef moduleDef = {
5938        PyModuleDef_HEAD_INIT,
5939        "_pg",          /* m_name */
5940        pg__doc__,      /* m_doc */
5941        -1,                     /* m_size */
5942        pgMethods       /* m_methods */
5943};
5944
5945/* Initialization function for the module */
5946MODULE_INIT_FUNC(_pg)
5947{
5948        PyObject   *mod, *dict, *s;
5949
5950        /* Create the module and add the functions */
5951
5952        mod = PyModule_Create(&moduleDef);
5953
5954        /* Initialize here because some Windows platforms get confused otherwise */
5955#if IS_PY3
5956        connType.tp_base = noticeType.tp_base =
5957                queryType.tp_base = sourceType.tp_base = &PyBaseObject_Type;
5958#ifdef LARGE_OBJECTS
5959        largeType.tp_base = &PyBaseObject_Type;
5960#endif
5961#else
5962        connType.ob_type = noticeType.ob_type =
5963                queryType.ob_type = sourceType.ob_type = &PyType_Type;
5964#ifdef LARGE_OBJECTS
5965        largeType.ob_type = &PyType_Type;
5966#endif
5967#endif
5968
5969        if (PyType_Ready(&connType)
5970                || PyType_Ready(&noticeType)
5971                || PyType_Ready(&queryType)
5972                || PyType_Ready(&sourceType)
5973#ifdef LARGE_OBJECTS
5974                || PyType_Ready(&largeType)
5975#endif
5976                ) return NULL;
5977
5978        dict = PyModule_GetDict(mod);
5979
5980        /* Exceptions as defined by DB-API 2.0 */
5981        Error = PyErr_NewException("pg.Error", PyExc_Exception, NULL);
5982        PyDict_SetItemString(dict, "Error", Error);
5983
5984        Warning = PyErr_NewException("pg.Warning", PyExc_Exception, NULL);
5985        PyDict_SetItemString(dict, "Warning", Warning);
5986
5987        InterfaceError = PyErr_NewException("pg.InterfaceError", Error, NULL);
5988        PyDict_SetItemString(dict, "InterfaceError", InterfaceError);
5989
5990        DatabaseError = PyErr_NewException("pg.DatabaseError", Error, NULL);
5991        PyDict_SetItemString(dict, "DatabaseError", DatabaseError);
5992
5993        InternalError = PyErr_NewException("pg.InternalError", DatabaseError, NULL);
5994        PyDict_SetItemString(dict, "InternalError", InternalError);
5995
5996        OperationalError =
5997                PyErr_NewException("pg.OperationalError", DatabaseError, NULL);
5998        PyDict_SetItemString(dict, "OperationalError", OperationalError);
5999
6000        ProgrammingError =
6001                PyErr_NewException("pg.ProgrammingError", DatabaseError, NULL);
6002        PyDict_SetItemString(dict, "ProgrammingError", ProgrammingError);
6003
6004        IntegrityError =
6005                PyErr_NewException("pg.IntegrityError", DatabaseError, NULL);
6006        PyDict_SetItemString(dict, "IntegrityError", IntegrityError);
6007
6008        DataError = PyErr_NewException("pg.DataError", DatabaseError, NULL);
6009        PyDict_SetItemString(dict, "DataError", DataError);
6010
6011        NotSupportedError =
6012                PyErr_NewException("pg.NotSupportedError", DatabaseError, NULL);
6013        PyDict_SetItemString(dict, "NotSupportedError", NotSupportedError);
6014
6015        /* Make the version available */
6016        s = PyStr_FromString(PyPgVersion);
6017        PyDict_SetItemString(dict, "version", s);
6018        PyDict_SetItemString(dict, "__version__", s);
6019        Py_DECREF(s);
6020
6021        /* results type for queries */
6022        PyDict_SetItemString(dict, "RESULT_EMPTY", PyInt_FromLong(RESULT_EMPTY));
6023        PyDict_SetItemString(dict, "RESULT_DML", PyInt_FromLong(RESULT_DML));
6024        PyDict_SetItemString(dict, "RESULT_DDL", PyInt_FromLong(RESULT_DDL));
6025        PyDict_SetItemString(dict, "RESULT_DQL", PyInt_FromLong(RESULT_DQL));
6026
6027        /* transaction states */
6028        PyDict_SetItemString(dict,"TRANS_IDLE",PyInt_FromLong(PQTRANS_IDLE));
6029        PyDict_SetItemString(dict,"TRANS_ACTIVE",PyInt_FromLong(PQTRANS_ACTIVE));
6030        PyDict_SetItemString(dict,"TRANS_INTRANS",PyInt_FromLong(PQTRANS_INTRANS));
6031        PyDict_SetItemString(dict,"TRANS_INERROR",PyInt_FromLong(PQTRANS_INERROR));
6032        PyDict_SetItemString(dict,"TRANS_UNKNOWN",PyInt_FromLong(PQTRANS_UNKNOWN));
6033
6034#ifdef LARGE_OBJECTS
6035        /* create mode for large objects */
6036        PyDict_SetItemString(dict, "INV_READ", PyInt_FromLong(INV_READ));
6037        PyDict_SetItemString(dict, "INV_WRITE", PyInt_FromLong(INV_WRITE));
6038
6039        /* position flags for lo_lseek */
6040        PyDict_SetItemString(dict, "SEEK_SET", PyInt_FromLong(SEEK_SET));
6041        PyDict_SetItemString(dict, "SEEK_CUR", PyInt_FromLong(SEEK_CUR));
6042        PyDict_SetItemString(dict, "SEEK_END", PyInt_FromLong(SEEK_END));
6043#endif /* LARGE_OBJECTS */
6044
6045#ifdef DEFAULT_VARS
6046        /* prepares default values */
6047        Py_INCREF(Py_None);
6048        pg_default_host = Py_None;
6049        Py_INCREF(Py_None);
6050        pg_default_base = Py_None;
6051        Py_INCREF(Py_None);
6052        pg_default_opt = Py_None;
6053        Py_INCREF(Py_None);
6054        pg_default_port = Py_None;
6055        Py_INCREF(Py_None);
6056        pg_default_user = Py_None;
6057        Py_INCREF(Py_None);
6058        pg_default_passwd = Py_None;
6059#endif /* DEFAULT_VARS */
6060
6061        /* store common pg encoding ids */
6062
6063        pg_encoding_utf8 = pg_char_to_encoding("UTF8");
6064        pg_encoding_latin1 = pg_char_to_encoding("LATIN1");
6065        pg_encoding_ascii = pg_char_to_encoding("SQL_ASCII");
6066
6067        /* Check for errors */
6068        if (PyErr_Occurred())
6069                return NULL;
6070
6071        return mod;
6072}
Note: See TracBrowser for help on using the repository browser.